diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c01a45ecb..56955c722f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,10 @@ ### Enhancements -* None. +* Exclude types with a `@Suite` attribute and functions annotated with `@Test` from `no_magic_numbers` rule. + Also treat a type as a `@Suite` if it contains `@Test` functions. + [SimplyDanny](https://github.com/SimplyDanny) + [#5964](https://github.com/realm/SwiftLint/issues/5964) ### Bug Fixes diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/NoMagicNumbersRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/NoMagicNumbersRule.swift index 7cf3157800..8c5e6da19b 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/NoMagicNumbersRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/NoMagicNumbersRule.swift @@ -81,9 +81,26 @@ struct NoMagicNumbersRule: Rule { Example("let (lowerBound, upperBound) = (400, 599)"), Example("let a = (5, 10)"), Example("let notFound = (statusCode: 404, description: \"Not Found\", isError: true)"), + Example("#Preview { ContentView(value: 5) }"), + Example("@Test func f() { let _ = 2 + 2 }"), Example(""" - #Preview { - ContentView(value: 5) + @Suite struct Test { + @Test func f() { + func g() { let _ = 2 + 2 } + let _ = 2 + 2 + } + } + """), + Example(""" + @Suite actor Test { + private var a: Int { 2 } + @Test func f() { let _ = 2 + a } + } + """), + Example(""" + class Test { // @Suite implicitly + private var a: Int { 2 } + @Test func f() { let _ = 2 + a } } """), ], @@ -127,12 +144,12 @@ private extension NoMagicNumbersRule { private var nonTestClasses: Set = [] private var possibleViolations: [String: Set] = [:] - override func visit(_ node: PatternBindingSyntax) -> SyntaxVisitorContinueKind { - node.isSimpleTupleAssignment ? .skipChildren : .visitChildren + override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { + node.isTestSuite ? .skipChildren : .visitChildren } - override func visit(_ node: MacroExpansionExprSyntax) -> SyntaxVisitorContinueKind { - node.macroName.text == "Preview" ? .skipChildren : .visitChildren + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + node.isTestSuite ? .skipChildren : .visitChildren } override func visitPost(_ node: ClassDeclSyntax) { @@ -145,6 +162,10 @@ private extension NoMagicNumbersRule { } } + override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { + node.isTestSuite ? .skipChildren : .visitChildren + } + override func visitPost(_ node: FloatLiteralExprSyntax) { guard node.literal.isMagicNumber else { return @@ -152,6 +173,10 @@ private extension NoMagicNumbersRule { collectViolation(forNode: node) } + override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + node.attributes.contains(attributeNamed: "Test") ? .skipChildren : .visitChildren + } + override func visitPost(_ node: IntegerLiteralExprSyntax) { guard node.literal.isMagicNumber else { return @@ -159,6 +184,18 @@ private extension NoMagicNumbersRule { collectViolation(forNode: node) } + override func visit(_ node: MacroExpansionExprSyntax) -> SyntaxVisitorContinueKind { + node.macroName.text == "Preview" ? .skipChildren : .visitChildren + } + + override func visit(_ node: PatternBindingSyntax) -> SyntaxVisitorContinueKind { + node.isSimpleTupleAssignment ? .skipChildren : .visitChildren + } + + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + node.isTestSuite ? .skipChildren : .visitChildren + } + private func collectViolation(forNode node: some ExprSyntaxProtocol) { if node.isMemberOfATestClass(configuration.testParentClasses) { return @@ -190,6 +227,17 @@ private extension NoMagicNumbersRule { } } +private extension DeclGroupSyntax { + var isTestSuite: Bool { + if attributes.contains(attributeNamed: "Suite") { + return true + } + return memberBlock.members.contains { + $0.decl.as(FunctionDeclSyntax.self)?.attributes.contains(attributeNamed: "Test") == true + } + } +} + private extension TokenSyntax { var isMagicNumber: Bool { guard let number = Double(text.replacingOccurrences(of: "_", with: "")) else {