-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Migrate VerticalWhitespaceOpeningBracesRule to SwiftSyntax #6119
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
base: main
Are you sure you want to change the base?
Migrate VerticalWhitespaceOpeningBracesRule to SwiftSyntax #6119
Conversation
27e3c77
to
b690c0c
Compare
Generated by 🚫 Danger |
78d1b0c
to
ea4a254
Compare
## Summary Convert VerticalWhitespaceOpeningBracesRule to use SwiftSyntax instead of SourceKit for improved performance and better detection of empty lines after opening braces. ## Key Technical Improvements - **Enhanced trivia analysis** for accurate empty line detection after opening braces - **Proper handling of closure "in" keywords** with context-aware detection - **Improved correction logic** handling all newline types (LF, CR, CRLF) consistently - **SwiftSyntax visitor pattern** replacing regex-based detection for better accuracy - **Comprehensive token analysis** supporting all opening brace types (`{`, `[`, `(`) - **Accurate position tracking** for violation start and end positions ## Migration Details - Replaced `CorrectableRule, OptInRule` with `@SwiftSyntaxRule(correctable: true, optIn: true)` - Implemented `ViolationsSyntaxVisitor` for detecting violations in token trailing trivia - Implemented `ViolationsSyntaxRewriter` for correcting violations across different syntax contexts - Added proper handling of closures, code blocks, arrays, and tuples - Maintained exact position reporting for violation locations - Preserved all existing test cases and rule behavior
ea4a254
to
af63388
Compare
Rebased to get the better summary. |
The difference to the previous implementation are examples like func f() { // comment
} with comments after the opening brace. They trigger now. Another difference is when the f { foo,
bar in
} The previous implementation didn't trigger on the empty line, the new implementation does. I think that both cases are acceptable without introducing an option since there are only ~20 examples of either nature in the scanned repositories. |
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.
It's a bit irritating that the rule triggers on the opening brace in all cases except for closures where it triggers on the empty line. We should harmonize that (probably in a separate change afterwards).
} | ||
} | ||
|
||
private extension TriviaPiece { |
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.
We should move this to SwiftSyntax+SwiftLint.swift
and reused it in other rules.
} | ||
|
||
private extension VerticalWhitespaceOpeningBracesRule { | ||
final class Visitor: ViolationsSyntaxVisitor<SeverityConfiguration<VerticalWhitespaceOpeningBracesRule>> { |
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.
final class Visitor: ViolationsSyntaxVisitor<SeverityConfiguration<VerticalWhitespaceOpeningBracesRule>> { | |
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> { |
} | ||
} | ||
|
||
final class Rewriter: ViolationsSyntaxRewriter<SeverityConfiguration<VerticalWhitespaceOpeningBracesRule>> { |
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.
final class Rewriter: ViolationsSyntaxRewriter<SeverityConfiguration<VerticalWhitespaceOpeningBracesRule>> { | |
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> { |
if let firstStatement = node.statements.first { | ||
let leadingTrivia = firstStatement.leadingTrivia | ||
let correctedTrivia = correctTrivia(trivia: leadingTrivia) | ||
if correctedTrivia.hasCorrections { | ||
numberOfCorrections += correctedTrivia.correctionCount | ||
var newStatements = node.statements | ||
newStatements[newStatements.startIndex] = firstStatement | ||
.with(\.leadingTrivia, correctedTrivia.trivia) | ||
return node.with(\.statements, newStatements) | ||
} | ||
} | ||
return super.visit(node) |
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.
These blocks look all very similar. Common parts could be extracted into a method.
// Comment explaining the logic | ||
performAction() | ||
} | ||
"""), |
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 tried with another example:
if x == 5 { // comment
print("x is 5")
}
The violation triggers at the comment and the correction removes on of the leading slashes //
.
} | ||
} | ||
|
||
final class Rewriter: ViolationsSyntaxRewriter<SeverityConfiguration<VerticalWhitespaceOpeningBracesRule>> { |
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 rewriter is currently not used at all since the visitor does the replacement already and the rule doesn't specify explicitRewriter: true
.
Summary
Convert VerticalWhitespaceOpeningBracesRule to use SwiftSyntax instead
of SourceKit for improved performance and better detection of empty
lines after opening braces.
Key Technical Improvements
opening braces
detection
CRLF) consistently
better accuracy
(
{
,[
,(
)Migration Details
CorrectableRule, OptInRule
with@SwiftSyntaxRule(correctable: true, optIn: true)
ViolationsSyntaxVisitor
for detecting violations intoken trailing trivia
ViolationsSyntaxRewriter
for correcting violationsacross different syntax contexts