Skip to content

Commit

Permalink
Skip defer statements in #if block if it is not itself the last s…
Browse files Browse the repository at this point in the history
…tatement (realm#4617)
  • Loading branch information
SimplyDanny authored Dec 6, 2022
1 parent 4adabd8 commit 609418f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 5 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
[SimplyDanny](https://github.com/SimplyDanny)
[#4612](https://github.com/realm/SwiftLint/issues/4612)

* Skip `defer` statements being last in an `#if` block if the `#if` statement is
not itself the last statement in a block.
[SimplyDanny](https://github.com/SimplyDanny)
[#4615](https://github.com/realm/SwiftLint/issues/4615)

* Fix false positives in `empty_enum_arguments` when the called expression
is an identifier or an init call.
[Steffen Matthischke](https://github.com/heeaad)
Expand Down
48 changes: 43 additions & 5 deletions Source/SwiftLintFramework/Rules/Lint/InertDeferRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,17 @@ struct InertDeferRule: ConfigurationProviderRule, SwiftSyntaxRule {
print("other code")
}
}
""")
"""),
Example("""
func f() {
#if os(macOS)
defer { print(2) }
#else
defer { print(3) }
#endif
print(1)
}
""", excludeFromDocumentation: true)
],
triggeringExamples: [
Example("""
Expand All @@ -46,7 +56,23 @@ struct InertDeferRule: ConfigurationProviderRule, SwiftSyntaxRule {
// comment
}
}
""")
"""),
Example("""
func f(arg: Int) {
if arg == 1 {
↓defer { print(2) }
// a comment
} else {
↓defer { print(3) }
}
print(1)
#if os(macOS)
↓defer { print(4) }
#else
↓defer { print(5) }
#endif
}
""", excludeFromDocumentation: true)
]
)

Expand All @@ -58,13 +84,25 @@ struct InertDeferRule: ConfigurationProviderRule, SwiftSyntaxRule {
private extension InertDeferRule {
final class Visitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: DeferStmtSyntax) {
guard let codeBlockItem = node.parent?.as(CodeBlockItemSyntax.self),
let codeBlockList = codeBlockItem.parent?.as(CodeBlockItemListSyntax.self),
codeBlockList.last == codeBlockItem else {
guard node.isLastStatement else {
return
}
if let ifConfigClause = node.parent?.parent?.parent?.as(IfConfigClauseSyntax.self),
ifConfigClause.parent?.parent?.isLastStatement == false {
return
}

violations.append(node.deferKeyword.positionAfterSkippingLeadingTrivia)
}
}
}

private extension SyntaxProtocol {
var isLastStatement: Bool {
if let codeBlockItem = parent?.as(CodeBlockItemSyntax.self),
let codeBlockList = codeBlockItem.parent?.as(CodeBlockItemListSyntax.self) {
return codeBlockList.last == codeBlockItem
}
return false
}
}

0 comments on commit 609418f

Please sign in to comment.