From 325c4ff24a09c60012b73ef94e8dac3cc61b077e Mon Sep 17 00:00:00 2001 From: Jared Grubb Date: Sat, 26 Oct 2024 13:00:13 -0700 Subject: [PATCH 1/3] RedundantTypeAnnotation: add 'ignore_type_interfaces' option The `redundant_type_annotation` and `explicit_type_interface` rules conflict. For users that want to have an explicit type interface, but still be able to write simple code inside the bodies of functions, I want to add an option to `redundant_type_annotation` that has it ignore "type interfaces". For example, this allows: ``` struct Foo { var bar: Bar = Bar() // OK: ignore this! I want explicit types on interfaces. func baz() { let bar: Bar = Bar() // WARN: redundant_type_annotation kicks in here though. } } ``` --- CHANGELOG.md | 6 ++++ .../RedundantTypeAnnotationRule.swift | 29 ++++++++++++++++++- ...RedundantTypeAnnotationConfiguration.swift | 2 ++ .../default_rule_configurations.yml | 1 + 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfdf749b3a..3e3990ed91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,12 @@ command line option. [Martin Redington](https://github.com/mildm8nnered) [#5801](https://github.com/realm/SwiftLint/issues/5801) +* The `redundant_type_annotation` rule gains a new option, + `ignore_type_interfaces`, that skips enforcement on members in a + type declaration (like a `struct`). This helps the rule coexist with + the `explicit_type_interface` rule that requires such redundancy. + [jaredgrubb](https://github.com/jaredgrubb) + [#3750](https://github.com/realm/SwiftLint/issues/3750) #### Bug Fixes diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift index 019ff40ac0..1017cdefdb 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift @@ -57,6 +57,12 @@ struct RedundantTypeAnnotationRule: OptInRule, SwiftSyntaxCorrectableRule { Example("var dbl: Double = 0.0"), Example("var int: Int = 0"), Example("var str: String = \"str\""), + Example(""" + struct Foo { + var url: URL = URL() + let myVar: Int? = 0, s: String = "" + } + """, configuration: ["ignore_type_interfaces": true]), ], triggeringExamples: [ Example("var url↓:URL=URL()"), @@ -88,6 +94,13 @@ struct RedundantTypeAnnotationRule: OptInRule, SwiftSyntaxCorrectableRule { } } """), + Example(""" + class ViewController: UIViewController { + func someMethod() { + let myVar↓: Int = Int(5) + } + } + """, configuration: ["ignore_type_interfaces": true]), Example("let a↓: [Int] = [Int]()"), Example("let a↓: A.B = A.B()"), Example(""" @@ -183,7 +196,7 @@ private extension RedundantTypeAnnotationRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: PatternBindingSyntax) { if let varDecl = node.parent?.parent?.as(VariableDeclSyntax.self), - configuration.ignoreAttributes.allSatisfy({ !varDecl.attributes.contains(attributeNamed: $0) }), + !configuration.shouldSkipRuleCheck(for: varDecl), let typeAnnotation = node.typeAnnotation, let initializer = node.initializer?.value { collectViolation(forType: typeAnnotation, withInitializer: initializer) @@ -261,3 +274,17 @@ private extension SyntaxKind { } } } + +extension RedundantTypeAnnotationConfiguration { + func shouldSkipRuleCheck(for varDecl: VariableDeclSyntax) -> Bool { + if ignoreAttributes.contains(where: { varDecl.attributes.contains(attributeNamed: $0) }) { + return true + } + if ignoreTypeInterfaces, + let parentNode = varDecl.parent, + parentNode.as(CodeBlockItemSyntax.self) == nil { + return true + } + return false + } +} diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift index 3eb9596298..e354d3b9a4 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift @@ -8,6 +8,8 @@ struct RedundantTypeAnnotationConfiguration: SeverityBasedRuleConfiguration { var severityConfiguration = SeverityConfiguration(.warning) @ConfigurationElement(key: "ignore_attributes") var ignoreAttributes = Set(["IBInspectable"]) + @ConfigurationElement(key: "ignore_type_interfaces") + private(set) var ignoreTypeInterfaces = false @ConfigurationElement(key: "consider_default_literal_types_redundant") private(set) var considerDefaultLiteralTypesRedundant = false } diff --git a/Tests/IntegrationTests/default_rule_configurations.yml b/Tests/IntegrationTests/default_rule_configurations.yml index 57148068b8..ce295d9674 100644 --- a/Tests/IntegrationTests/default_rule_configurations.yml +++ b/Tests/IntegrationTests/default_rule_configurations.yml @@ -473,6 +473,7 @@ redundant_string_enum_value: redundant_type_annotation: severity: warning ignore_attributes: ["IBInspectable"] + ignore_type_interfaces: false consider_default_literal_types_redundant: false redundant_void_return: severity: warning From a81abc516e157a7a4e1a240238eee9ca9270a986 Mon Sep 17 00:00:00 2001 From: Jared Grubb Date: Fri, 8 Nov 2024 16:51:12 -0800 Subject: [PATCH 2/3] - address review comments --- CHANGELOG.md | 5 +++-- .../Idiomatic/RedundantTypeAnnotationRule.swift | 12 ++++-------- .../RedundantTypeAnnotationConfiguration.swift | 4 ++-- .../IntegrationTests/default_rule_configurations.yml | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e3990ed91..3be513f1c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,10 +25,11 @@ command line option. [Martin Redington](https://github.com/mildm8nnered) [#5801](https://github.com/realm/SwiftLint/issues/5801) + * The `redundant_type_annotation` rule gains a new option, - `ignore_type_interfaces`, that skips enforcement on members in a + `ignore_properties`, that skips enforcement on members in a type declaration (like a `struct`). This helps the rule coexist with - the `explicit_type_interface` rule that requires such redundancy. + the `explicit_type_interface` rule that requires such redundancy. [jaredgrubb](https://github.com/jaredgrubb) [#3750](https://github.com/realm/SwiftLint/issues/3750) diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift index 1017cdefdb..ac7b3047bc 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantTypeAnnotationRule.swift @@ -62,7 +62,7 @@ struct RedundantTypeAnnotationRule: OptInRule, SwiftSyntaxCorrectableRule { var url: URL = URL() let myVar: Int? = 0, s: String = "" } - """, configuration: ["ignore_type_interfaces": true]), + """, configuration: ["ignore_properties": true]), ], triggeringExamples: [ Example("var url↓:URL=URL()"), @@ -100,7 +100,7 @@ struct RedundantTypeAnnotationRule: OptInRule, SwiftSyntaxCorrectableRule { let myVar↓: Int = Int(5) } } - """, configuration: ["ignore_type_interfaces": true]), + """, configuration: ["ignore_properties": true]), Example("let a↓: [Int] = [Int]()"), Example("let a↓: A.B = A.B()"), Example(""" @@ -280,11 +280,7 @@ extension RedundantTypeAnnotationConfiguration { if ignoreAttributes.contains(where: { varDecl.attributes.contains(attributeNamed: $0) }) { return true } - if ignoreTypeInterfaces, - let parentNode = varDecl.parent, - parentNode.as(CodeBlockItemSyntax.self) == nil { - return true - } - return false + + return ignoreProperties && varDecl.parent?.is(MemberBlockItemSyntax.self) == true } } diff --git a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift index e354d3b9a4..7bb54dacfa 100644 --- a/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift +++ b/Source/SwiftLintBuiltInRules/Rules/RuleConfigurations/RedundantTypeAnnotationConfiguration.swift @@ -8,8 +8,8 @@ struct RedundantTypeAnnotationConfiguration: SeverityBasedRuleConfiguration { var severityConfiguration = SeverityConfiguration(.warning) @ConfigurationElement(key: "ignore_attributes") var ignoreAttributes = Set(["IBInspectable"]) - @ConfigurationElement(key: "ignore_type_interfaces") - private(set) var ignoreTypeInterfaces = false + @ConfigurationElement(key: "ignore_properties") + private(set) var ignoreProperties = false @ConfigurationElement(key: "consider_default_literal_types_redundant") private(set) var considerDefaultLiteralTypesRedundant = false } diff --git a/Tests/IntegrationTests/default_rule_configurations.yml b/Tests/IntegrationTests/default_rule_configurations.yml index ce295d9674..f9014e5743 100644 --- a/Tests/IntegrationTests/default_rule_configurations.yml +++ b/Tests/IntegrationTests/default_rule_configurations.yml @@ -473,7 +473,7 @@ redundant_string_enum_value: redundant_type_annotation: severity: warning ignore_attributes: ["IBInspectable"] - ignore_type_interfaces: false + ignore_properties: false consider_default_literal_types_redundant: false redundant_void_return: severity: warning From ecb3500727c3ee1f2dec120ff05e81c313920774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= Date: Tue, 12 Nov 2024 20:06:14 +0100 Subject: [PATCH 3/3] Retrigger build