diff --git a/CHANGELOG.md b/CHANGELOG.md index 7257d37b63..3596e31d18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,11 @@ [chipp](https://github.com/chipp) [#5791](https://github.com/realm/SwiftLint/issues/5791) +* The `prefer_type_checking` rule will no longer trigger for non-optional + type casting (`as`), or for comparisons to optional types. + [Martin Redington](https://github.com/mildm8nnered) + [#5802](https://github.com/realm/SwiftLint/issues/5802) + ## 0.57.0: Squeaky Clean Cycle #### Breaking diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferTypeCheckingRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferTypeCheckingRule.swift index c0ae6731d7..49bd78af04 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferTypeCheckingRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferTypeCheckingRule.swift @@ -24,6 +24,8 @@ struct PreferTypeCheckingRule: Rule { foo.run() } """), + Example("bar as Foo? != nil"), + Example("bar as? Foo? != nil"), ], triggeringExamples: [ Example("bar ↓as? Foo != nil"), @@ -53,7 +55,7 @@ struct PreferTypeCheckingRule: Rule { private extension PreferTypeCheckingRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: InfixOperatorExprSyntax) { - if node.typeChecksWithAsCasting, let asExpr = node.leftOperand.as(AsExprSyntax.self) { + if let asExpr = node.asExprWithOptionalTypeChecking { violations.append(asExpr.asKeyword.positionAfterSkippingLeadingTrivia) } } @@ -61,8 +63,7 @@ private extension PreferTypeCheckingRule { final class Rewriter: ViolationsSyntaxRewriter { override func visit(_ node: InfixOperatorExprSyntax) -> ExprSyntax { - guard node.typeChecksWithAsCasting, - let asExpr = node.leftOperand.as(AsExprSyntax.self) else { + guard let asExpr = node.asExprWithOptionalTypeChecking else { return super.visit(node) } @@ -79,9 +80,15 @@ private extension PreferTypeCheckingRule { } private extension InfixOperatorExprSyntax { - var typeChecksWithAsCasting: Bool { - self.leftOperand.is(AsExprSyntax.self) - && self.operator.as(BinaryOperatorExprSyntax.self)?.operator.tokenKind == .binaryOperator("!=") - && self.rightOperand.is(NilLiteralExprSyntax.self) + var asExprWithOptionalTypeChecking: AsExprSyntax? { + if let asExpr = leftOperand.as(AsExprSyntax.self), + asExpr.questionOrExclamationMark?.tokenKind == .postfixQuestionMark, + asExpr.type.is(OptionalTypeSyntax.self) == false, + self.operator.as(BinaryOperatorExprSyntax.self)?.operator.tokenKind == .binaryOperator("!="), + rightOperand.is(NilLiteralExprSyntax.self) { + asExpr + } else { + nil + } } }