diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift index 41f2cdfd60..b2b6f6cecb 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift @@ -74,44 +74,46 @@ struct ExplicitTypeInterfaceRule: OptInRule, ConfigurationProviderRule, SwiftSyn } } -private class Visitor: ViolationsSyntaxVisitor { - let configuration: ExplicitTypeInterfaceConfiguration +private extension ExplicitTypeInterfaceRule { + final class Visitor: ViolationsSyntaxVisitor { + let configuration: ExplicitTypeInterfaceConfiguration - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } - init(configuration: ExplicitTypeInterfaceConfiguration) { - self.configuration = configuration - super.init(viewMode: .sourceAccurate) - } + init(configuration: ExplicitTypeInterfaceConfiguration) { + self.configuration = configuration + super.init(viewMode: .sourceAccurate) + } - override func visitPost(_ node: VariableDeclSyntax) { - if node.modifiers.contains(keyword: .class) { - if configuration.allowedKinds.contains(.class) { - checkViolation(node) - } - } else if node.modifiers.contains(keyword: .static) { - if configuration.allowedKinds.contains(.static) { - checkViolation(node) - } - } else if node.parent?.is(MemberBlockItemSyntax.self) == true { - if configuration.allowedKinds.contains(.instance) { - checkViolation(node) - } - } else if node.parent?.is(CodeBlockItemSyntax.self) == true { - if configuration.allowedKinds.contains(.local) { - checkViolation(node) + override func visitPost(_ node: VariableDeclSyntax) { + if node.modifiers.contains(keyword: .class) { + if configuration.allowedKinds.contains(.class) { + checkViolation(node) + } + } else if node.modifiers.contains(keyword: .static) { + if configuration.allowedKinds.contains(.static) { + checkViolation(node) + } + } else if node.parent?.is(MemberBlockItemSyntax.self) == true { + if configuration.allowedKinds.contains(.instance) { + checkViolation(node) + } + } else if node.parent?.is(CodeBlockItemSyntax.self) == true { + if configuration.allowedKinds.contains(.local) { + checkViolation(node) + } } } - } - private func checkViolation(_ node: VariableDeclSyntax) { - for binding in node.bindings { - if configuration.allowRedundancy, let initializer = binding.initializer, - initializer.isTypeConstructor || initializer.isTypeReference { - continue - } - if binding.typeAnnotation == nil { - violations.append(binding.positionAfterSkippingLeadingTrivia) + private func checkViolation(_ node: VariableDeclSyntax) { + for binding in node.bindings { + if configuration.allowRedundancy, let initializer = binding.initializer, + initializer.isTypeConstructor || initializer.isTypeReference { + continue + } + if binding.typeAnnotation == nil { + violations.append(binding.positionAfterSkippingLeadingTrivia) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceCastRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceCastRule.swift index 4d6a44ec6c..03ac7ab921 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceCastRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceCastRule.swift @@ -15,20 +15,22 @@ struct ForceCastRule: ConfigurationProviderRule, SwiftSyntaxRule { ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - ForceCastRuleVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private final class ForceCastRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: AsExprSyntax) { - if node.questionOrExclamationMark?.tokenKind == .exclamationMark { - violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia) +private extension ForceCastRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: AsExprSyntax) { + if node.questionOrExclamationMark?.tokenKind == .exclamationMark { + violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia) + } } - } - override func visitPost(_ node: UnresolvedAsExprSyntax) { - if node.questionOrExclamationMark?.tokenKind == .exclamationMark { - violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: UnresolvedAsExprSyntax) { + if node.questionOrExclamationMark?.tokenKind == .exclamationMark { + violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceUnwrappingRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceUnwrappingRule.swift index 0f3e1c789d..bd50632866 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceUnwrappingRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceUnwrappingRule.swift @@ -66,12 +66,14 @@ struct ForceUnwrappingRule: OptInRule, SwiftSyntaxRule, ConfigurationProviderRul ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - ForceUnwrappingVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private final class ForceUnwrappingVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: ForceUnwrapExprSyntax) { - violations.append(node.exclamationMark.positionAfterSkippingLeadingTrivia) +private extension ForceUnwrappingRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: ForceUnwrapExprSyntax) { + violations.append(node.exclamationMark.positionAfterSkippingLeadingTrivia) + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PatternMatchingKeywordsRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PatternMatchingKeywordsRule.swift index 4372170fd7..0f7d1e5824 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PatternMatchingKeywordsRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PatternMatchingKeywordsRule.swift @@ -43,31 +43,31 @@ private extension PatternMatchingKeywordsRule { violations.append(contentsOf: localViolations) } } +} - final class TupleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: LabeledExprListSyntax) { - let list = node.flatteningEnumPatterns() - .compactMap { elem in - elem.expression.asValueBindingPattern() - } - - guard list.count > 1, - let firstLetOrVar = list.first?.bindingSpecifier.tokenKind else { - return +private final class TupleVisitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: LabeledExprListSyntax) { + let list = node.flatteningEnumPatterns() + .compactMap { elem in + elem.expression.asValueBindingPattern() } - let hasViolation = list.allSatisfy { elem in - elem.bindingSpecifier.tokenKind == firstLetOrVar - } + guard list.count > 1, + let firstLetOrVar = list.first?.bindingSpecifier.tokenKind else { + return + } - guard hasViolation else { - return - } + let hasViolation = list.allSatisfy { elem in + elem.bindingSpecifier.tokenKind == firstLetOrVar + } - violations.append(contentsOf: list.compactMap { elem in - return elem.bindingSpecifier.positionAfterSkippingLeadingTrivia - }) + guard hasViolation else { + return } + + violations.append(contentsOf: list.compactMap { elem in + return elem.bindingSpecifier.positionAfterSkippingLeadingTrivia + }) } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift index 25de6ca5da..66556e831f 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift @@ -52,7 +52,7 @@ private extension PreferZeroOverExplicitInitRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PrivateOverFilePrivateRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PrivateOverFilePrivateRule.swift index d108370e64..c3d66f21c3 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PrivateOverFilePrivateRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/PrivateOverFilePrivateRule.swift @@ -133,7 +133,7 @@ private extension PrivateOverFilePrivateRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] private let validateExtensions: Bool private let locationConverter: SourceLocationConverter diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantNilCoalescingRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantNilCoalescingRule.swift index 777e7cc9fd..4b68507c92 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantNilCoalescingRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/RedundantNilCoalescingRule.swift @@ -40,7 +40,7 @@ private extension RedundantNilCoalescingRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ReturnValueFromVoidFunctionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ReturnValueFromVoidFunctionRule.swift index 2b2ff1d59b..383769139a 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ReturnValueFromVoidFunctionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ReturnValueFromVoidFunctionRule.swift @@ -14,16 +14,18 @@ struct ReturnValueFromVoidFunctionRule: ConfigurationProviderRule, OptInRule, Sw ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - ReturnValueFromVoidFunctionVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private final class ReturnValueFromVoidFunctionVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: ReturnStmtSyntax) { - if node.expression != nil, - let functionNode = Syntax(node).enclosingFunction(), - functionNode.returnsVoid { - violations.append(node.positionAfterSkippingLeadingTrivia) +private extension ReturnValueFromVoidFunctionRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: ReturnStmtSyntax) { + if node.expression != nil, + let functionNode = Syntax(node).enclosingFunction(), + functionNode.returnsVoid { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ShorthandOptionalBindingRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ShorthandOptionalBindingRule.swift index 37a0218750..6aaf8dccba 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ShorthandOptionalBindingRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/ShorthandOptionalBindingRule.swift @@ -88,37 +88,39 @@ struct ShorthandOptionalBindingRule: OptInRule, SwiftSyntaxCorrectableRule, Conf } } -private class Visitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: OptionalBindingConditionSyntax) { - if node.isShadowingOptionalBinding { - violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia) +private extension ShorthandOptionalBindingRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: OptionalBindingConditionSyntax) { + if node.isShadowingOptionalBinding { + violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia) + } } } -} - -private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - private let locationConverter: SourceLocationConverter - private let disabledRegions: [SourceRange] - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + private let locationConverter: SourceLocationConverter + private let disabledRegions: [SourceRange] - override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax { - guard - node.isShadowingOptionalBinding, - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) - else { - return super.visit(node) + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let newNode = node - .with(\.initializer, nil) - .with(\.pattern, node.pattern.with(\.trailingTrivia, node.trailingTrivia)) - return super.visit(newNode) + override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax { + guard + node.isShadowingOptionalBinding, + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) + else { + return super.visit(node) + } + + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let newNode = node + .with(\.initializer, nil) + .with(\.pattern, node.pattern.with(\.trailingTrivia, node.trailingTrivia)) + return super.visit(newNode) + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/StrictFilePrivateRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/StrictFilePrivateRule.swift index cb91298e9a..68e71f43e9 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/StrictFilePrivateRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/StrictFilePrivateRule.swift @@ -135,39 +135,6 @@ private enum ProtocolRequirementType: Equatable { } private extension StrictFilePrivateRule { - final class ProtocolCollector: ViolationsSyntaxVisitor { - private(set) var protocols = [String: [ProtocolRequirementType]]() - private var currentProtocolName: String = "" - - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .allExcept(ProtocolDeclSyntax.self) } - - override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { - currentProtocolName = node.name.text - return .visitChildren - } - - override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { - protocols[currentProtocolName, default: []].append(.method(node.name.text)) - return .skipChildren - } - - override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { - for binding in node.bindings { - guard let name = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.text, - let accessorBlock = binding.accessorBlock else { - continue - } - if accessorBlock.specifiesGetAccessor { - protocols[currentProtocolName, default: []].append(.getter(name)) - } - if accessorBlock.specifiesSetAccessor { - protocols[currentProtocolName, default: []].append(.setter(name)) - } - } - return .skipChildren - } - } - final class Visitor: ViolationsSyntaxVisitor { private let file: SourceFileSyntax @@ -245,6 +212,39 @@ private extension StrictFilePrivateRule { } } +private final class ProtocolCollector: ViolationsSyntaxVisitor { + private(set) var protocols = [String: [ProtocolRequirementType]]() + private var currentProtocolName: String = "" + + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .allExcept(ProtocolDeclSyntax.self) } + + override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { + currentProtocolName = node.name.text + return .visitChildren + } + + override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind { + protocols[currentProtocolName, default: []].append(.method(node.name.text)) + return .skipChildren + } + + override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind { + for binding in node.bindings { + guard let name = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.text, + let accessorBlock = binding.accessorBlock else { + continue + } + if accessorBlock.specifiesGetAccessor { + protocols[currentProtocolName, default: []].append(.getter(name)) + } + if accessorBlock.specifiesSetAccessor { + protocols[currentProtocolName, default: []].append(.setter(name)) + } + } + return .skipChildren + } +} + private extension InheritanceClauseSyntax? { var inheritedTypeNames: [String] { self?.inheritedTypes.compactMap { $0.type.as(IdentifierTypeSyntax.self)?.name.text } ?? [] diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnavailableConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnavailableConditionRule.swift index ec05b61f57..3442fbe9a2 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnavailableConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnavailableConditionRule.swift @@ -70,58 +70,60 @@ struct UnavailableConditionRule: ConfigurationProviderRule, SwiftSyntaxRule { ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - UnavailableConditionRuleVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private final class UnavailableConditionRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: IfExprSyntax) { - guard node.body.statements.isEmpty else { - return - } +private extension UnavailableConditionRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: IfExprSyntax) { + guard node.body.statements.isEmpty else { + return + } - guard let condition = node.conditions.onlyElement, - let availability = asAvailabilityCondition(condition.condition) else { - return - } + guard let condition = node.conditions.onlyElement, + let availability = asAvailabilityCondition(condition.condition) else { + return + } - if otherAvailabilityCheckInvolved(ifStmt: node) { - // If there are other conditional branches with availability checks it might not be possible - // to just invert the first one. - return - } + if otherAvailabilityCheckInvolved(ifStmt: node) { + // If there are other conditional branches with availability checks it might not be possible + // to just invert the first one. + return + } - violations.append( - ReasonedRuleViolation( - position: availability.positionAfterSkippingLeadingTrivia, - reason: reason(for: availability) + violations.append( + ReasonedRuleViolation( + position: availability.positionAfterSkippingLeadingTrivia, + reason: reason(for: availability) + ) ) - ) - } + } - private func asAvailabilityCondition(_ condition: ConditionElementSyntax.Condition) + private func asAvailabilityCondition(_ condition: ConditionElementSyntax.Condition) -> AvailabilityConditionSyntax? { - condition.as(AvailabilityConditionSyntax.self) - } + condition.as(AvailabilityConditionSyntax.self) + } - private func otherAvailabilityCheckInvolved(ifStmt: IfExprSyntax) -> Bool { - if let elseBody = ifStmt.elseBody, let nestedIfStatement = elseBody.as(IfExprSyntax.self) { - if nestedIfStatement.conditions.map(\.condition).compactMap(asAvailabilityCondition).isNotEmpty { - return true + private func otherAvailabilityCheckInvolved(ifStmt: IfExprSyntax) -> Bool { + if let elseBody = ifStmt.elseBody, let nestedIfStatement = elseBody.as(IfExprSyntax.self) { + if nestedIfStatement.conditions.map(\.condition).compactMap(asAvailabilityCondition).isNotEmpty { + return true + } + return otherAvailabilityCheckInvolved(ifStmt: nestedIfStatement) } - return otherAvailabilityCheckInvolved(ifStmt: nestedIfStatement) + return false } - return false - } - private func reason(for condition: AvailabilityConditionSyntax) -> String { - switch condition.availabilityKeyword.tokenKind { - case .poundAvailable: - return "Use #unavailable instead of #available with an empty body" - case .poundUnavailable: - return "Use #available instead of #unavailable with an empty body" - default: - queuedFatalError("Unknown availability check type.") + private func reason(for condition: AvailabilityConditionSyntax) -> String { + switch condition.availabilityKeyword.tokenKind { + case .poundAvailable: + return "Use #unavailable instead of #available with an empty body" + case .poundUnavailable: + return "Use #available instead of #unavailable with an empty body" + default: + queuedFatalError("Unknown availability check type.") + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnneededBreakInSwitchRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnneededBreakInSwitchRule.swift index 1d9ca9ad55..cc5a6237cb 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnneededBreakInSwitchRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UnneededBreakInSwitchRule.swift @@ -87,57 +87,59 @@ struct UnneededBreakInSwitchRule: SwiftSyntaxCorrectableRule, ConfigurationProvi ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - UnneededBreakInSwitchRuleVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } - func makeRewriter(file: SwiftLintCore.SwiftLintFile) -> SwiftLintCore.ViolationsSyntaxRewriter? { - UnneededBreakInSwitchRewriter( + func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? { + Rewriter( locationConverter: file.locationConverter, disabledRegions: disabledRegions(file: file) ) } } -private final class UnneededBreakInSwitchRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: SwitchCaseSyntax) { - guard let statement = node.unneededBreak else { - return - } +private extension UnneededBreakInSwitchRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: SwitchCaseSyntax) { + guard let statement = node.unneededBreak else { + return + } - violations.append(statement.item.positionAfterSkippingLeadingTrivia) + violations.append(statement.item.positionAfterSkippingLeadingTrivia) + } } -} -private final class UnneededBreakInSwitchRewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [SwiftSyntax.AbsolutePosition] = [] - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [SwiftSyntax.AbsolutePosition] = [] + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions + } - override func visit(_ node: SwitchCaseSyntax) -> SwitchCaseSyntax { - let stmts = CodeBlockItemListSyntax(node.statements.dropLast()) + override func visit(_ node: SwitchCaseSyntax) -> SwitchCaseSyntax { + let stmts = CodeBlockItemListSyntax(node.statements.dropLast()) - guard let breakStatement = node.unneededBreak, let secondLast = stmts.last, - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else { - return super.visit(node) - } + guard let breakStatement = node.unneededBreak, let secondLast = stmts.last, + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else { + return super.visit(node) + } - correctionPositions.append(breakStatement.item.positionAfterSkippingLeadingTrivia) + correctionPositions.append(breakStatement.item.positionAfterSkippingLeadingTrivia) - let trivia = breakStatement.item.leadingTrivia + breakStatement.item.trailingTrivia + let trivia = breakStatement.item.leadingTrivia + breakStatement.item.trailingTrivia - let newNode = node - .with(\.statements, stmts) - .with(\.statements.trailingTrivia, secondLast.item.trailingTrivia + trivia) - .trimmed { !$0.isComment } - .formatted() - .as(SwitchCaseSyntax.self)! + let newNode = node + .with(\.statements, stmts) + .with(\.statements.trailingTrivia, secondLast.item.trailingTrivia + trivia) + .trimmed { !$0.isComment } + .formatted() + .as(SwitchCaseSyntax.self)! - return super.visit(newNode) + return super.visit(newNode) + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UntypedErrorInCatchRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UntypedErrorInCatchRule.swift index a3ec5047cf..051113afe7 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UntypedErrorInCatchRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/UntypedErrorInCatchRule.swift @@ -86,11 +86,11 @@ struct UntypedErrorInCatchRule: OptInRule, ConfigurationProviderRule, SwiftSynta ]) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - UntypedErrorInCatchRuleVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? { - UntypedErrorInCatchRuleRewriter( + Rewriter( locationConverter: file.locationConverter, disabledRegions: disabledRegions(file: file) ) @@ -119,39 +119,41 @@ private extension CatchItemSyntax { } } -private final class UntypedErrorInCatchRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: CatchClauseSyntax) { - guard let item = node.catchItems.onlyElement, item.isIdentifierPattern else { - return +private extension UntypedErrorInCatchRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: CatchClauseSyntax) { + guard let item = node.catchItems.onlyElement, item.isIdentifierPattern else { + return + } + violations.append(node.catchKeyword.positionAfterSkippingLeadingTrivia) } - violations.append(node.catchKeyword.positionAfterSkippingLeadingTrivia) } -} -private final class UntypedErrorInCatchRuleRewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] - - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] - override func visit(_ node: CatchClauseSyntax) -> CatchClauseSyntax { - guard - let item = node.catchItems.onlyElement, - item.isIdentifierPattern, - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) - else { - return super.visit(node) + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions } - correctionPositions.append(node.catchKeyword.positionAfterSkippingLeadingTrivia) - return super.visit( - node - .with(\.catchKeyword, node.catchKeyword.with(\.trailingTrivia, .spaces(1))) - .with(\.catchItems, CatchItemListSyntax([])) - ) + override func visit(_ node: CatchClauseSyntax) -> CatchClauseSyntax { + guard + let item = node.catchItems.onlyElement, + item.isIdentifierPattern, + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) + else { + return super.visit(node) + } + + correctionPositions.append(node.catchKeyword.positionAfterSkippingLeadingTrivia) + return super.visit( + node + .with(\.catchKeyword, node.catchKeyword.with(\.trailingTrivia, .spaces(1))) + .with(\.catchItems, CatchItemListSyntax([])) + ) + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift index d970e1bad4..4edd62187e 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Idiomatic/VoidFunctionInTernaryConditionRule.swift @@ -107,39 +107,41 @@ struct VoidFunctionInTernaryConditionRule: ConfigurationProviderRule, SwiftSynta ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - VoidFunctionInTernaryConditionVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private class VoidFunctionInTernaryConditionVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: TernaryExprSyntax) { - guard node.thenExpression.is(FunctionCallExprSyntax.self), - node.elseExpression.is(FunctionCallExprSyntax.self), - let parent = node.parent?.as(ExprListSyntax.self), - !parent.containsAssignment, - let grandparent = parent.parent, - grandparent.is(SequenceExprSyntax.self), - let blockItem = grandparent.parent?.as(CodeBlockItemSyntax.self), - !blockItem.isImplicitReturn else { - return +private extension VoidFunctionInTernaryConditionRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: TernaryExprSyntax) { + guard node.thenExpression.is(FunctionCallExprSyntax.self), + node.elseExpression.is(FunctionCallExprSyntax.self), + let parent = node.parent?.as(ExprListSyntax.self), + !parent.containsAssignment, + let grandparent = parent.parent, + grandparent.is(SequenceExprSyntax.self), + let blockItem = grandparent.parent?.as(CodeBlockItemSyntax.self), + !blockItem.isImplicitReturn else { + return + } + + violations.append(node.questionMark.positionAfterSkippingLeadingTrivia) } - violations.append(node.questionMark.positionAfterSkippingLeadingTrivia) - } + override func visitPost(_ node: UnresolvedTernaryExprSyntax) { + guard node.thenExpression.is(FunctionCallExprSyntax.self), + let parent = node.parent?.as(ExprListSyntax.self), + parent.last?.is(FunctionCallExprSyntax.self) == true, + !parent.containsAssignment, + let grandparent = parent.parent, + grandparent.is(SequenceExprSyntax.self), + let blockItem = grandparent.parent?.as(CodeBlockItemSyntax.self), + !blockItem.isImplicitReturn else { + return + } - override func visitPost(_ node: UnresolvedTernaryExprSyntax) { - guard node.thenExpression.is(FunctionCallExprSyntax.self), - let parent = node.parent?.as(ExprListSyntax.self), - parent.last?.is(FunctionCallExprSyntax.self) == true, - !parent.containsAssignment, - let grandparent = parent.parent, - grandparent.is(SequenceExprSyntax.self), - let blockItem = grandparent.parent?.as(CodeBlockItemSyntax.self), - !blockItem.isImplicitReturn else { - return + violations.append(node.questionMark.positionAfterSkippingLeadingTrivia) } - - violations.append(node.questionMark.positionAfterSkippingLeadingTrivia) } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/AnyObjectProtocolRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/AnyObjectProtocolRule.swift index 6757063864..084f87bdb2 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/AnyObjectProtocolRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/AnyObjectProtocolRule.swift @@ -52,13 +52,13 @@ struct AnyObjectProtocolRule: SwiftSyntaxCorrectableRule, OptInRule, Configurati } private extension AnyObjectProtocolRule { - private final class Visitor: ViolationsSyntaxVisitor { + final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: ClassRestrictionTypeSyntax) { violations.append(node.positionAfterSkippingLeadingTrivia) } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/BalancedXCTestLifecycleRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/BalancedXCTestLifecycleRule.swift index c599e71e07..950f1f51ef 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/BalancedXCTestLifecycleRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/BalancedXCTestLifecycleRule.swift @@ -135,16 +135,16 @@ private extension BalancedXCTestLifecycleRule { violations.append(node.name.positionAfterSkippingLeadingTrivia) } } +} - final class SetupTearDownVisitor: ViolationsSyntaxVisitor { - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } - private(set) var methods: Set = [] +private final class SetupTearDownVisitor: ViolationsSyntaxVisitor { + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } + private(set) var methods: Set = [] - override func visitPost(_ node: FunctionDeclSyntax) { - if let method = XCTMethod(node.name.description), - node.signature.parameterClause.parameters.isEmpty { - methods.insert(method) - } + override func visitPost(_ node: FunctionDeclSyntax) { + if let method = XCTMethod(node.name.description), + node.signature.parameterClause.parameters.isEmpty { + methods.insert(method) } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/DeploymentTargetRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/DeploymentTargetRule.swift index ea80ef2b21..0116123914 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/DeploymentTargetRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/DeploymentTargetRule.swift @@ -1,7 +1,7 @@ import SwiftSyntax struct DeploymentTargetRule: ConfigurationProviderRule, SwiftSyntaxRule { - private typealias Version = DeploymentTargetConfiguration.Version + fileprivate typealias Version = DeploymentTargetConfiguration.Version var configuration = DeploymentTargetConfiguration() static let description = RuleDescription( @@ -51,7 +51,7 @@ struct DeploymentTargetRule: ConfigurationProviderRule, SwiftSyntaxRule { } private extension DeploymentTargetRule { - private final class Visitor: ViolationsSyntaxVisitor { + final class Visitor: ViolationsSyntaxVisitor { private let platformToConfiguredMinVersion: [String: Version] init(platformToConfiguredMinVersion: [String: Version]) { diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/EmptyXCTestMethodRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/EmptyXCTestMethodRule.swift index e2cce85ea3..19e2044889 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/EmptyXCTestMethodRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/EmptyXCTestMethodRule.swift @@ -13,26 +13,28 @@ struct EmptyXCTestMethodRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxR ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - EmptyXCTestMethodRuleVisitor(testParentClasses: configuration.testParentClasses) + Visitor(testParentClasses: configuration.testParentClasses) } } -private final class EmptyXCTestMethodRuleVisitor: ViolationsSyntaxVisitor { - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } - private let testParentClasses: Set +private extension EmptyXCTestMethodRule { + final class Visitor: ViolationsSyntaxVisitor { + override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all } + private let testParentClasses: Set - init(testParentClasses: Set) { - self.testParentClasses = testParentClasses - super.init(viewMode: .sourceAccurate) - } + init(testParentClasses: Set) { + self.testParentClasses = testParentClasses + super.init(viewMode: .sourceAccurate) + } - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - node.isXCTestCase(testParentClasses) ? .visitChildren : .skipChildren - } + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + node.isXCTestCase(testParentClasses) ? .visitChildren : .skipChildren + } - override func visitPost(_ node: FunctionDeclSyntax) { - if (node.modifiers.contains(keyword: .override) || node.isTestMethod) && node.hasEmptyBody { - violations.append(node.funcKeyword.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: FunctionDeclSyntax) { + if (node.modifiers.contains(keyword: .override) || node.isTestMethod) && node.hasEmptyBody { + violations.append(node.funcKeyword.positionAfterSkippingLeadingTrivia) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/PrivateUnitTestRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/PrivateUnitTestRule.swift index fe82546b28..86ef4c4f77 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/PrivateUnitTestRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/PrivateUnitTestRule.swift @@ -138,90 +138,92 @@ struct PrivateUnitTestRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRul } } -private class Visitor: ViolationsSyntaxVisitor { - private let configuration: PrivateUnitTestConfiguration +private extension PrivateUnitTestRule { + final class Visitor: ViolationsSyntaxVisitor { + private let configuration: PrivateUnitTestConfiguration - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } - init(configuration: PrivateUnitTestConfiguration) { - self.configuration = configuration - super.init(viewMode: .sourceAccurate) - } + init(configuration: PrivateUnitTestConfiguration) { + self.configuration = configuration + super.init(viewMode: .sourceAccurate) + } - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - !node.isPrivate && node.hasParent(configuredIn: configuration) ? .visitChildren : .skipChildren - } + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + !node.isPrivate && node.hasParent(configuredIn: configuration) ? .visitChildren : .skipChildren + } - override func visitPost(_ node: ClassDeclSyntax) { - if node.isPrivate, node.hasParent(configuredIn: configuration) { - violations.append(node.classKeyword.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: ClassDeclSyntax) { + if node.isPrivate, node.hasParent(configuredIn: configuration) { + violations.append(node.classKeyword.positionAfterSkippingLeadingTrivia) + } } - } - override func visitPost(_ node: FunctionDeclSyntax) { - if node.isTestMethod, node.isPrivate { - violations.append(node.funcKeyword.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: FunctionDeclSyntax) { + if node.isTestMethod, node.isPrivate { + violations.append(node.funcKeyword.positionAfterSkippingLeadingTrivia) + } } } -} -private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - private let configuration: PrivateUnitTestConfiguration - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + private let configuration: PrivateUnitTestConfiguration + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] - init(configuration: PrivateUnitTestConfiguration, - locationConverter: SourceLocationConverter, - disabledRegions: [SourceRange]) { - self.configuration = configuration - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } - - override func visit(_ node: ClassDeclSyntax) -> DeclSyntax { - guard - node.isPrivate, - node.hasParent(configuredIn: configuration), - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) - else { - return super.visit(node) + init(configuration: PrivateUnitTestConfiguration, + locationConverter: SourceLocationConverter, + disabledRegions: [SourceRange]) { + self.configuration = configuration + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let (modifiers, declKeyword) = withoutPrivate(modifiers: node.modifiers, declKeyword: node.classKeyword) - return super.visit(node.with(\.modifiers, modifiers).with(\.classKeyword, declKeyword)) - } + override func visit(_ node: ClassDeclSyntax) -> DeclSyntax { + guard + node.isPrivate, + node.hasParent(configuredIn: configuration), + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) + else { + return super.visit(node) + } - override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax { - guard - node.isTestMethod, - node.isPrivate, - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) - else { - return super.visit(node) + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let (modifiers, declKeyword) = withoutPrivate(modifiers: node.modifiers, declKeyword: node.classKeyword) + return super.visit(node.with(\.modifiers, modifiers).with(\.classKeyword, declKeyword)) } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let (modifiers, declKeyword) = withoutPrivate(modifiers: node.modifiers, declKeyword: node.funcKeyword) - return super.visit(node.with(\.modifiers, modifiers).with(\.funcKeyword, declKeyword)) - } + override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax { + guard + node.isTestMethod, + node.isPrivate, + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) + else { + return super.visit(node) + } + + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let (modifiers, declKeyword) = withoutPrivate(modifiers: node.modifiers, declKeyword: node.funcKeyword) + return super.visit(node.with(\.modifiers, modifiers).with(\.funcKeyword, declKeyword)) + } - private func withoutPrivate(modifiers: DeclModifierListSyntax, - declKeyword: TokenSyntax) -> (DeclModifierListSyntax, TokenSyntax) { - var filteredModifiers = [DeclModifierSyntax]() - var leadingTrivia = Trivia() - for modifier in modifiers { - let accumulatedLeadingTrivia = leadingTrivia + (modifier.leadingTrivia) - if modifier.name.tokenKind == .keyword(.private) { - leadingTrivia = accumulatedLeadingTrivia - } else { - filteredModifiers.append(modifier.with(\.leadingTrivia, accumulatedLeadingTrivia)) - leadingTrivia = Trivia() + private func withoutPrivate(modifiers: DeclModifierListSyntax, + declKeyword: TokenSyntax) -> (DeclModifierListSyntax, TokenSyntax) { + var filteredModifiers = [DeclModifierSyntax]() + var leadingTrivia = Trivia() + for modifier in modifiers { + let accumulatedLeadingTrivia = leadingTrivia + (modifier.leadingTrivia) + if modifier.name.tokenKind == .keyword(.private) { + leadingTrivia = accumulatedLeadingTrivia + } else { + filteredModifiers.append(modifier.with(\.leadingTrivia, accumulatedLeadingTrivia)) + leadingTrivia = Trivia() + } } + let declKeyword = declKeyword.with(\.leadingTrivia, leadingTrivia + (declKeyword.leadingTrivia)) + return (DeclModifierListSyntax(filteredModifiers), declKeyword) } - let declKeyword = declKeyword.with(\.leadingTrivia, leadingTrivia + (declKeyword.leadingTrivia)) - return (DeclModifierListSyntax(filteredModifiers), declKeyword) } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/SelfInPropertyInitializationRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/SelfInPropertyInitializationRule.swift index f4e5af5efd..4587162247 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/SelfInPropertyInitializationRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/SelfInPropertyInitializationRule.swift @@ -113,20 +113,20 @@ private extension SelfInPropertyInitializationRule { } } } +} - final class IdentifierUsageVisitor: SyntaxVisitor { - let identifier: TokenKind - private(set) var isTokenUsed = false +private final class IdentifierUsageVisitor: SyntaxVisitor { + let identifier: TokenKind + private(set) var isTokenUsed = false - init(identifier: TokenKind) { - self.identifier = identifier - super.init(viewMode: .sourceAccurate) - } + init(identifier: TokenKind) { + self.identifier = identifier + super.init(viewMode: .sourceAccurate) + } - override func visitPost(_ node: DeclReferenceExprSyntax) { - if node.baseName.tokenKind == identifier, node.keyPathInParent != \MemberAccessExprSyntax.declName { - isTokenUsed = true - } + override func visitPost(_ node: DeclReferenceExprSyntax) { + if node.baseName.tokenKind == identifier, node.keyPathInParent != \MemberAccessExprSyntax.declName { + isTokenUsed = true } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/StrongIBOutletRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/StrongIBOutletRule.swift index 5c50ee3e4b..17b4ff65a1 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/StrongIBOutletRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/StrongIBOutletRule.swift @@ -45,7 +45,7 @@ private extension StrongIBOutletRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/TestCaseAccessibilityRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/TestCaseAccessibilityRule.swift index 3b5eac4c99..0e516d96a7 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/TestCaseAccessibilityRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/TestCaseAccessibilityRule.swift @@ -56,79 +56,79 @@ private extension TestCaseAccessibilityRule { ) } } +} - final class XCTestClassVisitor: ViolationsSyntaxVisitor { - private let allowedPrefixes: Set - - init(allowedPrefixes: Set) { - self.allowedPrefixes = allowedPrefixes - super.init(viewMode: .sourceAccurate) - } - - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } +private final class XCTestClassVisitor: ViolationsSyntaxVisitor { + private let allowedPrefixes: Set - override func visitPost(_ node: VariableDeclSyntax) { - guard !node.modifiers.containsPrivateOrFileprivate(), - !XCTestHelpers.isXCTestVariable(node) else { - return - } + init(allowedPrefixes: Set) { + self.allowedPrefixes = allowedPrefixes + super.init(viewMode: .sourceAccurate) + } - for binding in node.bindings { - guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self), - case let name = pattern.identifier.text, - !allowedPrefixes.contains(where: name.hasPrefix) else { - continue - } + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } - violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia) - return - } + override func visitPost(_ node: VariableDeclSyntax) { + guard !node.modifiers.containsPrivateOrFileprivate(), + !XCTestHelpers.isXCTestVariable(node) else { + return } - override func visitPost(_ node: FunctionDeclSyntax) { - guard hasViolation(modifiers: node.modifiers, identifierToken: node.name), - !XCTestHelpers.isXCTestFunction(node) else { - return + for binding in node.bindings { + guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self), + case let name = pattern.identifier.text, + !allowedPrefixes.contains(where: name.hasPrefix) else { + continue } - violations.append(node.positionAfterSkippingLeadingTrivia) + violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia) + return } + } - override func visitPost(_ node: ClassDeclSyntax) { - if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { - violations.append(node.classKeyword.positionAfterSkippingLeadingTrivia) - } + override func visitPost(_ node: FunctionDeclSyntax) { + guard hasViolation(modifiers: node.modifiers, identifierToken: node.name), + !XCTestHelpers.isXCTestFunction(node) else { + return } - override func visitPost(_ node: EnumDeclSyntax) { - if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { - violations.append(node.enumKeyword.positionAfterSkippingLeadingTrivia) - } + violations.append(node.positionAfterSkippingLeadingTrivia) + } + + override func visitPost(_ node: ClassDeclSyntax) { + if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { + violations.append(node.classKeyword.positionAfterSkippingLeadingTrivia) } + } - override func visitPost(_ node: StructDeclSyntax) { - if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { - violations.append(node.structKeyword.positionAfterSkippingLeadingTrivia) - } + override func visitPost(_ node: EnumDeclSyntax) { + if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { + violations.append(node.enumKeyword.positionAfterSkippingLeadingTrivia) } + } - override func visitPost(_ node: ActorDeclSyntax) { - if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { - violations.append(node.actorKeyword.positionAfterSkippingLeadingTrivia) - } + override func visitPost(_ node: StructDeclSyntax) { + if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { + violations.append(node.structKeyword.positionAfterSkippingLeadingTrivia) } + } - override func visitPost(_ node: TypeAliasDeclSyntax) { - if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { - violations.append(node.typealiasKeyword.positionAfterSkippingLeadingTrivia) - } + override func visitPost(_ node: ActorDeclSyntax) { + if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { + violations.append(node.actorKeyword.positionAfterSkippingLeadingTrivia) } + } - private func hasViolation(modifiers: DeclModifierListSyntax, identifierToken: TokenSyntax) -> Bool { - !modifiers.containsPrivateOrFileprivate() - && !allowedPrefixes.contains(where: identifierToken.text.hasPrefix) + override func visitPost(_ node: TypeAliasDeclSyntax) { + if hasViolation(modifiers: node.modifiers, identifierToken: node.name) { + violations.append(node.typealiasKeyword.positionAfterSkippingLeadingTrivia) } } + + private func hasViolation(modifiers: DeclModifierListSyntax, identifierToken: TokenSyntax) -> Bool { + !modifiers.containsPrivateOrFileprivate() + && !allowedPrefixes.contains(where: identifierToken.text.hasPrefix) + } } private extension ClassDeclSyntax { diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/UnneededOverrideRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/UnneededOverrideRule.swift index 476993892d..fdd129aef3 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/UnneededOverrideRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/UnneededOverrideRule.swift @@ -57,35 +57,37 @@ private func extractFunctionCallSyntax(_ node: SyntaxProtocol) -> FunctionCallEx return syntax?.as(FunctionCallExprSyntax.self) } -private final class Visitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: FunctionDeclSyntax) { - if isUnneededOverride(node) { - self.violations.append(node.positionAfterSkippingLeadingTrivia) +private extension UnneededOverrideRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: FunctionDeclSyntax) { + if isUnneededOverride(node) { + self.violations.append(node.positionAfterSkippingLeadingTrivia) + } } } -} - -private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - var correctionPositions: [AbsolutePosition] = [] - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + var correctionPositions: [AbsolutePosition] = [] + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] - override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax { - if isUnneededOverride(node) && - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) { - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let expr: DeclSyntax = "" - return expr - .with(\.leadingTrivia, node.leadingTrivia) - .with(\.trailingTrivia, node.trailingTrivia) + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions } - return super.visit(node) + override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax { + if isUnneededOverride(node) && + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) { + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let expr: DeclSyntax = "" + return expr + .with(\.leadingTrivia, node.leadingTrivia) + .with(\.trailingTrivia, node.trailingTrivia) + } + + return super.visit(node) + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/UnownedVariableCaptureRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/UnownedVariableCaptureRule.swift index de0da2c825..87c86cbfe8 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/UnownedVariableCaptureRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/UnownedVariableCaptureRule.swift @@ -33,14 +33,16 @@ struct UnownedVariableCaptureRule: SwiftSyntaxRule, OptInRule, ConfigurationProv ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - UnownedVariableCaptureRuleVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private final class UnownedVariableCaptureRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: TokenSyntax) { - if case .keyword(.unowned) = node.tokenKind, node.parent?.is(ClosureCaptureSpecifierSyntax.self) == true { - violations.append(node.positionAfterSkippingLeadingTrivia) +private extension UnownedVariableCaptureRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: TokenSyntax) { + if case .keyword(.unowned) = node.tokenKind, node.parent?.is(ClosureCaptureSpecifierSyntax.self) == true { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedControlFlowLabelRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedControlFlowLabelRule.swift index 24b5ab05c6..da315b8d29 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedControlFlowLabelRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedControlFlowLabelRule.swift @@ -101,7 +101,7 @@ private extension UnusedControlFlowLabelRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedSetterValueRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedSetterValueRule.swift index 0f1e80682a..58e69e2601 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedSetterValueRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/UnusedSetterValueRule.swift @@ -150,20 +150,20 @@ private extension UnusedSetterValueRule { } } } +} - final class NewValueUsageVisitor: SyntaxVisitor { - let variableName: String - private(set) var isVariableUsed = false +private final class NewValueUsageVisitor: SyntaxVisitor { + let variableName: String + private(set) var isVariableUsed = false - init(variableName: String) { - self.variableName = variableName - super.init(viewMode: .sourceAccurate) - } + init(variableName: String) { + self.variableName = variableName + super.init(viewMode: .sourceAccurate) + } - override func visitPost(_ node: DeclReferenceExprSyntax) { - if node.baseName.text == variableName { - isVariableUsed = true - } + override func visitPost(_ node: DeclReferenceExprSyntax) { + if node.baseName.text == variableName { + isVariableUsed = true } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Lint/YodaConditionRule.swift b/Source/SwiftLintBuiltInRules/Rules/Lint/YodaConditionRule.swift index 4973a7f159..4cc12f9be7 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Lint/YodaConditionRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Lint/YodaConditionRule.swift @@ -35,64 +35,66 @@ struct YodaConditionRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxRule ]) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - YodaConditionRuleVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private final class YodaConditionRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: IfExprSyntax) { - visit(conditions: node.conditions) - } - - override func visitPost(_ node: GuardStmtSyntax) { - visit(conditions: node.conditions) - } +private extension YodaConditionRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: IfExprSyntax) { + visit(conditions: node.conditions) + } - override func visitPost(_ node: RepeatStmtSyntax) { - visit(condition: node.condition) - } + override func visitPost(_ node: GuardStmtSyntax) { + visit(conditions: node.conditions) + } - override func visitPost(_ node: WhileStmtSyntax) { - visit(conditions: node.conditions) - } + override func visitPost(_ node: RepeatStmtSyntax) { + visit(condition: node.condition) + } - private func visit(conditions: ConditionElementListSyntax) { - for condition in conditions.compactMap({ $0.condition.as(ExprSyntax.self) }) { - visit(condition: condition) + override func visitPost(_ node: WhileStmtSyntax) { + visit(conditions: node.conditions) } - } - private func visit(condition: ExprSyntax) { - guard let children = condition.as(SequenceExprSyntax.self)?.elements.children(viewMode: .sourceAccurate) else { - return + private func visit(conditions: ConditionElementListSyntax) { + for condition in conditions.compactMap({ $0.condition.as(ExprSyntax.self) }) { + visit(condition: condition) + } } - let comparisonOperators = children - .compactMap { $0.as(BinaryOperatorExprSyntax.self) } - .filter { ["==", "!=", ">", "<", ">=", "<="].contains($0.operator.text) } - for comparisonOperator in comparisonOperators { - guard let operatorIndex = children.index(of: comparisonOperator) else { - continue + + private func visit(condition: ExprSyntax) { + guard let elements = condition.as(SequenceExprSyntax.self)?.elements else { + return } - let rhsIdx = children.index(operatorIndex, offsetBy: 1) - if children[rhsIdx].isLiteral { - let afterRhsIndex = children.index(after: rhsIdx) - guard children.endIndex != rhsIdx, afterRhsIndex != nil else { - // This is already the end of the expression. + let children = elements.children(viewMode: .sourceAccurate) + let comparisonOperators = children + .compactMap { $0.as(BinaryOperatorExprSyntax.self) } + .filter { ["==", "!=", ">", "<", ">=", "<="].contains($0.operator.text) } + for comparisonOperator in comparisonOperators { + guard let operatorIndex = children.index(of: comparisonOperator) else { continue } - if children[afterRhsIndex].isLogicalBinaryOperator { - // Next token is an operator with weaker binding. Thus, the literal is unique on the - // right-hand side of the comparison operator. - continue + let rhsIdx = children.index(operatorIndex, offsetBy: 1) + if children[rhsIdx].isLiteral { + let afterRhsIndex = children.index(after: rhsIdx) + guard children.endIndex != rhsIdx, afterRhsIndex != nil else { + // This is already the end of the expression. + continue + } + if children[afterRhsIndex].isLogicalBinaryOperator { + // Next token is an operator with weaker binding. Thus, the literal is unique on the + // right-hand side of the comparison operator. + continue + } } - } - let lhsIdx = children.index(operatorIndex, offsetBy: -1) - let lhs = children[lhsIdx] - if lhs.isLiteral { - if children.startIndex == lhsIdx || children[children.index(before: lhsIdx)].isLogicalBinaryOperator { - // Literal is at the very beginning of the expression or the previous token is an operator with - // weaker binding. Thus, the literal is unique on the left-hand side of the comparison operator. - violations.append(lhs.positionAfterSkippingLeadingTrivia) + let lhsIdx = children.index(operatorIndex, offsetBy: -1) + let lhs = children[lhsIdx] + if lhs.isLiteral, + children.startIndex == lhsIdx || children[children.index(before: lhsIdx)].isLogicalBinaryOperator { + // Literal is at the very beginning of the expression or the previous token is an operator with + // weaker binding. Thus, the literal is unique on the left-hand side of the comparison operator. + violations.append(lhs.positionAfterSkippingLeadingTrivia) } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/ClosingBraceRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/ClosingBraceRule.swift index 2ab5a9611e..372d2e09a5 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/ClosingBraceRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/ClosingBraceRule.swift @@ -39,7 +39,7 @@ private extension ClosingBraceRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/ClosureSpacingRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/ClosureSpacingRule.swift index 0b404f129c..e2c4c81da9 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/ClosureSpacingRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/ClosureSpacingRule.swift @@ -47,76 +47,74 @@ struct ClosureSpacingRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - ClosureSpacingRuleVisitor(locationConverter: file.locationConverter) + Visitor(locationConverter: file.locationConverter) } func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? { - ClosureSpacingRuleRewriter( + Rewriter( locationConverter: file.locationConverter, disabledRegions: disabledRegions(file: file) ) } } -// MARK: - ClosureSpacingRuleVisitor +private extension ClosureSpacingRule { + final class Visitor: ViolationsSyntaxVisitor { + let locationConverter: SourceLocationConverter -private final class ClosureSpacingRuleVisitor: ViolationsSyntaxVisitor { - let locationConverter: SourceLocationConverter - - init(locationConverter: SourceLocationConverter) { - self.locationConverter = locationConverter - super.init(viewMode: .sourceAccurate) - } + init(locationConverter: SourceLocationConverter) { + self.locationConverter = locationConverter + super.init(viewMode: .sourceAccurate) + } - override func visitPost(_ node: ClosureExprSyntax) { - if node.shouldCheckForClosureSpacingRule(locationConverter: locationConverter), - node.violations.hasViolations { - violations.append(node.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: ClosureExprSyntax) { + if node.shouldCheckForClosureSpacingRule(locationConverter: locationConverter), + node.violations.hasViolations { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } } -} -// MARK: - ClosureSpacingRuleRewriter + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] -private final class ClosureSpacingRuleRewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions + } - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + override func visit(_ node: ClosureExprSyntax) -> ExprSyntax { + var node = node + node.statements = visit(node.statements) - override func visit(_ node: ClosureExprSyntax) -> ExprSyntax { - var node = node - node.statements = visit(node.statements) + guard + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), + node.shouldCheckForClosureSpacingRule(locationConverter: locationConverter) + else { + return super.visit(node) + } - guard - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), - node.shouldCheckForClosureSpacingRule(locationConverter: locationConverter) - else { - return super.visit(node) - } + let violations = node.violations + if violations.leftBraceLeftSpace { + node.leftBrace = node.leftBrace.with(\.leadingTrivia, .spaces(1)) + } + if violations.leftBraceRightSpace { + node.leftBrace = node.leftBrace.with(\.trailingTrivia, .spaces(1)) + } + if violations.rightBraceLeftSpace { + node.rightBrace = node.rightBrace.with(\.leadingTrivia, .spaces(1)) + } + if violations.rightBraceRightSpace { + node.rightBrace = node.rightBrace.with(\.trailingTrivia, .spaces(1)) + } + if violations.hasViolations { + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + } - let violations = node.violations - if violations.leftBraceLeftSpace { - node.leftBrace = node.leftBrace.with(\.leadingTrivia, .spaces(1)) - } - if violations.leftBraceRightSpace { - node.leftBrace = node.leftBrace.with(\.trailingTrivia, .spaces(1)) - } - if violations.rightBraceLeftSpace { - node.rightBrace = node.rightBrace.with(\.leadingTrivia, .spaces(1)) - } - if violations.rightBraceRightSpace { - node.rightBrace = node.rightBrace.with(\.trailingTrivia, .spaces(1)) - } - if violations.hasViolations { - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + return super.visit(node) } - - return super.visit(node) } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/ComputedAccessorsOrderRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/ComputedAccessorsOrderRule.swift index cbd0295af2..daf8411828 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/ComputedAccessorsOrderRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/ComputedAccessorsOrderRule.swift @@ -13,48 +13,50 @@ struct ComputedAccessorsOrderRule: ConfigurationProviderRule, SwiftSyntaxRule { ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - ComputedAccessorsOrderRuleVisitor(expectedOrder: configuration.order) + Visitor(expectedOrder: configuration.order) } } -private final class ComputedAccessorsOrderRuleVisitor: ViolationsSyntaxVisitor { - enum ViolationKind { +private extension ComputedAccessorsOrderRule { + private enum ViolationKind { case `subscript`, property } - private let expectedOrder: ComputedAccessorsOrderConfiguration.Order + final class Visitor: ViolationsSyntaxVisitor { + private let expectedOrder: ComputedAccessorsOrderConfiguration.Order - init(expectedOrder: ComputedAccessorsOrderConfiguration.Order) { - self.expectedOrder = expectedOrder - super.init(viewMode: .sourceAccurate) - } - - override func visitPost(_ node: AccessorBlockSyntax) { - guard let firstAccessor = node.accessorsList.first, - let order = node.order, - order != expectedOrder else { - return + init(expectedOrder: ComputedAccessorsOrderConfiguration.Order) { + self.expectedOrder = expectedOrder + super.init(viewMode: .sourceAccurate) } - let kind: ViolationKind = node.parent?.as(SubscriptDeclSyntax.self) == nil ? .property : .subscript - violations.append( - ReasonedRuleViolation( - position: firstAccessor.positionAfterSkippingLeadingTrivia, - reason: reason(for: kind) + override func visitPost(_ node: AccessorBlockSyntax) { + guard let firstAccessor = node.accessorsList.first, + let order = node.order, + order != expectedOrder else { + return + } + + let kind: ViolationKind = node.parent?.as(SubscriptDeclSyntax.self) == nil ? .property : .subscript + violations.append( + ReasonedRuleViolation( + position: firstAccessor.positionAfterSkippingLeadingTrivia, + reason: reason(for: kind) + ) ) - ) - } + } - private func reason(for kind: ComputedAccessorsOrderRuleVisitor.ViolationKind) -> String { - let kindString = kind == .subscript ? "subscripts" : "properties" - let orderString: String - switch expectedOrder { - case .getSet: - orderString = "getter and then the setter" - case .setGet: - orderString = "setter and then the getter" + private func reason(for kind: ViolationKind) -> String { + let kindString = kind == .subscript ? "subscripts" : "properties" + let orderString: String + switch expectedOrder { + case .getSet: + orderString = "getter and then the setter" + case .setGet: + orderString = "setter and then the getter" + } + return "Computed \(kindString) should first declare the \(orderString)" } - return "Computed \(kindString) should first declare the \(orderString)" } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/ControlStatementRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/ControlStatementRule.swift index b7d91864c4..a4c579bd05 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/ControlStatementRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/ControlStatementRule.swift @@ -80,108 +80,110 @@ struct ControlStatementRule: ConfigurationProviderRule, SwiftSyntaxCorrectableRu } } -private final class Visitor: ViolationsSyntaxVisitor { - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } +private extension ControlStatementRule { + final class Visitor: ViolationsSyntaxVisitor { + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } - override func visitPost(_ node: CatchClauseSyntax) { - if node.catchItems.containSuperfluousParens == true { - violations.append(node.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: CatchClauseSyntax) { + if node.catchItems.containSuperfluousParens == true { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } - } - override func visitPost(_ node: GuardStmtSyntax) { - if node.conditions.containSuperfluousParens { - violations.append(node.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: GuardStmtSyntax) { + if node.conditions.containSuperfluousParens { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } - } - override func visitPost(_ node: IfExprSyntax) { - if node.conditions.containSuperfluousParens { - violations.append(node.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: IfExprSyntax) { + if node.conditions.containSuperfluousParens { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } - } - override func visitPost(_ node: SwitchExprSyntax) { - if node.subject.unwrapped != nil { - violations.append(node.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: SwitchExprSyntax) { + if node.subject.unwrapped != nil { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } - } - override func visitPost(_ node: WhileStmtSyntax) { - if node.conditions.containSuperfluousParens { - violations.append(node.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: WhileStmtSyntax) { + if node.conditions.containSuperfluousParens { + violations.append(node.positionAfterSkippingLeadingTrivia) + } } } -} -private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions + } - override func visit(_ node: CatchClauseSyntax) -> CatchClauseSyntax { - guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), - case let items = node.catchItems, items.containSuperfluousParens == true else { + override func visit(_ node: CatchClauseSyntax) -> CatchClauseSyntax { + guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), + case let items = node.catchItems, items.containSuperfluousParens == true else { + return super.visit(node) + } + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let node = node + .with(\.catchKeyword, node.catchKeyword.with(\.trailingTrivia, .space)) + .with(\.catchItems, items.withoutParens) return super.visit(node) } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let node = node - .with(\.catchKeyword, node.catchKeyword.with(\.trailingTrivia, .space)) - .with(\.catchItems, items.withoutParens) - return super.visit(node) - } - override func visit(_ node: GuardStmtSyntax) -> StmtSyntax { - guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), - node.conditions.containSuperfluousParens else { + override func visit(_ node: GuardStmtSyntax) -> StmtSyntax { + guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), + node.conditions.containSuperfluousParens else { + return super.visit(node) + } + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let node = node + .with(\.guardKeyword, node.guardKeyword.with(\.trailingTrivia, .space)) + .with(\.conditions, node.conditions.withoutParens) return super.visit(node) } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let node = node - .with(\.guardKeyword, node.guardKeyword.with(\.trailingTrivia, .space)) - .with(\.conditions, node.conditions.withoutParens) - return super.visit(node) - } - override func visit(_ node: IfExprSyntax) -> ExprSyntax { - guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), - node.conditions.containSuperfluousParens else { + override func visit(_ node: IfExprSyntax) -> ExprSyntax { + guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), + node.conditions.containSuperfluousParens else { + return super.visit(node) + } + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let node = node + .with(\.ifKeyword, node.ifKeyword.with(\.trailingTrivia, .space)) + .with(\.conditions, node.conditions.withoutParens) return super.visit(node) } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let node = node - .with(\.ifKeyword, node.ifKeyword.with(\.trailingTrivia, .space)) - .with(\.conditions, node.conditions.withoutParens) - return super.visit(node) - } - override func visit(_ node: SwitchExprSyntax) -> ExprSyntax { - guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), - let tupleElement = node.subject.unwrapped else { + override func visit(_ node: SwitchExprSyntax) -> ExprSyntax { + guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), + let tupleElement = node.subject.unwrapped else { + return super.visit(node) + } + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let node = node + .with(\.switchKeyword, node.switchKeyword.with(\.trailingTrivia, .space)) + .with(\.subject, tupleElement.with(\.trailingTrivia, .space)) return super.visit(node) } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let node = node - .with(\.switchKeyword, node.switchKeyword.with(\.trailingTrivia, .space)) - .with(\.subject, tupleElement.with(\.trailingTrivia, .space)) - return super.visit(node) - } - override func visit(_ node: WhileStmtSyntax) -> StmtSyntax { - guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), - node.conditions.containSuperfluousParens else { + override func visit(_ node: WhileStmtSyntax) -> StmtSyntax { + guard !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), + node.conditions.containSuperfluousParens else { + return super.visit(node) + } + correctionPositions.append(node.positionAfterSkippingLeadingTrivia) + let node = node + .with(\.whileKeyword, node.whileKeyword.with(\.trailingTrivia, .space)) + .with(\.conditions, node.conditions.withoutParens) return super.visit(node) } - correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let node = node - .with(\.whileKeyword, node.whileKeyword.with(\.trailingTrivia, .space)) - .with(\.conditions, node.conditions.withoutParens) - return super.visit(node) } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/DirectReturnRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/DirectReturnRule.swift index e120b25e15..6fcc75041d 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/DirectReturnRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/DirectReturnRule.swift @@ -187,12 +187,82 @@ struct DirectReturnRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule, } } -private class Visitor: ViolationsSyntaxVisitor { - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } +private extension DirectReturnRule { + final class Visitor: ViolationsSyntaxVisitor { + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } - override func visitPost(_ statements: CodeBlockItemListSyntax) { - if let (binding, _) = statements.violation { - violations.append(binding.positionAfterSkippingLeadingTrivia) + override func visitPost(_ statements: CodeBlockItemListSyntax) { + if let (binding, _) = statements.violation { + violations.append(binding.positionAfterSkippingLeadingTrivia) + } + } + } + + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] + + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions + } + + override func visit(_ statements: CodeBlockItemListSyntax) -> CodeBlockItemListSyntax { + guard let (binding, returnStmt) = statements.violation, + !binding.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), + let bindingList = binding.parent?.as(PatternBindingListSyntax.self), + let varDecl = bindingList.parent?.as(VariableDeclSyntax.self), + var initExpression = binding.initializer?.value else { + return super.visit(statements) + } + correctionPositions.append(binding.positionAfterSkippingLeadingTrivia) + var newStmtList = Array(statements.dropLast(2)) + let newBindingList = bindingList + .filter { $0 != binding } + .enumerated() + .map { index, item in + if index == bindingList.count - 2 { + return item.with(\.trailingComma, nil) + } + return item + } + if let type = binding.typeAnnotation?.type { + initExpression = ExprSyntax( + fromProtocol: AsExprSyntax( + expression: initExpression.trimmed, + asKeyword: .keyword(.as).with(\.leadingTrivia, .space).with(\.trailingTrivia, .space), + type: type.trimmed + ) + ) + } + if newBindingList.isNotEmpty { + newStmtList.append(CodeBlockItemSyntax( + item: .decl(DeclSyntax(varDecl.with(\.bindings, PatternBindingListSyntax(newBindingList)))) + )) + newStmtList.append(CodeBlockItemSyntax( + item: .stmt(StmtSyntax(returnStmt.with(\.expression, initExpression))) + )) + } else { + let leadingTrivia = varDecl.leadingTrivia.withoutTrailingIndentation + + returnStmt.leadingTrivia.withFirstEmptyLineRemoved + let trailingTrivia = varDecl.trailingTrivia.withoutTrailingIndentation + + returnStmt.trailingTrivia + + newStmtList.append( + CodeBlockItemSyntax( + item: .stmt( + StmtSyntax( + returnStmt + .with(\.expression, initExpression) + .with(\.leadingTrivia, leadingTrivia) + .with(\.trailingTrivia, trailingTrivia) + ) + ) + ) + ) + } + return super.visit(CodeBlockItemListSyntax(newStmtList)) } } } @@ -214,70 +284,3 @@ private extension CodeBlockItemListSyntax { return nil } } -private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] - - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } - - override func visit(_ statements: CodeBlockItemListSyntax) -> CodeBlockItemListSyntax { - guard let (binding, returnStmt) = statements.violation, - !binding.isContainedIn(regions: disabledRegions, locationConverter: locationConverter), - let bindingList = binding.parent?.as(PatternBindingListSyntax.self), - let varDecl = bindingList.parent?.as(VariableDeclSyntax.self), - var initExpression = binding.initializer?.value else { - return super.visit(statements) - } - correctionPositions.append(binding.positionAfterSkippingLeadingTrivia) - var newStmtList = Array(statements.dropLast(2)) - let newBindingList = bindingList - .filter { $0 != binding } - .enumerated() - .map { index, item in - if index == bindingList.count - 2 { - return item.with(\.trailingComma, nil) - } - return item - } - if let type = binding.typeAnnotation?.type { - initExpression = ExprSyntax( - fromProtocol: AsExprSyntax( - expression: initExpression.trimmed, - asKeyword: .keyword(.as).with(\.leadingTrivia, .space).with(\.trailingTrivia, .space), - type: type.trimmed - ) - ) - } - if newBindingList.isNotEmpty { - newStmtList.append(CodeBlockItemSyntax( - item: .decl(DeclSyntax(varDecl.with(\.bindings, PatternBindingListSyntax(newBindingList)))) - )) - newStmtList.append(CodeBlockItemSyntax( - item: .stmt(StmtSyntax(returnStmt.with(\.expression, initExpression))) - )) - } else { - let leadingTrivia = varDecl.leadingTrivia.withoutTrailingIndentation + - returnStmt.leadingTrivia.withFirstEmptyLineRemoved - let trailingTrivia = varDecl.trailingTrivia.withoutTrailingIndentation + - returnStmt.trailingTrivia - - newStmtList.append( - CodeBlockItemSyntax( - item: .stmt( - StmtSyntax( - returnStmt - .with(\.expression, initExpression) - .with(\.leadingTrivia, leadingTrivia) - .with(\.trailingTrivia, trailingTrivia) - ) - ) - ) - ) - } - return super.visit(CodeBlockItemListSyntax(newStmtList)) - } -} diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift index a43c6b9509..205edb22c8 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift @@ -64,7 +64,7 @@ private extension EmptyParenthesesWithTrailingClosureRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitGetterRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitGetterRule.swift index 34c0abfc20..89dcf2ba44 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitGetterRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitGetterRule.swift @@ -13,12 +13,12 @@ struct ImplicitGetterRule: ConfigurationProviderRule, SwiftSyntaxRule { ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - ImplicitGetterRuleVisitor(viewMode: .sourceAccurate) + Visitor(viewMode: .sourceAccurate) } } -private final class ImplicitGetterRuleVisitor: ViolationsSyntaxVisitor { - enum ViolationKind { +private extension ImplicitGetterRule { + private enum ViolationKind { case `subscript`, property var violationDescription: String { @@ -31,22 +31,24 @@ private final class ImplicitGetterRuleVisitor: ViolationsSyntaxVisitor { } } - override func visitPost(_ node: AccessorBlockSyntax) { - guard let getAccessor = node.getAccessor, - node.setAccessor == nil, - getAccessor.effectSpecifiers == nil, - getAccessor.modifier == nil, - getAccessor.attributes.isEmpty == true, - getAccessor.body != nil else { - return - } + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: AccessorBlockSyntax) { + guard let getAccessor = node.getAccessor, + node.setAccessor == nil, + getAccessor.effectSpecifiers == nil, + getAccessor.modifier == nil, + getAccessor.attributes.isEmpty == true, + getAccessor.body != nil else { + return + } - let kind: ViolationKind = node.parent?.as(SubscriptDeclSyntax.self) == nil ? .property : .subscript - violations.append( - ReasonedRuleViolation( - position: getAccessor.positionAfterSkippingLeadingTrivia, - reason: kind.violationDescription + let kind: ViolationKind = node.parent?.as(SubscriptDeclSyntax.self) == nil ? .property : .subscript + violations.append( + ReasonedRuleViolation( + position: getAccessor.positionAfterSkippingLeadingTrivia, + reason: kind.violationDescription + ) ) - ) + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitReturnRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitReturnRule.swift index 11840252df..b34c5e0bab 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitReturnRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/ImplicitReturnRule.swift @@ -19,7 +19,7 @@ struct ImplicitReturnRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule } private extension ImplicitReturnRule { - private class Visitor: ViolationsSyntaxVisitor { + final class Visitor: ViolationsSyntaxVisitor { private let config: ConfigurationType override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/NonOverridableClassDeclarationRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/NonOverridableClassDeclarationRule.swift index 42acfed61c..f68b067f62 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/NonOverridableClassDeclarationRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/NonOverridableClassDeclarationRule.swift @@ -100,55 +100,57 @@ struct NonOverridableClassDeclarationRule: SwiftSyntaxCorrectableRule, Configura } } -private class Visitor: ViolationsSyntaxVisitor { - private let configuration: NonOverridableClassDeclarationConfiguration +private extension NonOverridableClassDeclarationRule { + final class Visitor: ViolationsSyntaxVisitor { + private let configuration: NonOverridableClassDeclarationConfiguration - private var finalClassScope = Stack() + private var finalClassScope = Stack() - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } - init(configuration: NonOverridableClassDeclarationConfiguration) { - self.configuration = configuration - super.init(viewMode: .sourceAccurate) - } - - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - finalClassScope.push(node.modifiers.contains(keyword: .final)) - return .visitChildren - } + init(configuration: NonOverridableClassDeclarationConfiguration) { + self.configuration = configuration + super.init(viewMode: .sourceAccurate) + } - override func visitPost(_ node: ClassDeclSyntax) { - _ = finalClassScope.pop() - } + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + finalClassScope.push(node.modifiers.contains(keyword: .final)) + return .visitChildren + } - override func visitPost(_ node: FunctionDeclSyntax) { - checkViolations(for: node.modifiers, types: "methods") - } + override func visitPost(_ node: ClassDeclSyntax) { + _ = finalClassScope.pop() + } - override func visitPost(_ node: VariableDeclSyntax) { - checkViolations(for: node.modifiers, types: "properties") - } + override func visitPost(_ node: FunctionDeclSyntax) { + checkViolations(for: node.modifiers, types: "methods") + } - private func checkViolations(for modifiers: DeclModifierListSyntax, types: String) { - guard !modifiers.contains(keyword: .final), - let classKeyword = modifiers.first(where: { $0.name.text == "class" }), - case let inFinalClass = finalClassScope.peek() == true, - inFinalClass || modifiers.contains(keyword: .private) else { - return + override func visitPost(_ node: VariableDeclSyntax) { + checkViolations(for: node.modifiers, types: "properties") } - violations.append(ReasonedRuleViolation( - position: classKeyword.positionAfterSkippingLeadingTrivia, - reason: inFinalClass + + private func checkViolations(for modifiers: DeclModifierListSyntax, types: String) { + guard !modifiers.contains(keyword: .final), + let classKeyword = modifiers.first(where: { $0.name.text == "class" }), + case let inFinalClass = finalClassScope.peek() == true, + inFinalClass || modifiers.contains(keyword: .private) else { + return + } + violations.append(ReasonedRuleViolation( + position: classKeyword.positionAfterSkippingLeadingTrivia, + reason: inFinalClass ? "Class \(types) in final classes should themselves be final" : "Private class methods and properties should be declared final", - severity: configuration.severity - )) - violationCorrections.append( - ViolationCorrection( - start: classKeyword.positionAfterSkippingLeadingTrivia, - end: classKeyword.endPositionBeforeTrailingTrivia, - replacement: configuration.finalClassModifier.rawValue + severity: configuration.severity + )) + violationCorrections.append( + ViolationCorrection( + start: classKeyword.positionAfterSkippingLeadingTrivia, + end: classKeyword.endPositionBeforeTrailingTrivia, + replacement: configuration.finalClassModifier.rawValue + ) ) - ) + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/NumberSeparatorRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/NumberSeparatorRule.swift index 570263f3b8..b1aeb53f18 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/NumberSeparatorRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/NumberSeparatorRule.swift @@ -60,7 +60,7 @@ private extension NumberSeparatorRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter, NumberSeparatorValidator { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter, NumberSeparatorValidator { private(set) var correctionPositions: [AbsolutePosition] = [] let configuration: NumberSeparatorConfiguration let locationConverter: SourceLocationConverter diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfInStaticReferencesRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfInStaticReferencesRule.swift index 67407d5b2a..08492a8c7b 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfInStaticReferencesRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfInStaticReferencesRule.swift @@ -15,7 +15,7 @@ struct PreferSelfInStaticReferencesRule: SwiftSyntaxCorrectableRule, Configurati ) } -private class Visitor: ViolationsSyntaxVisitor { +private extension PreferSelfInStaticReferencesRule { private enum ParentDeclBehavior { case likeClass(name: String) case likeStruct(String) @@ -35,193 +35,195 @@ private class Visitor: ViolationsSyntaxVisitor { case skipReferences } - private var parentDeclScopes = Stack() - private var variableDeclScopes = Stack() + final class Visitor: ViolationsSyntaxVisitor { + private var parentDeclScopes = Stack() + private var variableDeclScopes = Stack() - override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { - parentDeclScopes.push(.likeClass(name: node.name.text)) - return .skipChildren - } - - override func visitPost(_ node: ActorDeclSyntax) { - parentDeclScopes.pop() - } - - override func visit(_ node: AttributeSyntax) -> SyntaxVisitorContinueKind { - if case .skipReferences = variableDeclScopes.peek() { + override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { + parentDeclScopes.push(.likeClass(name: node.name.text)) return .skipChildren } - return .visitChildren - } - - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - parentDeclScopes.push(.likeClass(name: node.name.text)) - return .visitChildren - } - - override func visitPost(_ node: ClassDeclSyntax) { - parentDeclScopes.pop() - } - override func visit(_ node: CodeBlockItemListSyntax) -> SyntaxVisitorContinueKind { - variableDeclScopes.push(.handleReferences) - return .visitChildren - } + override func visitPost(_ node: ActorDeclSyntax) { + parentDeclScopes.pop() + } - override func visitPost(_ node: CodeBlockItemListSyntax) { - variableDeclScopes.pop() - } + override func visit(_ node: AttributeSyntax) -> SyntaxVisitorContinueKind { + if case .skipReferences = variableDeclScopes.peek() { + return .skipChildren + } + return .visitChildren + } - override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { - parentDeclScopes.push(.likeStruct(node.name.text)) - return .visitChildren - } + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + parentDeclScopes.push(.likeClass(name: node.name.text)) + return .visitChildren + } - override func visitPost(_ node: EnumDeclSyntax) { - parentDeclScopes.pop() - } + override func visitPost(_ node: ClassDeclSyntax) { + parentDeclScopes.pop() + } - override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { - parentDeclScopes.push(.skipReferences) - return .visitChildren - } + override func visit(_ node: CodeBlockItemListSyntax) -> SyntaxVisitorContinueKind { + variableDeclScopes.push(.handleReferences) + return .visitChildren + } - override func visitPost(_ node: ExtensionDeclSyntax) { - parentDeclScopes.pop() - } + override func visitPost(_ node: CodeBlockItemListSyntax) { + variableDeclScopes.pop() + } - override func visit(_ node: MemberAccessExprSyntax) -> SyntaxVisitorContinueKind { - if case .likeClass = parentDeclScopes.peek() { - if node.declName.baseName.tokenKind == .keyword(.self) { - return .skipChildren - } + override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { + parentDeclScopes.push(.likeStruct(node.name.text)) + return .visitChildren } - return .visitChildren - } - override func visitPost(_ node: DeclReferenceExprSyntax) { - guard let parent = node.parent, !parent.is(GenericSpecializationExprSyntax.self), - node.keyPathInParent != \MemberAccessExprSyntax.declName else { - return + override func visitPost(_ node: EnumDeclSyntax) { + parentDeclScopes.pop() } - if parent.is(FunctionCallExprSyntax.self), case .likeClass = parentDeclScopes.peek() { - return + + override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind { + parentDeclScopes.push(.skipReferences) + return .visitChildren } - addViolation(on: node.baseName) - } - override func visit(_ node: InitializerClauseSyntax) -> SyntaxVisitorContinueKind { - if case .skipReferences = variableDeclScopes.peek() { - return .skipChildren + override func visitPost(_ node: ExtensionDeclSyntax) { + parentDeclScopes.pop() } - return .visitChildren - } - override func visit(_ node: MemberBlockSyntax) -> SyntaxVisitorContinueKind { - if case .likeClass = parentDeclScopes.peek() { - variableDeclScopes.push(.skipReferences) - } else { - variableDeclScopes.push(.handleReferences) + override func visit(_ node: MemberAccessExprSyntax) -> SyntaxVisitorContinueKind { + if case .likeClass = parentDeclScopes.peek() { + if node.declName.baseName.tokenKind == .keyword(.self) { + return .skipChildren + } + } + return .visitChildren } - return .visitChildren - } - override func visitPost(_ node: MemberBlockSyntax) { - variableDeclScopes.pop() - } + override func visitPost(_ node: DeclReferenceExprSyntax) { + guard let parent = node.parent, !parent.is(GenericSpecializationExprSyntax.self), + node.keyPathInParent != \MemberAccessExprSyntax.declName else { + return + } + if parent.is(FunctionCallExprSyntax.self), case .likeClass = parentDeclScopes.peek() { + return + } + addViolation(on: node.baseName) + } - override func visit(_ node: MacroExpansionExprSyntax) -> SyntaxVisitorContinueKind { - if case .likeClass = parentDeclScopes.peek(), case .identifier("selector") = node.macroName.tokenKind { + override func visit(_ node: InitializerClauseSyntax) -> SyntaxVisitorContinueKind { + if case .skipReferences = variableDeclScopes.peek() { + return .skipChildren + } return .visitChildren } - return .skipChildren - } - override func visit(_ node: FunctionParameterClauseSyntax) -> SyntaxVisitorContinueKind { - if case .likeStruct = parentDeclScopes.peek() { + override func visit(_ node: MemberBlockSyntax) -> SyntaxVisitorContinueKind { + if case .likeClass = parentDeclScopes.peek() { + variableDeclScopes.push(.skipReferences) + } else { + variableDeclScopes.push(.handleReferences) + } return .visitChildren } - return .skipChildren - } - override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { - parentDeclScopes.push(.skipReferences) - return .skipChildren - } + override func visitPost(_ node: MemberBlockSyntax) { + variableDeclScopes.pop() + } - override func visitPost(_ node: ProtocolDeclSyntax) { - parentDeclScopes.pop() - } + override func visit(_ node: MacroExpansionExprSyntax) -> SyntaxVisitorContinueKind { + if case .likeClass = parentDeclScopes.peek(), case .identifier("selector") = node.macroName.tokenKind { + return .visitChildren + } + return .skipChildren + } - override func visit(_ node: ReturnClauseSyntax) -> SyntaxVisitorContinueKind { - if case .likeStruct = parentDeclScopes.peek() { - return .visitChildren + override func visit(_ node: FunctionParameterClauseSyntax) -> SyntaxVisitorContinueKind { + if case .likeStruct = parentDeclScopes.peek() { + return .visitChildren + } + return .skipChildren } - return .skipChildren - } - override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { - parentDeclScopes.push(.likeStruct(node.name.text)) - return .visitChildren - } + override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind { + parentDeclScopes.push(.skipReferences) + return .skipChildren + } - override func visitPost(_ node: StructDeclSyntax) { - parentDeclScopes.pop() - } + override func visitPost(_ node: ProtocolDeclSyntax) { + parentDeclScopes.pop() + } - override func visit(_ node: GenericArgumentListSyntax) -> SyntaxVisitorContinueKind { - if case .likeClass = parentDeclScopes.peek() { + override func visit(_ node: ReturnClauseSyntax) -> SyntaxVisitorContinueKind { + if case .likeStruct = parentDeclScopes.peek() { + return .visitChildren + } return .skipChildren } - return .visitChildren - } - override func visitPost(_ node: IdentifierTypeSyntax) { - guard let parent = node.parent else { - return + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + parentDeclScopes.push(.likeStruct(node.name.text)) + return .visitChildren } - if case .likeClass = parentDeclScopes.peek(), parent.is(GenericArgumentSyntax.self) { - // Type is a generic parameter in a class. - return + + override func visitPost(_ node: StructDeclSyntax) { + parentDeclScopes.pop() } - if node.genericArguments == nil { - // Type is specialized. - addViolation(on: node.name) + + override func visit(_ node: GenericArgumentListSyntax) -> SyntaxVisitorContinueKind { + if case .likeClass = parentDeclScopes.peek() { + return .skipChildren + } + return .visitChildren } - } - override func visit(_ node: TypeAliasDeclSyntax) -> SyntaxVisitorContinueKind { - if case .likeClass = parentDeclScopes.peek() { - return .skipChildren + override func visitPost(_ node: IdentifierTypeSyntax) { + guard let parent = node.parent else { + return + } + if case .likeClass = parentDeclScopes.peek(), parent.is(GenericArgumentSyntax.self) { + // Type is a generic parameter in a class. + return + } + if node.genericArguments == nil { + // Type is specialized. + addViolation(on: node.name) + } } - return .visitChildren - } - override func visit(_ node: TypeAnnotationSyntax) -> SyntaxVisitorContinueKind { - guard case .likeStruct = parentDeclScopes.peek() else { - return .skipChildren + override func visit(_ node: TypeAliasDeclSyntax) -> SyntaxVisitorContinueKind { + if case .likeClass = parentDeclScopes.peek() { + return .skipChildren + } + return .visitChildren } - if let varDecl = node.parent?.parent?.parent?.as(VariableDeclSyntax.self) { - if varDecl.parent?.is(CodeBlockItemSyntax.self) == true // Local variable declaration - || varDecl.bindings.onlyElement?.accessorBlock != nil // Computed property - || !node.type.is(IdentifierTypeSyntax.self) // Complex or collection type - { - return .visitChildren + + override func visit(_ node: TypeAnnotationSyntax) -> SyntaxVisitorContinueKind { + guard case .likeStruct = parentDeclScopes.peek() else { + return .skipChildren + } + if let varDecl = node.parent?.parent?.parent?.as(VariableDeclSyntax.self) { + if varDecl.parent?.is(CodeBlockItemSyntax.self) == true // Local variable declaration + || varDecl.bindings.onlyElement?.accessorBlock != nil // Computed property + || !node.type.is(IdentifierTypeSyntax.self) // Complex or collection type + { + return .visitChildren + } } + return .skipChildren } - return .skipChildren - } - private func addViolation(on node: TokenSyntax) { - if let parentName = parentDeclScopes.peek()?.parentName, node.tokenKind == .identifier(parentName) { - violations.append(node.positionAfterSkippingLeadingTrivia) - violationCorrections.append( - ViolationCorrection( - start: node.positionAfterSkippingLeadingTrivia, - end: node.endPositionBeforeTrailingTrivia, - replacement: "Self" + private func addViolation(on node: TokenSyntax) { + if let parentName = parentDeclScopes.peek()?.parentName, node.tokenKind == .identifier(parentName) { + violations.append(node.positionAfterSkippingLeadingTrivia) + violationCorrections.append( + ViolationCorrection( + start: node.positionAfterSkippingLeadingTrivia, + end: node.endPositionBeforeTrailingTrivia, + replacement: "Self" + ) ) - ) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift index fc7abd2931..87d9bcc150 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift @@ -123,7 +123,7 @@ private extension PreferSelfTypeOverTypeOfSelfRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift index e36b792d34..429e9593d2 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift @@ -46,7 +46,7 @@ private extension ProtocolPropertyAccessorsOrderRule { } } - private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { private(set) var correctionPositions: [AbsolutePosition] = [] let locationConverter: SourceLocationConverter let disabledRegions: [SourceRange] diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/RedundantSelfInClosureRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/RedundantSelfInClosureRule.swift index a5b55938da..238445075f 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/RedundantSelfInClosureRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/RedundantSelfInClosureRule.swift @@ -34,86 +34,88 @@ private enum SelfCaptureKind { case uncaptured } -private class ContextVisitor: DeclaredIdentifiersTrackingVisitor { - private var typeDeclarations = Stack() - private var functionCalls = Stack() - private var selfCaptures = Stack() +private extension RedundantSelfInClosureRule { + final class ContextVisitor: DeclaredIdentifiersTrackingVisitor { + private var typeDeclarations = Stack() + private var functionCalls = Stack() + private var selfCaptures = Stack() - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .extensionsAndProtocols } + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .extensionsAndProtocols } - override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { - typeDeclarations.push(.likeClass) - return .visitChildren - } + override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind { + typeDeclarations.push(.likeClass) + return .visitChildren + } - override func visitPost(_ node: ActorDeclSyntax) { - typeDeclarations.pop() - } + override func visitPost(_ node: ActorDeclSyntax) { + typeDeclarations.pop() + } - override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { - typeDeclarations.push(.likeClass) - return .visitChildren - } + override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { + typeDeclarations.push(.likeClass) + return .visitChildren + } - override func visitPost(_ node: ClassDeclSyntax) { - typeDeclarations.pop() - } + override func visitPost(_ node: ClassDeclSyntax) { + typeDeclarations.pop() + } - override func visit(_ node: ClosureExprSyntax) -> SyntaxVisitorContinueKind { - if let selfItem = node.signature?.capture?.items.first(where: \.capturesSelf) { - selfCaptures.push(selfItem.capturesWeakly ? .weak : .strong) - } else { - selfCaptures.push(.uncaptured) + override func visit(_ node: ClosureExprSyntax) -> SyntaxVisitorContinueKind { + if let selfItem = node.signature?.capture?.items.first(where: \.capturesSelf) { + selfCaptures.push(selfItem.capturesWeakly ? .weak : .strong) + } else { + selfCaptures.push(.uncaptured) + } + return .visitChildren } - return .visitChildren - } - override func visitPost(_ node: ClosureExprSyntax) { - guard let activeTypeDeclarationKind = typeDeclarations.peek(), - let activeFunctionCallType = functionCalls.peek(), - let activeSelfCaptureKind = selfCaptures.peek() else { - return + override func visitPost(_ node: ClosureExprSyntax) { + guard let activeTypeDeclarationKind = typeDeclarations.peek(), + let activeFunctionCallType = functionCalls.peek(), + let activeSelfCaptureKind = selfCaptures.peek() else { + return + } + let localViolationCorrections = ExplicitSelfVisitor( + typeDeclarationKind: activeTypeDeclarationKind, + functionCallType: activeFunctionCallType, + selfCaptureKind: activeSelfCaptureKind, + scope: scope + ).walk(tree: node.statements, handler: \.violationCorrections) + violations.append(contentsOf: localViolationCorrections.map(\.start)) + violationCorrections.append(contentsOf: localViolationCorrections) + selfCaptures.pop() } - let localViolationCorrections = ExplicitSelfVisitor( - typeDeclarationKind: activeTypeDeclarationKind, - functionCallType: activeFunctionCallType, - selfCaptureKind: activeSelfCaptureKind, - scope: scope - ).walk(tree: node.statements, handler: \.violationCorrections) - violations.append(contentsOf: localViolationCorrections.map(\.start)) - violationCorrections.append(contentsOf: localViolationCorrections) - selfCaptures.pop() - } - override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { - typeDeclarations.push(.likeStruct) - return .visitChildren - } + override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind { + typeDeclarations.push(.likeStruct) + return .visitChildren + } - override func visitPost(_ node: EnumDeclSyntax) { - typeDeclarations.pop() - } + override func visitPost(_ node: EnumDeclSyntax) { + typeDeclarations.pop() + } - override func visit(_ node: FunctionCallExprSyntax) -> SyntaxVisitorContinueKind { - if node.calledExpression.is(ClosureExprSyntax.self) { - functionCalls.push(.anonymousClosure) - } else { - functionCalls.push(.function) + override func visit(_ node: FunctionCallExprSyntax) -> SyntaxVisitorContinueKind { + if node.calledExpression.is(ClosureExprSyntax.self) { + functionCalls.push(.anonymousClosure) + } else { + functionCalls.push(.function) + } + return .visitChildren } - return .visitChildren - } - override func visitPost(_ node: FunctionCallExprSyntax) { - functionCalls.pop() - } + override func visitPost(_ node: FunctionCallExprSyntax) { + functionCalls.pop() + } - override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { - typeDeclarations.push(.likeStruct) - return .visitChildren - } + override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind { + typeDeclarations.push(.likeStruct) + return .visitChildren + } - override func visitPost(_ node: StructDeclSyntax) { - typeDeclarations.pop() + override func visitPost(_ node: StructDeclSyntax) { + typeDeclarations.pop() + } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/SelfBindingRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/SelfBindingRule.swift index 95abe84777..457a6f71e8 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/SelfBindingRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/SelfBindingRule.swift @@ -47,11 +47,11 @@ struct SelfBindingRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule, O ) func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor { - SelfBindingRuleVisitor(bindIdentifier: configuration.bindIdentifier) + Visitor(bindIdentifier: configuration.bindIdentifier) } func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? { - SelfBindingRuleRewriter( + Rewriter( bindIdentifier: configuration.bindIdentifier, locationConverter: file.locationConverter, disabledRegions: disabledRegions(file: file) @@ -59,98 +59,93 @@ struct SelfBindingRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule, O } } -// MARK: - SelfBindingRuleVisitor +private extension SelfBindingRule { + final class Visitor: ViolationsSyntaxVisitor { + private let bindIdentifier: String -private final class SelfBindingRuleVisitor: ViolationsSyntaxVisitor { - private let bindIdentifier: String - - init(bindIdentifier: String) { - self.bindIdentifier = bindIdentifier - super.init(viewMode: .sourceAccurate) - } - - override func visitPost(_ node: OptionalBindingConditionSyntax) { - if let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self), - identifierPattern.identifier.text != bindIdentifier { - var hasViolation = false - if let initializerIdentifier = node.initializer?.value.as(DeclReferenceExprSyntax.self) { - hasViolation = initializerIdentifier.baseName.text == "self" - } else if node.initializer == nil { - hasViolation = identifierPattern.identifier.text == "self" && bindIdentifier != "self" - } + init(bindIdentifier: String) { + self.bindIdentifier = bindIdentifier + super.init(viewMode: .sourceAccurate) + } - if hasViolation { - violations.append( - ReasonedRuleViolation( - position: identifierPattern.positionAfterSkippingLeadingTrivia, - reason: "`self` should always be re-bound to `\(bindIdentifier)`" + override func visitPost(_ node: OptionalBindingConditionSyntax) { + if let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self), + identifierPattern.identifier.text != bindIdentifier { + var hasViolation = false + if let initializerIdentifier = node.initializer?.value.as(DeclReferenceExprSyntax.self) { + hasViolation = initializerIdentifier.baseName.text == "self" + } else if node.initializer == nil { + hasViolation = identifierPattern.identifier.text == "self" && bindIdentifier != "self" + } + + if hasViolation { + violations.append( + ReasonedRuleViolation( + position: identifierPattern.positionAfterSkippingLeadingTrivia, + reason: "`self` should always be re-bound to `\(bindIdentifier)`" + ) ) - ) + } } } } -} -// MARK: - SelfBindingRuleRewriter + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + private let bindIdentifier: String + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] + + init(bindIdentifier: String, locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.bindIdentifier = bindIdentifier + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions + } -private final class SelfBindingRuleRewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - private let bindIdentifier: String - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] + override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax { + guard + let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self), + identifierPattern.identifier.text != bindIdentifier, + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) + else { + return super.visit(node) + } - init(bindIdentifier: String, locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.bindIdentifier = bindIdentifier - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + if let initializerIdentifier = node.initializer?.value.as(DeclReferenceExprSyntax.self), + initializerIdentifier.baseName.text == "self" { + correctionPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia) - override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax { - guard - let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self), - identifierPattern.identifier.text != bindIdentifier, - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) - else { - return super.visit(node) - } + let newPattern = PatternSyntax( + identifierPattern + .with(\.identifier, identifierPattern.identifier.with(\.tokenKind, .identifier(bindIdentifier))) + ) - if let initializerIdentifier = node.initializer?.value.as(DeclReferenceExprSyntax.self), - initializerIdentifier.baseName.text == "self" { - correctionPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia) + return super.visit(node.with(\.pattern, newPattern)) + } else if node.initializer == nil, identifierPattern.identifier.text == "self", bindIdentifier != "self" { + correctionPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia) - let newPattern = PatternSyntax( - identifierPattern - .with(\.identifier, - identifierPattern.identifier.with(\.tokenKind, .identifier(bindIdentifier)) + let newPattern = PatternSyntax( + identifierPattern + .with(\.identifier, identifierPattern.identifier.with(\.tokenKind, .identifier(bindIdentifier))) ) - ) - - return super.visit(node.with(\.pattern, newPattern)) - } else if node.initializer == nil, identifierPattern.identifier.text == "self", bindIdentifier != "self" { - correctionPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia) - - let newPattern = PatternSyntax( - identifierPattern - .with(\.identifier, - identifierPattern.identifier.with(\.tokenKind, .identifier(bindIdentifier))) - ) - - let newInitializer = InitializerClauseSyntax( - value: DeclReferenceExprSyntax( - baseName: .keyword( - .`self`, - leadingTrivia: .space, - trailingTrivia: identifierPattern.trailingTrivia + + let newInitializer = InitializerClauseSyntax( + value: DeclReferenceExprSyntax( + baseName: .keyword( + .`self`, + leadingTrivia: .space, + trailingTrivia: identifierPattern.trailingTrivia + ) ) ) - ) - - let newNode = node - .with(\.pattern, newPattern) - .with(\.initializer, newInitializer) - return super.visit(newNode) - } else { - return super.visit(node) + + let newNode = node + .with(\.pattern, newPattern) + .with(\.initializer, newInitializer) + return super.visit(newNode) + } else { + return super.visit(node) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/SuperfluousElseRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/SuperfluousElseRule.swift index 11f3df5723..69e8fe5e29 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/SuperfluousElseRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/SuperfluousElseRule.swift @@ -96,12 +96,14 @@ struct SuperfluousElseRule: ConfigurationProviderRule, OptInRule { ) } -private class Visitor: ViolationsSyntaxVisitor { - override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } +private extension SuperfluousElseRule { + final class Visitor: ViolationsSyntaxVisitor { + override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } - override func visitPost(_ node: IfExprSyntax) { - if node.violatesRule { - violations.append(node.ifKeyword.positionAfterSkippingLeadingTrivia) + override func visitPost(_ node: IfExprSyntax) { + if node.violatesRule { + violations.append(node.ifKeyword.positionAfterSkippingLeadingTrivia) + } } } } diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/SwitchCaseAlignmentRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/SwitchCaseAlignmentRule.swift index 807ba13470..09a77e8634 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/SwitchCaseAlignmentRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/SwitchCaseAlignmentRule.swift @@ -44,7 +44,7 @@ struct SwitchCaseAlignmentRule: SwiftSyntaxRule, ConfigurationProviderRule { } extension SwitchCaseAlignmentRule { - private final class Visitor: ViolationsSyntaxVisitor { + final class Visitor: ViolationsSyntaxVisitor { private let locationConverter: SourceLocationConverter private let indentedCases: Bool diff --git a/Source/SwiftLintBuiltInRules/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift b/Source/SwiftLintBuiltInRules/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift index 1a6265f3f7..b79c857735 100644 --- a/Source/SwiftLintBuiltInRules/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift +++ b/Source/SwiftLintBuiltInRules/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift @@ -81,50 +81,52 @@ struct UnneededParenthesesInClosureArgumentRule: ConfigurationProviderRule, Swif } } -private final class Visitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: ClosureSignatureSyntax) { - guard let clause = node.parameterClause?.as(ClosureParameterClauseSyntax.self), - clause.parameters.isNotEmpty, - clause.parameters.allSatisfy({ $0.type == nil }) else { - return - } +private extension UnneededParenthesesInClosureArgumentRule { + final class Visitor: ViolationsSyntaxVisitor { + override func visitPost(_ node: ClosureSignatureSyntax) { + guard let clause = node.parameterClause?.as(ClosureParameterClauseSyntax.self), + clause.parameters.isNotEmpty, + clause.parameters.allSatisfy({ $0.type == nil }) else { + return + } - violations.append(clause.positionAfterSkippingLeadingTrivia) + violations.append(clause.positionAfterSkippingLeadingTrivia) + } } -} - -private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { - private(set) var correctionPositions: [AbsolutePosition] = [] - let locationConverter: SourceLocationConverter - let disabledRegions: [SourceRange] - init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { - self.locationConverter = locationConverter - self.disabledRegions = disabledRegions - } + final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { + private(set) var correctionPositions: [AbsolutePosition] = [] + let locationConverter: SourceLocationConverter + let disabledRegions: [SourceRange] - override func visit(_ node: ClosureSignatureSyntax) -> ClosureSignatureSyntax { - guard - let clause = node.parameterClause?.as(ClosureParameterClauseSyntax.self), - clause.parameters.isNotEmpty, - clause.parameters.allSatisfy({ $0.type == nil }), - !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) - else { - return super.visit(node) + init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) { + self.locationConverter = locationConverter + self.disabledRegions = disabledRegions } - let items = clause.parameters.enumerated().compactMap { idx, param -> ClosureShorthandParameterSyntax? in - let name = param.firstName - let isLast = idx == clause.parameters.count - 1 - return ClosureShorthandParameterSyntax( - name: name, - trailingComma: isLast ? nil : .commaToken(trailingTrivia: Trivia(pieces: [.spaces(1)])) - ) - } + override func visit(_ node: ClosureSignatureSyntax) -> ClosureSignatureSyntax { + guard + let clause = node.parameterClause?.as(ClosureParameterClauseSyntax.self), + clause.parameters.isNotEmpty, + clause.parameters.allSatisfy({ $0.type == nil }), + !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) + else { + return super.visit(node) + } - correctionPositions.append(clause.positionAfterSkippingLeadingTrivia) + let items = clause.parameters.enumerated().compactMap { idx, param -> ClosureShorthandParameterSyntax? in + let name = param.firstName + let isLast = idx == clause.parameters.count - 1 + return ClosureShorthandParameterSyntax( + name: name, + trailingComma: isLast ? nil : .commaToken(trailingTrivia: Trivia(pieces: [.spaces(1)])) + ) + } - let paramList = ClosureShorthandParameterListSyntax(items).with(\.trailingTrivia, .spaces(1)) - return super.visit(node.with(\.parameterClause, .init(paramList))) + correctionPositions.append(clause.positionAfterSkippingLeadingTrivia) + + let paramList = ClosureShorthandParameterListSyntax(items).with(\.trailingTrivia, .spaces(1)) + return super.visit(node.with(\.parameterClause, .init(paramList))) + } } }