Skip to content

Commit

Permalink
Ignore no magic numbers violations if they are in an extension of a t…
Browse files Browse the repository at this point in the history
…est class (only works in the same file)
  • Loading branch information
mildm8nnered committed Jul 30, 2023
1 parent b3189aa commit d423c44
Showing 1 changed file with 80 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ struct NoMagicNumbersRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule
let bar = array[42]
}
}
"""),
Example("""
class FooTests: XCTestCase {
let baz: [Int] = Array(repeating: 0, count: 10)
}
extension FooTests {
class Bar {
let baz: [Int] = Array(repeating: 0, count: 10)
}
}
"""),
Example("""
extension FooTests {
class Bar {
let baz: [Int] = Array(repeating: 0, count: 10)
}
}
class FooTests: XCTestCase {
let baz: [Int] = Array(repeating: 0, count: 10)
}
""")
],
triggeringExamples: [
Expand All @@ -76,22 +98,65 @@ struct NoMagicNumbersRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderRule
private extension NoMagicNumbersRule {
final class Visitor: ViolationsSyntaxVisitor {
private let testParentClasses: Set<String>
private var testClasses: Set<String> = []
private var nonTestClasses: Set<String> = []
private var possibleViolations: [String: [ReasonedRuleViolation]] = [:]

init(viewMode: SyntaxTreeViewMode, testParentClasses: Set<String>) {
self.testParentClasses = testParentClasses
super.init(viewMode: viewMode)
}

override func visitPost(_ node: ClassDeclSyntax) {
let className = node.trimmedDescription
if node.isXCTestCase(testParentClasses) {
testClasses.insert(className)
} else {
nonTestClasses.insert(className)
}
processPossibleViolations(forClassName: className)
}

override func visitPost(_ node: FloatLiteralExprSyntax) {
if node.isMemberOfATestClass(testParentClasses) == false, node.floatingDigits.isMagicNumber {
violations.append(node.floatingDigits.positionAfterSkippingLeadingTrivia)
guard node.floatingDigits.isMagicNumber else {
return
}
let violation = node.floatingDigits.positionAfterSkippingLeadingTrivia
process(violation: violation, forNode: node)
}

override func visitPost(_ node: IntegerLiteralExprSyntax) {
if node.isMemberOfATestClass(testParentClasses) == false, node.digits.isMagicNumber {
violations.append(node.digits.positionAfterSkippingLeadingTrivia)
guard node.digits.isMagicNumber else {
return
}
let violation = node.digits.positionAfterSkippingLeadingTrivia
process(violation: violation, forNode: node)
}

private func process(violation: AbsolutePosition, forNode node: ExprSyntaxProtocol) {
guard if node.isMemberOfATestClass(testParentClasses) == false else {
return
}
if let extendedTypeName = node.extendedClassname() {
if testClasses.contains(extendedTypeName) {
violations.append(violation)
} else if nonTestClasses.contains(extendedTypeName) == false {
var possibleViolationsForClass = possibleViolations[extendedTypeName] ?? []
possibleViolationsForClass.append(violation)
possibleViolations[extendedTypeName] = possibleViolationsForClass
}
} else {
violations.append(violation)
}
}

private func processPossibleViolations(forClassName className: String) {
guard let possibleViolationsForClass = possibleViolations[className] else {
return
}
violations.append(contentsOf: possibleViolationsForClass)
violations.sort(by: { $0.position < $1.position })
possibleViolations[className] = nil
}
}
}
Expand Down Expand Up @@ -126,4 +191,15 @@ private extension ExprSyntaxProtocol {
}
return false
}

func extendedClassname() -> String? {
var parent = parent
while parent != nil {
if let extensionDecl = parent?.as(ExtensionDeclSyntax.self) {
return extensionDecl.extendedType.trimmedDescription
}
parent = parent?.parent
}
return nil
}
}

0 comments on commit d423c44

Please sign in to comment.