Let all rewriters have a configuration by default (#5467)

This commit is contained in:
Danny Mösch
2024-02-11 15:13:24 +01:00
committed by GitHub
parent c874c4e692
commit 4078e41f1b
54 changed files with 128 additions and 286 deletions
@@ -35,16 +35,16 @@ enum LegacyFunctionRuleHelper {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter<Configuration: RuleConfiguration>: ViolationsSyntaxRewriter<Configuration> {
private let legacyFunctions: [String: RewriteStrategy]
init(
legacyFunctions: [String: RewriteStrategy],
locationConverter: SourceLocationConverter,
disabledRegions: [SourceRange]
configuration: Configuration,
file: SwiftLintFile
) {
self.legacyFunctions = legacyFunctions
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
super.init(configuration: configuration, file: file)
}
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
@@ -35,12 +35,8 @@ struct DuplicateImportsRule: SwiftSyntaxCorrectableRule {
queuedFatalError("Unreachable: `validate(file:)` will be used instead")
}
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
importPositionsToRemove: file.duplicateImportsViolationPositions(),
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
Rewriter(configuration: configuration, file: file)
}
}
@@ -152,17 +148,8 @@ private extension SwiftLintFile {
}
private extension DuplicateImportsRule {
final class Rewriter: ViolationsSyntaxRewriter {
let importPositionsToRemove: [AbsolutePosition]
init(
importPositionsToRemove: [AbsolutePosition],
locationConverter: SourceLocationConverter,
disabledRegions: [SourceRange]
) {
self.importPositionsToRemove = importPositionsToRemove
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
private lazy var importPositionsToRemove = file.duplicateImportsViolationPositions()
override func visit(_ node: CodeBlockItemListSyntax) -> CodeBlockItemListSyntax {
let itemsToRemove = node
@@ -201,7 +201,7 @@ private extension ExplicitInitRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
guard let calledExpression = node.calledExpression.as(MemberAccessExprSyntax.self),
let violationPosition = calledExpression.explicitInitPosition,
@@ -47,7 +47,7 @@ private extension JoinedDefaultParameterRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
guard let violationPosition = node.violationPosition else {
return super.visit(node)
@@ -108,11 +108,11 @@ struct LegacyCGGeometryFunctionsRule: SwiftSyntaxCorrectableRule {
)
}
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
LegacyFunctionRuleHelper.Rewriter(
legacyFunctions: Self.legacyFunctions,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
configuration: configuration,
file: file
)
}
}
@@ -31,7 +31,7 @@ private extension LegacyConstantRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: DeclReferenceExprSyntax) -> ExprSyntax {
guard let correction = LegacyConstantRuleExamples.patterns[node.baseName.text] else {
return super.visit(node)
@@ -134,7 +134,7 @@ private extension LegacyConstructorRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
guard let identifierExpr = node.calledExpression.as(DeclReferenceExprSyntax.self),
case let identifier = identifierExpr.baseName.text,
@@ -108,11 +108,11 @@ struct LegacyNSGeometryFunctionsRule: SwiftSyntaxCorrectableRule {
)
}
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
LegacyFunctionRuleHelper.Rewriter(
legacyFunctions: Self.legacyFunctions,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
configuration: configuration,
file: file
)
}
}
@@ -80,7 +80,7 @@ private extension NimbleOperatorRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
guard let expectation = node.expectation(),
let predicate = predicatesMapping[expectation.operatorExpr.baseName.text],
@@ -45,7 +45,7 @@ private extension PreferZeroOverExplicitInitRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
guard node.hasViolation, let name = node.name else {
return super.visit(node)
@@ -1,7 +1,7 @@
import SwiftSyntax
@SwiftSyntaxRule
struct PrivateOverFilePrivateRule: SwiftSyntaxCorrectableRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct PrivateOverFilePrivateRule: Rule {
var configuration = PrivateOverFilePrivateConfiguration()
static let description = RuleDescription(
@@ -54,14 +54,6 @@ struct PrivateOverFilePrivateRule: SwiftSyntaxCorrectableRule {
Example("private class MyClass {\nfileprivate(set) var myInt = 4\n}")
]
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
validateExtensions: configuration.validateExtensions,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension PrivateOverFilePrivateRule {
@@ -123,17 +115,10 @@ private extension PrivateOverFilePrivateRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
private let validateExtensions: Bool
init(validateExtensions: Bool, locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) {
self.validateExtensions = validateExtensions
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
// don't call super in any of the `visit` methods to avoid digging into the children
override func visit(_ node: ExtensionDeclSyntax) -> DeclSyntax {
guard validateExtensions, let modifier = node.modifiers.fileprivateModifier,
guard configuration.validateExtensions, let modifier = node.modifiers.fileprivateModifier,
let modifierIndex = node.modifiers.fileprivateModifierIndex else {
return DeclSyntax(node)
}
@@ -33,7 +33,7 @@ private extension RedundantNilCoalescingRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ExprListSyntax) -> ExprListSyntax {
guard
node.count > 2,
@@ -118,7 +118,7 @@ private extension RedundantOptionalInitializationRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visitAny(_ node: Syntax) -> Syntax? { nil }
override func visit(_ node: VariableDeclSyntax) -> DeclSyntax {
@@ -1,7 +1,7 @@
import SwiftSyntax
@SwiftSyntaxRule
struct RedundantVoidReturnRule: SwiftSyntaxCorrectableRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct RedundantVoidReturnRule: Rule {
var configuration = RedundantVoidReturnConfiguration()
static let description = RuleDescription(
@@ -68,14 +68,6 @@ struct RedundantVoidReturnRule: SwiftSyntaxCorrectableRule {
Example("protocol Foo {\n #if true\n func foo()\n #endif\n}")
]
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
configuration: configuration,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension RedundantVoidReturnRule {
@@ -92,18 +84,7 @@ private extension RedundantVoidReturnRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
let configuration: ConfigurationType
init(
configuration: ConfigurationType,
locationConverter: SourceLocationConverter,
disabledRegions: [SourceRange]
) {
self.configuration = configuration
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ClosureSignatureSyntax) -> ClosureSignatureSyntax {
guard configuration.includeClosures,
let output = node.returnClause,
@@ -26,7 +26,7 @@ private extension ReturnValueFromVoidFunctionRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ statements: CodeBlockItemListSyntax) -> CodeBlockItemListSyntax {
guard let returnStmt = statements.last?.item.as(ReturnStmtSyntax.self),
let expr = returnStmt.expression,
@@ -90,7 +90,7 @@ private extension ShorthandOptionalBindingRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax {
guard node.isShadowingOptionalBinding else {
return super.visit(node)
@@ -40,7 +40,7 @@ private extension ToggleBoolRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ExprListSyntax) -> ExprListSyntax {
guard node.hasToggleBoolViolation, let firstExpr = node.first, let index = node.index(of: firstExpr) else {
return super.visit(node)
@@ -35,7 +35,7 @@ private extension TrailingSemicolonRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: TokenSyntax) -> TokenSyntax {
guard node.isTrailingSemicolon else {
return super.visit(node)
@@ -99,7 +99,7 @@ private extension UnneededBreakInSwitchRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: SwitchCaseSyntax) -> SwitchCaseSyntax {
let stmts = CodeBlockItemListSyntax(node.statements.dropLast())
@@ -46,7 +46,7 @@ private extension UnneededSynthesizedInitializerRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
private var unneededInitializers: [InitializerDeclSyntax] = []
override func visitAny(_ node: Syntax) -> Syntax? { nil }
@@ -119,7 +119,7 @@ private extension UntypedErrorInCatchRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: CatchClauseSyntax) -> CatchClauseSyntax {
guard let item = node.catchItems.onlyElement, item.isIdentifierPattern else {
return super.visit(node)
@@ -43,11 +43,8 @@ struct AnyObjectProtocolRule: SwiftSyntaxCorrectableRule, OptInRule {
return Visitor(configuration: configuration, file: file)
}
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
Rewriter(configuration: configuration, file: file)
}
}
@@ -58,7 +55,7 @@ private extension AnyObjectProtocolRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: InheritedTypeSyntax) -> InheritedTypeSyntax {
let typeName = node.type
guard typeName.is(ClassRestrictionTypeSyntax.self) else {
@@ -91,7 +91,7 @@ private extension LowerACLThanParentRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: DeclModifierSyntax) -> DeclModifierSyntax {
guard node.isHigherACLThanParent else {
return super.visit(node)
@@ -25,7 +25,7 @@ private extension MarkRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ token: TokenSyntax) -> TokenSyntax {
var pieces = token.leadingTrivia.pieces
for result in token.violationResults() {
@@ -1,8 +1,8 @@
import Foundation
import SwiftSyntax
@SwiftSyntaxRule
struct PrivateUnitTestRule: SwiftSyntaxCorrectableRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct PrivateUnitTestRule: Rule {
var configuration = PrivateUnitTestConfiguration()
static let description = RuleDescription(
@@ -125,14 +125,6 @@ struct PrivateUnitTestRule: SwiftSyntaxCorrectableRule {
""")
]
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
configuration: configuration,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension PrivateUnitTestRule {
@@ -156,16 +148,7 @@ private extension PrivateUnitTestRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
private let configuration: PrivateUnitTestConfiguration
init(configuration: PrivateUnitTestConfiguration,
locationConverter: SourceLocationConverter,
disabledRegions: [SourceRange]) {
self.configuration = configuration
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ClassDeclSyntax) -> DeclSyntax {
guard node.isPrivate, node.hasParent(configuredIn: configuration) else {
return super.visit(node)
@@ -38,7 +38,7 @@ private extension StrongIBOutletRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: VariableDeclSyntax) -> DeclSyntax {
guard let violationPosition = node.violationPosition,
let weakOrUnownedModifier = node.weakOrUnownedModifier,
@@ -31,7 +31,7 @@ private extension UnneededOverrideRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax {
guard node.isUnneededOverride else {
return super.visit(node)
@@ -33,7 +33,7 @@ private extension UnusedClosureParameterRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ClosureExprSyntax) -> ExprSyntax {
guard node.namedParameters.isNotEmpty,
let signature = node.signature,
@@ -94,7 +94,7 @@ private extension UnusedControlFlowLabelRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: LabeledStmtSyntax) -> StmtSyntax {
guard let violationPosition = node.violationPosition else {
return super.visit(node)
@@ -1,8 +1,8 @@
import SwiftLintCore
import SwiftSyntax
@SwiftSyntaxRule(foldExpressions: true)
struct EmptyCountRule: SwiftSyntaxCorrectableRule, OptInRule {
@SwiftSyntaxRule(foldExpressions: true, explicitRewriter: true)
struct EmptyCountRule: OptInRule {
var configuration = EmptyCountConfiguration()
static let description = RuleDescription(
@@ -64,14 +64,6 @@ struct EmptyCountRule: SwiftSyntaxCorrectableRule, OptInRule {
Example("[Int]().count != 3 && ![Int]().isEmpty || isEmpty && [Int]().count > 2")
]
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
configuration: configuration,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension EmptyCountRule {
@@ -87,16 +79,7 @@ private extension EmptyCountRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
private let configuration: EmptyCountConfiguration
init(configuration: EmptyCountConfiguration,
locationConverter: SourceLocationConverter,
disabledRegions: [SourceRange]) {
self.configuration = configuration
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: InfixOperatorExprSyntax) -> ExprSyntax {
guard let binaryOperator = node.binaryOperator, binaryOperator.isComparison else {
return super.visit(node)
@@ -1,8 +1,8 @@
import SwiftLintCore
import SwiftSyntax
@SwiftSyntaxRule
struct FinalTestCaseRule: SwiftSyntaxCorrectableRule, OptInRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct FinalTestCaseRule: OptInRule {
var configuration = FinalTestCaseConfiguration()
static var description = RuleDescription(
@@ -29,14 +29,6 @@ struct FinalTestCaseRule: SwiftSyntaxCorrectableRule, OptInRule {
Example("internal final class Test: XCTestCase {}")
]
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
configuration: configuration,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension FinalTestCaseRule {
@@ -48,16 +40,7 @@ private extension FinalTestCaseRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
private let configuration: FinalTestCaseConfiguration
init(configuration: FinalTestCaseConfiguration,
locationConverter: SourceLocationConverter,
disabledRegions: [SourceRange]) {
self.configuration = configuration
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ClassDeclSyntax) -> DeclSyntax {
var newNode = node
if node.isNonFinalTestClass(parentClasses: configuration.testParentClasses) {
@@ -32,7 +32,7 @@ private extension ClosingBraceRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: TokenSyntax) -> TokenSyntax {
guard node.hasClosingBraceViolation else {
return super.visit(node)
@@ -56,7 +56,7 @@ private extension ClosureSpacingRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ClosureExprSyntax) -> ExprSyntax {
var node = node
node.statements = visit(node.statements)
@@ -108,7 +108,7 @@ private extension ControlStatementRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: CatchClauseSyntax) -> CatchClauseSyntax {
guard case let items = node.catchItems, items.containSuperfluousParens == true else {
return super.visit(node)
@@ -191,7 +191,7 @@ private extension DirectReturnRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ statements: CodeBlockItemListSyntax) -> CodeBlockItemListSyntax {
guard let (binding, returnStmt) = statements.violation,
let bindingList = binding.parent?.as(PatternBindingListSyntax.self),
@@ -128,7 +128,7 @@ private extension EmptyEnumArgumentsRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: SwitchCaseItemSyntax) -> SwitchCaseItemSyntax {
guard let (violationPosition, newPattern) = node.pattern.emptyEnumArgumentsViolation(rewrite: true) else {
return super.visit(node)
@@ -44,7 +44,7 @@ private extension EmptyParametersRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionTypeSyntax) -> TypeSyntax {
guard let violationPosition = node.emptyParametersViolationPosition else {
return super.visit(node)
@@ -57,7 +57,7 @@ private extension EmptyParenthesesWithTrailingClosureRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
guard let violationPosition = node.violationPosition else {
return super.visit(node)
@@ -56,7 +56,7 @@ private extension NoSpaceInMethodCallRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax {
guard node.hasNoSpaceInMethodCallViolation else {
return super.visit(node)
@@ -1,8 +1,8 @@
import Foundation
import SwiftSyntax
@SwiftSyntaxRule
struct NumberSeparatorRule: OptInRule, SwiftSyntaxCorrectableRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct NumberSeparatorRule: OptInRule {
var configuration = NumberSeparatorConfiguration()
static let description = RuleDescription(
@@ -25,14 +25,6 @@ struct NumberSeparatorRule: OptInRule, SwiftSyntaxCorrectableRule {
static let misplacedSeparatorsReason = """
Underscore(s) used as thousand separator(s) should be added after every 3 digits only
"""
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
configuration: configuration,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension NumberSeparatorRule {
@@ -50,16 +42,7 @@ private extension NumberSeparatorRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter, NumberSeparatorValidator {
let configuration: NumberSeparatorConfiguration
init(configuration: NumberSeparatorConfiguration,
locationConverter: SourceLocationConverter,
disabledRegions: [SourceRange]) {
self.configuration = configuration
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType>, NumberSeparatorValidator {
override func visit(_ node: FloatLiteralExprSyntax) -> ExprSyntax {
guard let violation = violation(token: node.literal) else {
return super.visit(node)
@@ -174,7 +174,7 @@ private extension OptionalEnumCaseMatchingRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: SwitchCaseItemSyntax) -> SwitchCaseItemSyntax {
guard
let pattern = node.pattern.as(ExpressionPatternSyntax.self),
@@ -116,7 +116,7 @@ private extension PreferSelfTypeOverTypeOfSelfRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: MemberAccessExprSyntax) -> ExprSyntax {
guard let function = node.base?.as(FunctionCallExprSyntax.self), function.hasViolation else {
return super.visit(node)
@@ -39,7 +39,7 @@ private extension ProtocolPropertyAccessorsOrderRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: AccessorBlockSyntax) -> AccessorBlockSyntax {
guard node.hasViolation else {
return super.visit(node)
@@ -37,7 +37,7 @@ private extension RedundantDiscardableLetRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: VariableDeclSyntax) -> DeclSyntax {
guard node.hasRedundantDiscardableLetViolation else {
return super.visit(node)
@@ -2,8 +2,8 @@ import SwiftSyntax
// MARK: - SelfBindingRule
@SwiftSyntaxRule
struct SelfBindingRule: SwiftSyntaxCorrectableRule, OptInRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct SelfBindingRule: OptInRule {
var configuration = SelfBindingConfiguration()
static let description = RuleDescription(
@@ -46,14 +46,6 @@ struct SelfBindingRule: SwiftSyntaxCorrectableRule, OptInRule {
Example("guard let this = self else { return }", configuration: ["bind_identifier": "this"])
]
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
bindIdentifier: configuration.bindIdentifier,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension SelfBindingRule {
@@ -80,17 +72,10 @@ private extension SelfBindingRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
private let bindIdentifier: String
init(bindIdentifier: String, locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) {
self.bindIdentifier = bindIdentifier
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax {
guard let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self),
identifierPattern.identifier.text != bindIdentifier else {
identifierPattern.identifier.text != configuration.bindIdentifier else {
return super.visit(node)
}
@@ -100,16 +85,20 @@ private extension SelfBindingRule {
let newPattern = PatternSyntax(
identifierPattern
.with(\.identifier, identifierPattern.identifier.with(\.tokenKind, .identifier(bindIdentifier)))
.with(\.identifier, identifierPattern.identifier
.with(\.tokenKind, .identifier(configuration.bindIdentifier)))
)
return super.visit(node.with(\.pattern, newPattern))
} else if node.initializer == nil, identifierPattern.identifier.text == "self", bindIdentifier != "self" {
} else if node.initializer == nil,
identifierPattern.identifier.text == "self",
configuration.bindIdentifier != "self" {
correctionPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia)
let newPattern = PatternSyntax(
identifierPattern
.with(\.identifier, identifierPattern.identifier.with(\.tokenKind, .identifier(bindIdentifier)))
.with(\.identifier, identifierPattern.identifier
.with(\.tokenKind, .identifier(configuration.bindIdentifier)))
)
let newInitializer = InitializerClauseSyntax(
@@ -1,8 +1,8 @@
import SwiftLintCore
import SwiftSyntax
@SwiftSyntaxRule
struct SuperfluousElseRule: SwiftSyntaxCorrectableRule, OptInRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct SuperfluousElseRule: OptInRule {
var configuration = SeverityConfiguration<Self>(.warning)
static let description = RuleDescription(
@@ -243,14 +243,6 @@ struct SuperfluousElseRule: SwiftSyntaxCorrectableRule, OptInRule {
""")
]
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
configuration: configuration,
file: file,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension SuperfluousElseRule {
@@ -264,11 +256,9 @@ private extension SuperfluousElseRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
init(configuration: ConfigurationType,
file: SwiftLintFile,
disabledRegions: [SourceRange]) {
super.init(locationConverter: file.locationConverter, disabledRegions: disabledRegions)
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override init(configuration: ConfigurationType, file: SwiftLintFile) {
super.init(configuration: configuration, file: file)
let correctionPositions = Visitor(configuration: configuration, file: file).walk(file: file) {
$0.violations.map(\.position)
}.filter { !$0.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) }
@@ -1,7 +1,7 @@
import SwiftSyntax
@SwiftSyntaxRule
struct TrailingCommaRule: SwiftSyntaxCorrectableRule {
@SwiftSyntaxRule(explicitRewriter: true)
struct TrailingCommaRule: Rule {
var configuration = TrailingCommaConfiguration()
private static let triggeringExamples: [Example] = [
@@ -47,14 +47,6 @@ struct TrailingCommaRule: SwiftSyntaxCorrectableRule {
triggeringExamples: Self.triggeringExamples,
corrections: Self.corrections
)
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
mandatoryComma: configuration.mandatoryComma,
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
}
}
private extension TrailingCommaRule {
@@ -97,20 +89,13 @@ private extension TrailingCommaRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
private let mandatoryComma: Bool
init(mandatoryComma: Bool, locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) {
self.mandatoryComma = mandatoryComma
super.init(locationConverter: locationConverter, disabledRegions: disabledRegions)
}
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: DictionaryElementListSyntax) -> DictionaryElementListSyntax {
guard let lastElement = node.last, let index = node.index(of: lastElement) else {
return super.visit(node)
}
switch (lastElement.trailingComma, mandatoryComma) {
switch (lastElement.trailingComma, configuration.mandatoryComma) {
case (let commaToken?, false):
correctionPositions.append(commaToken.positionAfterSkippingLeadingTrivia)
let newTrailingTrivia = (lastElement.value.trailingTrivia)
@@ -145,7 +130,7 @@ private extension TrailingCommaRule {
return super.visit(node)
}
switch (lastElement.trailingComma, mandatoryComma) {
switch (lastElement.trailingComma, configuration.mandatoryComma) {
case (let commaToken?, false):
correctionPositions.append(commaToken.positionAfterSkippingLeadingTrivia)
let newNode = node
@@ -87,7 +87,7 @@ private extension UnneededParenthesesInClosureArgumentRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ClosureSignatureSyntax) -> ClosureSignatureSyntax {
guard let clause = node.parameterClause?.as(ClosureParameterClauseSyntax.self),
clause.parameters.isNotEmpty,
@@ -59,7 +59,7 @@ private extension VoidReturnRule {
}
}
final class Rewriter: ViolationsSyntaxRewriter {
final class Rewriter: ViolationsSyntaxRewriter<ConfigurationType> {
override func visit(_ node: ReturnClauseSyntax) -> ReturnClauseSyntax {
if node.violates {
correctionPositions.append(node.type.positionAfterSkippingLeadingTrivia)
+11 -4
View File
@@ -46,13 +46,20 @@ public struct Region: Equatable {
///
/// - returns: True if the specified rule is disabled in this region.
public func isRuleDisabled(_ rule: some Rule) -> Bool {
guard !disabledRuleIdentifiers.contains(.all) else {
return areRulesDisabled(ruleIDs: type(of: rule).description.allIdentifiers)
}
/// Whether the given rules are disabled in this region.
///
/// - parameter ruleIDs: A list of rule IDs. Typically all identifiers of a single rule.
///
/// - returns: True if the specified rules are disabled in this region.
public func areRulesDisabled(ruleIDs: [String]) -> Bool {
if disabledRuleIdentifiers.contains(.all) {
return true
}
let identifiersToCheck = type(of: rule).description.allIdentifiers
let regionIdentifiers = Set(disabledRuleIdentifiers.map { $0.stringRepresentation })
return !regionIdentifiers.isDisjoint(with: identifiersToCheck)
return !regionIdentifiers.isDisjoint(with: ruleIDs)
}
/// Returns the deprecated rule aliases that are disabling the specified rule in this region.
@@ -2,21 +2,18 @@ import SwiftSyntax
/// A SwiftLint CorrectableRule that performs its corrections using a SwiftSyntax `SyntaxRewriter`.
public protocol SwiftSyntaxCorrectableRule: SwiftSyntaxRule, CorrectableRule {
/// Type of the rewriter.
associatedtype RewriterType: ViolationsSyntaxRewriter
/// Produce a `ViolationsSyntaxRewriter` for the given file.
///
/// - parameter file: The file for which to produce the rewriter.
///
/// - returns: A `ViolationsSyntaxRewriter` for the given file. May be `nil` in which case the rule visitor's
/// collected `violationCorrections` will be used.
func makeRewriter(file: SwiftLintFile) -> RewriterType?
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>?
}
public extension SwiftSyntaxCorrectableRule {
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
nil as ViolationsSyntaxRewriter?
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
nil
}
func correct(file: SwiftLintFile) -> [Correction] {
@@ -68,11 +65,20 @@ public extension SwiftSyntaxCorrectableRule {
}
/// A SwiftSyntax `SyntaxRewriter` that produces absolute positions where corrections were applied.
open class ViolationsSyntaxRewriter: SyntaxRewriter {
open class ViolationsSyntaxRewriter<Configuration: RuleConfiguration>: SyntaxRewriter {
/// A rule's configuration.
public let configuration: Configuration
/// The file from which the traversed syntax tree stems from.
public let file: SwiftLintFile
/// A converter of positions in the traversed source file.
public let locationConverter: SourceLocationConverter
public lazy var locationConverter = file.locationConverter
/// The regions in the traversed file that are disabled by a command.
public let disabledRegions: [SourceRange]
public lazy var disabledRegions = {
file.regions()
.filter { $0.areRulesDisabled(ruleIDs: Configuration.Parent.description.allIdentifiers) }
.compactMap { $0.toSourceRange(locationConverter: locationConverter) }
}()
/// Positions in a source file where corrections were applied.
public var correctionPositions = [AbsolutePosition]()
@@ -80,11 +86,12 @@ open class ViolationsSyntaxRewriter: SyntaxRewriter {
/// Initilizer for a ``ViolationsSyntaxRewriter``.
///
/// - Parameters:
/// - locationConverter: Converter for positions in the source file being rewritten.
/// - disabledRegions: Regions in the to be rewritten file that are disabled by a command.
public init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) {
self.locationConverter = locationConverter
self.disabledRegions = disabledRegions
/// - configuration: Configuration of a rule.
/// - file: File from which the syntax tree stems from.
@inlinable
public init(configuration: Configuration, file: SwiftLintFile) {
self.configuration = configuration
self.file = file
}
override open func visitAny(_ node: Syntax) -> Syntax? {
@@ -40,18 +40,6 @@ public extension SwiftSyntaxRule where ConfigurationType: SeverityBasedRuleConfi
}
public extension SwiftSyntaxRule {
/// Returns the source ranges in the specified file where this rule is disabled.
///
/// - parameter file: The file to get regions.
///
/// - returns: The source ranges in the specified file where this rule is disabled.
func disabledRegions(file: SwiftLintFile) -> [SourceRange] {
let locationConverter = file.locationConverter
return file.regions()
.filter { $0.isRuleDisabled(self) }
.compactMap { $0.toSourceRange(locationConverter: locationConverter) }
}
@inlinable
func validate(file: SwiftLintFile) -> [StyleViolation] {
guard let syntaxTree = preprocess(file: file) else {
@@ -29,11 +29,8 @@ enum SwiftSyntaxRule: ExtensionMacro {
),
try makeExtension(dependingOn: node.explicitRewriterArgument, in: context, with: """
extension \(type): SwiftSyntaxCorrectableRule {
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
Rewriter(configuration: configuration, file: file)
}
}
"""
+2 -5
View File
@@ -67,11 +67,8 @@ final class SwiftSyntaxRuleTests: XCTestCase {
}
extension Hello: SwiftSyntaxCorrectableRule {
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
Rewriter(
locationConverter: file.locationConverter,
disabledRegions: disabledRegions(file: file)
)
func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter<ConfigurationType>? {
Rewriter(configuration: configuration, file: file)
}
}
""",