-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SourceKit/CodeFormat] Re-work and improve the indentation implementation #30187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@swift-ci please test |
Build failed |
Wow, that’s a lot of radars! |
@swift-ci please test |
Build failed |
Build failed |
@swift-ci please test |
Build failed |
Build failed |
bf5bafe
to
9fce6ac
Compare
@swift-ci please test |
Build failed |
Build failed |
@swift-ci Please test |
lib/Parse/ParseExpr.cpp
Outdated
@@ -568,9 +559,12 @@ ParserResult<Expr> Parser::parseExprKeyPath() { | |||
|
|||
// FIXME: diagnostics | |||
ParserResult<Expr> rootResult, pathResult; | |||
Optional<ParserStatus> parseStatus; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can simply use ParserStatus parseStatus
here. The default is success. What I was talking is that ParserResult
cannot be success without the value. But ParserStatus
can have simple "success" value.
Build failed |
Build failed |
@swift-ci please test |
Build failed |
Build failed |
Failures seem unrelated. |
@swift-ci please smoke test OS X Platform |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, this is a big patch. So far I've reviewed everything except the million overloads of FormatWalker:: getIndentContextFrom
, of which I've sampled a handful of cases. Overall, I think the approach you've taken is better and more understandable than the previous version, and I'm happy with the overall structure. On the other hand it's not really possible to review every path here.
…tion. This restructures the indentation logic around producing a single IndentContext for the line being indented. An IndentContext has: - a ContextLoc, which points to a source location to indent relative to, - a Kind, indicating whether we should align with that location exactly, or with the start of the content on its containing line, and - an IndentLevel with the relative number of levels to indent by. It also improves the handling of: - chained and nested parens, braces, square brackets and angle brackets, and how those interact with the exact alignment of parameters, call arguments, and tuple, array and dictionary elements. - Indenting to the correct level after an incomplete expression, statement or decl. Resolves: rdar://problem/59135010 rdar://problem/25519439 rdar://problem/50137394 rdar://problem/48410444 rdar://problem/48643521 rdar://problem/42171947 rdar://problem/40130724 rdar://problem/41405163 rdar://problem/39367027 rdar://problem/36332430 rdar://problem/34464828 rdar://problem/33113738 rdar://problem/32314354 rdar://problem/30106520 rdar://problem/29773848 rdar://problem/27301544 rdar://problem/27776466 rdar://problem/27230819 rdar://problem/25490868 rdar://problem/23482354 rdar://problem/20193017 rdar://problem/47117735 rdar://problem/55950781 rdar://problem/55939440 rdar://problem/53247352 rdar://problem/54326612 rdar://problem/53131527 rdar://problem/48399673 rdar://problem/51361639 rdar://problem/58285950 rdar://problem/58286076 rdar://problem/53828204 rdar://problem/58286182 rdar://problem/58504167 rdar://problem/58286327 rdar://problem/53828026 rdar://problem/57623821 rdar://problem/56965360 rdar://problem/54470937 rdar://problem/55580761 rdar://problem/46928002 rdar://problem/35807378 rdar://problem/39397252 rdar://problem/26692035 rdar://problem/33760223 rdar://problem/48934744 rdar://problem/43315903 rdar://problem/24630624
…status correctly. We were always dropping the error status when returning from parseExprImpl. We were also incorrectly keeping error status after recovering by finding the right close token in parseList. This change fixes both, and also updates a few callers of parseList that assumed when they reported a failure parsing an element the list as a whole would get error status, which isn't true due to recovery.
…ontextLocs. - Rename several symbols to make it clearer whether the ranges they deal with are open or closed. - Add comments documenting the implementation of OutdentChecker::hasOutdent - Fix a bug where code after a doc coment block of the '/**' style was being indented 1 space. - Fix IsInStringLiteral not being set if the indent target was in a string segment of an interpolated multiline string. - Update OutdentChecker::hasOutdent to propagate indent contexts from parent parens/brackets/braces to child parens/brackets/braces that start later in the same line (like FormatWalker already does). This changes the braces in the example below to 'inherit' a ContextLoc from their parent square brackets, which have a ContextLoc at 'foo'. This makes the whole expression be correctly considered 'outdenting': foo(a: "hello" b: "hello")[x: { print("hello") }]
@swift-ci please smoke test |
It looks like the swiftpm test failure is related and due to the parser changes. The test parses the code below and checks the reported diagnostic for
Prior to my parser changes it produced:
And after:
I think this is because when parsing the tuple arg of Based on that it seems like the new behavior is desirable. @rintaro, do you agree? Should I just update the swiftpm test? |
I agree. Let's update the spm test. |
…a diagnostic it was checking for. The test parses the code below and checks for a "expected ')' in expression list" diagnostic: ``` import PackageDescription let package = Package( name: "Trivial", targets: [ .target( name: "foo", dependencies: []), ) ``` Prior to the parser fix the invalid collection literal failed to parse but the error status wasn't propagated up to the containing argument list parsing code, so it produced an additional (and undesirable) missing right token diagnostic that this test was checking for. /tmp/t.swift:9:1: error: expected expression in container literal ) ^ /tmp/t.swift:9:2: error: expected ')' in expression list ) ^ /tmp/t.swift:2:22: note: to match this opening '(' let package = Package( ^ Afer the parser fix in swiftlang/swift#30187, we only report the first container literal error and suppress the rest: /tmp/t.swift:9:1: error: expected expression in container literal ) ^
if (!isInCheckRange(L, R)) | ||
return true; | ||
|
||
// The CheckRange is made outdenting by any parens/braces/brackets with: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is still complicated, but the examples help a lot to get a feeling for how it works!
} | ||
|
||
Optional<Trailing> | ||
checkForTrailingTarget(SourceLoc End) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found the terminology "Trailing" hard to keep straight, since we have trailing closures, trailing where clauses, trailing targets ie. "Trailing". Would it be correct to call this something like PostTokenTarget
? Maybe "trailing" is the right word, but given how overloaded it is, it would be nice if we could find the most specific term here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'Token' part isn't quite right, since it can just be an empty line between two tokens. Do you mean "Trailing" specifically or the "TrailingTarget" term in general?
…opagate ContextLocs when necessary. We don't actually need to set a ContextOverride unless the ContextLoc and L paren/brace/bracket are on different lines. Combined with the fact that we only set them if the L and R parens/braces/brackets are on different lines to, it guarantees there will be at most one override that's applicable on any given line, which lets us simplify the logic somewhat.
@swift-ci please test |
Build failed |
Build failed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I reviewed the most recent changes, scanned through the many specific indentation context sources, did a few more in-depth looks at specific cases in a debugger, and reviewed the new tests. We can discuss the "Trailing" terminology, but it shouldn't block the PR. Thanks!
This was a huge PR, so thanks a lot for going through it all @benlangmuir. I'll do another run of the stress tester over the full compat suite (with just the format request enabled) to make sure the last two changes didn't break anything, and do a normal source compat run too just in case the parser changes somehow affect something before I merge. |
@swift-ci Please Test Source Compatibility |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parser changes look good!
This restructures the indentation logic around producing a single
IndentContext
for the line being indented. An
IndentContext
has:ContextLoc
, which points to a source location to indent relative toKind
, indicating whether we should indent relative to that location exactly or to the start of the content on its containing line, andIndentLevel
with the relative number of levels to indent by.It also improves the handling of:
Resolves:
rdar://problem/59135010
rdar://problem/25519439
rdar://problem/50137394
rdar://problem/48410444
rdar://problem/48643521
rdar://problem/42171947
rdar://problem/40130724
rdar://problem/41405163
rdar://problem/39367027
rdar://problem/36332430
rdar://problem/34464828
rdar://problem/33113738
rdar://problem/32314354
rdar://problem/30106520
rdar://problem/29773848
rdar://problem/27301544
rdar://problem/27776466
rdar://problem/27230819
rdar://problem/25490868
rdar://problem/23482354
rdar://problem/20193017
rdar://problem/47117735
rdar://problem/55950781
rdar://problem/55939440
rdar://problem/53247352
rdar://problem/54326612
rdar://problem/53131527
rdar://problem/48399673
rdar://problem/51361639
rdar://problem/58285950
rdar://problem/58286076
rdar://problem/53828204
rdar://problem/58286182
rdar://problem/58504167
rdar://problem/58286327
rdar://problem/53828026
rdar://problem/57623821
rdar://problem/56965360
rdar://problem/54470937
rdar://problem/55580761
rdar://problem/46928002
rdar://problem/35807378
rdar://problem/39397252
rdar://problem/26692035
rdar://problem/33760223
rdar://problem/48934744
rdar://problem/43315903
rdar://problem/24630624