Stop triggering `unused_capture_list` on variables referenced in optional bindings

This commit is contained in:
Danny Mösch 2023-03-12 13:50:58 +01:00
parent 7ac128c83d
commit fb89ab2fb5
2 changed files with 37 additions and 2 deletions

View File

@ -147,6 +147,11 @@
[SimplyDanny](https://github.com/SimplyDanny)
[#4548](https://github.com/realm/SwiftLint/issues/4548)
* Stop triggering `unused_capture_list` on captured variable that is only
referenced by a shorthand optional binding (`if let capturedVar { ... }`).
[SimplyDanny](https://github.com/SimplyDanny)
[#4804](https://github.com/realm/SwiftLint/issues/4804)
* Ensure that negative literals in initializers do not trigger
`no_magic_numbers` rule.
[SimplyDanny](https://github.com/SimplyDanny)

View File

@ -91,6 +91,14 @@ struct UnusedCaptureListRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInR
rx.onViewDidAppear.subscribe(onNext: { [unowned self] in
doSomething()
}).disposed(by: disposeBag)
"""),
Example("""
let closure = { [weak self] in
guard let self else {
return
}
someInstanceFunction()
}
""")
],
triggeringExamples: [
@ -128,7 +136,16 @@ struct UnusedCaptureListRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInR
}
}
"""),
Example("{ [↓foo] in _ }()")
Example("{ [↓foo] in _ }()"),
Example("""
let closure = { [weak a] in
// The new `a` immediatly shadows the captured `a` which thus isn't needed.
guard let a = getOptionalValue() else {
return
}
someInstanceFunction()
}
""")
]
)
@ -199,7 +216,20 @@ private final class IdentifierReferenceVisitor: SyntaxVisitor {
}
override func visitPost(_ node: IdentifierExprSyntax) {
let name = node.identifier.text
collectReference(by: node.identifier)
}
override func visitPost(_ node: IdentifierPatternSyntax) {
// Optional bindings without an initializer like `if let self { ... }` reference the captured `self`
// implicitly. This is handled in here. If we have `if let self = self { ... }` the initializer `self`
// is handled in the `IdentifierExprSyntax` case above.
if let binding = node.parent?.as(OptionalBindingConditionSyntax.self), binding.initializer == nil {
collectReference(by: node.identifier)
}
}
private func collectReference(by token: TokenSyntax) {
let name = token.text
if identifiersToSearch.contains(name) {
foundIdentifiers.insert(name)
}