mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
Support arbitrary configurations in @SwiftSyntaxRule (#5275)
Almost all rules based on SwiftSyntax can be set up now by just adding `@SwiftSyntaxRule` to the rule struct.
This commit is contained in:
@@ -3,12 +3,12 @@ import SwiftSyntaxBuilder
|
||||
|
||||
/// A helper to hold a visitor and rewriter that can lint and correct legacy NS/CG functions to a more modern syntax.
|
||||
enum LegacyFunctionRuleHelper {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor<Configuration: RuleConfiguration>: ViolationsSyntaxVisitor<Configuration> {
|
||||
private let legacyFunctions: [String: RewriteStrategy]
|
||||
|
||||
init(legacyFunctions: [String: RewriteStrategy]) {
|
||||
init(configuration: Configuration, file: SwiftLintFile, legacyFunctions: [String: RewriteStrategy]) {
|
||||
self.legacyFunctions = legacyFunctions
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
super.init(configuration: configuration, file: file)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
|
||||
+3
-13
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct AnonymousArgumentInMultilineClosureRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct AnonymousArgumentInMultilineClosureRule: OptInRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -30,21 +31,10 @@ struct AnonymousArgumentInMultilineClosureRule: SwiftSyntaxRule, OptInRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(locationConverter: file.locationConverter)
|
||||
}
|
||||
}
|
||||
|
||||
private extension AnonymousArgumentInMultilineClosureRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let locationConverter: SourceLocationConverter
|
||||
|
||||
init(locationConverter: SourceLocationConverter) {
|
||||
self.locationConverter = locationConverter
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visit(_ node: ClosureExprSyntax) -> SyntaxVisitorContinueKind {
|
||||
let startLocation = locationConverter.location(for: node.leftBrace.positionAfterSkippingLeadingTrivia)
|
||||
let endLocation = locationConverter.location(for: node.rightBrace.endPositionBeforeTrailingTrivia)
|
||||
|
||||
@@ -36,7 +36,7 @@ struct BlockBasedKVORule: Rule {
|
||||
}
|
||||
|
||||
private extension BlockBasedKVORule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
guard node.modifiers.contains(keyword: .override),
|
||||
case let parameterList = node.signature.parameterClause.parameters,
|
||||
|
||||
@@ -118,7 +118,7 @@ struct ConvenienceTypeRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension ConvenienceTypeRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }
|
||||
|
||||
override func visitPost(_ node: StructDeclSyntax) {
|
||||
@@ -151,44 +151,44 @@ private extension ConvenienceTypeRule {
|
||||
return false
|
||||
}
|
||||
|
||||
return ConvenienceTypeCheckVisitor(viewMode: .sourceAccurate)
|
||||
return ConvenienceTypeCheckVisitor(configuration: configuration, file: file)
|
||||
.walk(tree: members, handler: \.canBeConvenienceType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ConvenienceTypeCheckVisitor: ViolationsSyntaxVisitor {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
final class ConvenienceTypeCheckVisitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
private(set) var canBeConvenienceType = true
|
||||
private(set) var canBeConvenienceType = true
|
||||
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
if node.isInstanceVariable {
|
||||
canBeConvenienceType = false
|
||||
} else if node.attributes.containsObjc {
|
||||
canBeConvenienceType = false
|
||||
}
|
||||
}
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
if node.modifiers.containsStaticOrClass {
|
||||
if node.attributes.containsObjc {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
if node.isInstanceVariable {
|
||||
canBeConvenienceType = false
|
||||
} else if node.attributes.containsObjc {
|
||||
canBeConvenienceType = false
|
||||
}
|
||||
} else {
|
||||
canBeConvenienceType = false
|
||||
}
|
||||
}
|
||||
|
||||
override func visitPost(_ node: InitializerDeclSyntax) {
|
||||
if !node.attributes.hasUnavailableAttribute {
|
||||
canBeConvenienceType = false
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
if node.modifiers.containsStaticOrClass {
|
||||
if node.attributes.containsObjc {
|
||||
canBeConvenienceType = false
|
||||
}
|
||||
} else {
|
||||
canBeConvenienceType = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func visitPost(_ node: SubscriptDeclSyntax) {
|
||||
if !node.modifiers.containsStaticOrClass {
|
||||
canBeConvenienceType = false
|
||||
override func visitPost(_ node: InitializerDeclSyntax) {
|
||||
if !node.attributes.hasUnavailableAttribute {
|
||||
canBeConvenienceType = false
|
||||
}
|
||||
}
|
||||
|
||||
override func visitPost(_ node: SubscriptDeclSyntax) {
|
||||
if !node.modifiers.containsStaticOrClass {
|
||||
canBeConvenienceType = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ struct DiscouragedAssertRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension DiscouragedAssertRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text == "assert",
|
||||
let firstArg = node.arguments.first,
|
||||
|
||||
@@ -180,7 +180,7 @@ struct DiscouragedNoneNameRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension DiscouragedNoneNameRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: EnumCaseElementSyntax) {
|
||||
let emptyParams = node.parameterClause?.parameters.isEmpty ?? true
|
||||
if emptyParams, node.name.isNone {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct DiscouragedObjectLiteralRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct DiscouragedObjectLiteralRule: OptInRule {
|
||||
var configuration = DiscouragedObjectLiteralConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -21,21 +22,10 @@ struct DiscouragedObjectLiteralRule: SwiftSyntaxRule, OptInRule {
|
||||
Example("let color = ↓#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(configuration: configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private extension DiscouragedObjectLiteralRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: ConfigurationType
|
||||
|
||||
init(configuration: ConfigurationType) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: MacroExpansionExprSyntax) {
|
||||
guard
|
||||
case let .identifier(identifierText) = node.macroName.tokenKind,
|
||||
|
||||
@@ -15,7 +15,7 @@ struct DiscouragedOptionalBooleanRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension DiscouragedOptionalBooleanRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: OptionalTypeSyntax) {
|
||||
if node.wrappedType.as(IdentifierTypeSyntax.self)?.typeName == "Bool" {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -80,7 +80,7 @@ struct ExplicitEnumRawValueRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension ExplicitEnumRawValueRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }
|
||||
|
||||
override func visitPost(_ node: EnumCaseElementSyntax) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
import SwiftSyntaxBuilder
|
||||
|
||||
@SwiftSyntaxRule
|
||||
struct ExplicitInitRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
var configuration = ExplicitInitConfiguration()
|
||||
|
||||
@@ -169,24 +170,13 @@ struct ExplicitInitRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate, includeBareInit: configuration.includeBareInit)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
Rewriter(locationConverter: file.locationConverter, disabledRegions: disabledRegions(file: file))
|
||||
}
|
||||
}
|
||||
|
||||
private extension ExplicitInitRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let includeBareInit: Bool
|
||||
|
||||
init(viewMode: SyntaxTreeViewMode, includeBareInit: Bool) {
|
||||
self.includeBareInit = includeBareInit
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard let calledExpression = node.calledExpression.as(MemberAccessExprSyntax.self) else {
|
||||
return
|
||||
@@ -196,7 +186,7 @@ private extension ExplicitInitRule {
|
||||
violations.append(violationPosition)
|
||||
}
|
||||
|
||||
if includeBareInit, let violationPosition = calledExpression.bareInitPosition {
|
||||
if configuration.includeBareInit, let violationPosition = calledExpression.bareInitPosition {
|
||||
let reason = "Prefer named constructors over .init and type inference"
|
||||
violations.append(ReasonedRuleViolation(position: violationPosition, reason: reason))
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ struct ExplicitTopLevelACLRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension ExplicitTopLevelACLRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ExplicitTypeInterfaceRule: OptInRule, SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ExplicitTypeInterfaceRule: OptInRule {
|
||||
var configuration = ExplicitTypeInterfaceConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -68,23 +69,12 @@ struct ExplicitTypeInterfaceRule: OptInRule, SwiftSyntaxRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(configuration: configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ExplicitTypeInterfaceRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
let configuration: ExplicitTypeInterfaceConfiguration
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }
|
||||
|
||||
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) {
|
||||
|
||||
@@ -31,7 +31,7 @@ struct FallthroughRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension FallthroughRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FallThroughStmtSyntax) {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ struct FatalErrorMessageRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension FatalErrorMessageRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard let expression = node.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
expression.baseName.text == "fatalError",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ForWhereRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ForWhereRule: Rule {
|
||||
var configuration = ForWhereConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -115,21 +116,10 @@ struct ForWhereRule: SwiftSyntaxRule {
|
||||
""", configuration: ["allow_for_as_filter": true])
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(allowForAsFilter: configuration.allowForAsFilter)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ForWhereRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let allowForAsFilter: Bool
|
||||
|
||||
init(allowForAsFilter: Bool) {
|
||||
self.allowForAsFilter = allowForAsFilter
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ForStmtSyntax) {
|
||||
guard node.whereClause == nil,
|
||||
let onlyExprStmt = node.body.statements.onlyElement?.item.as(ExpressionStmtSyntax.self),
|
||||
@@ -142,7 +132,7 @@ private extension ForWhereRule {
|
||||
return
|
||||
}
|
||||
|
||||
if allowForAsFilter, ifExpr.containsReturnStatement {
|
||||
if configuration.allowForAsFilter, ifExpr.containsReturnStatement {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ForceCastRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ForceCastRule: Rule {
|
||||
var configuration = SeverityConfiguration<Self>(.error)
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -13,14 +14,10 @@ struct ForceCastRule: SwiftSyntaxRule {
|
||||
],
|
||||
triggeringExamples: [ Example("NSNumber() ↓as! Int") ]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ForceCastRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: AsExprSyntax) {
|
||||
if node.questionOrExclamationMark?.tokenKind == .exclamationMark {
|
||||
violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -27,7 +27,7 @@ struct ForceTryRule: Rule {
|
||||
}
|
||||
|
||||
private extension ForceTryRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: TryExprSyntax) {
|
||||
if node.questionOrExclamationMark?.tokenKind == .exclamationMark {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ForceUnwrappingRule: OptInRule, SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ForceUnwrappingRule: OptInRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -64,14 +65,10 @@ struct ForceUnwrappingRule: OptInRule, SwiftSyntaxRule {
|
||||
Example("map[\"a\"]↓!↓!")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ForceUnwrappingRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ForceUnwrapExprSyntax) {
|
||||
violations.append(node.exclamationMark.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ struct FunctionDefaultParameterAtEndRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension FunctionDefaultParameterAtEndRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
guard !node.modifiers.contains(keyword: .override), node.signature.containsViolation else {
|
||||
return
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import Foundation
|
||||
import SwiftSyntax
|
||||
|
||||
struct GenericTypeNameRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct GenericTypeNameRule: Rule {
|
||||
var configuration = NameConfiguration<Self>(minLengthWarning: 1,
|
||||
minLengthError: 0,
|
||||
maxLengthWarning: 20,
|
||||
@@ -47,21 +48,10 @@ struct GenericTypeNameRule: SwiftSyntaxRule {
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(configuration: configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private extension GenericTypeNameRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: ConfigurationType
|
||||
|
||||
init(configuration: ConfigurationType) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: GenericParameterSyntax) {
|
||||
let name = node.name.text
|
||||
guard !name.isEmpty, !configuration.shouldExclude(name: name) else { return }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ImplicitlyUnwrappedOptionalRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ImplicitlyUnwrappedOptionalRule: OptInRule {
|
||||
var configuration = ImplicitlyUnwrappedOptionalConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -40,27 +41,16 @@ struct ImplicitlyUnwrappedOptionalRule: SwiftSyntaxRule, OptInRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(mode: configuration.mode)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ImplicitlyUnwrappedOptionalRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let mode: ConfigurationType.ImplicitlyUnwrappedOptionalModeConfiguration
|
||||
|
||||
init(mode: ConfigurationType.ImplicitlyUnwrappedOptionalModeConfiguration) {
|
||||
self.mode = mode
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ImplicitlyUnwrappedOptionalTypeSyntax) {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
|
||||
override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
switch mode {
|
||||
switch configuration.mode {
|
||||
case .all:
|
||||
return .visitChildren
|
||||
case .allExceptIBOutlets:
|
||||
|
||||
@@ -23,7 +23,7 @@ struct IsDisjointRule: Rule {
|
||||
}
|
||||
|
||||
private extension IsDisjointRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: MemberAccessExprSyntax) {
|
||||
guard
|
||||
node.declName.baseName.text == "isEmpty",
|
||||
|
||||
@@ -46,7 +46,7 @@ struct JoinedDefaultParameterRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
}
|
||||
|
||||
private extension JoinedDefaultParameterRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
if let violationPosition = node.violationPosition {
|
||||
violations.append(violationPosition)
|
||||
|
||||
@@ -100,8 +100,12 @@ struct LegacyCGGeometryFunctionsRule: SwiftSyntaxCorrectableRule {
|
||||
"CGRectIntersection": .function(name: "intersection", argumentLabels: [""])
|
||||
]
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
LegacyFunctionRuleHelper.Visitor(legacyFunctions: Self.legacyFunctions)
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
LegacyFunctionRuleHelper.Visitor(
|
||||
configuration: configuration,
|
||||
file: file,
|
||||
legacyFunctions: Self.legacyFunctions
|
||||
)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
|
||||
@@ -24,7 +24,7 @@ struct LegacyConstantRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension LegacyConstantRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: DeclReferenceExprSyntax) {
|
||||
if LegacyConstantRuleExamples.patterns.keys.contains(node.baseName.text) {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -132,7 +132,7 @@ struct LegacyConstructorRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension LegacyConstructorRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
if let identifierExpr = node.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
constructorsToCorrectedNames[identifierExpr.baseName.text] != nil {
|
||||
|
||||
@@ -76,7 +76,7 @@ struct LegacyHashingRule: Rule {
|
||||
}
|
||||
|
||||
private extension LegacyHashingRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard
|
||||
node.parent?.is(MemberBlockItemSyntax.self) == true,
|
||||
|
||||
@@ -40,7 +40,7 @@ struct LegacyMultipleRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension LegacyMultipleRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: InfixOperatorExprSyntax) {
|
||||
guard let operatorNode = node.operator.as(BinaryOperatorExprSyntax.self),
|
||||
operatorNode.operator.tokenKind == .binaryOperator("%"),
|
||||
|
||||
@@ -100,8 +100,12 @@ struct LegacyNSGeometryFunctionsRule: SwiftSyntaxCorrectableRule {
|
||||
"NSPointInRect": .function(name: "contains", argumentLabels: [""], reversed: true)
|
||||
]
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
LegacyFunctionRuleHelper.Visitor(legacyFunctions: Self.legacyFunctions)
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
LegacyFunctionRuleHelper.Visitor(
|
||||
configuration: configuration,
|
||||
file: file,
|
||||
legacyFunctions: Self.legacyFunctions
|
||||
)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
|
||||
@@ -69,7 +69,7 @@ struct LegacyObjcTypeRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension LegacyObjcTypeRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: IdentifierTypeSyntax) {
|
||||
if let typeName = node.typeName, legacyObjcTypes.contains(typeName) {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -23,7 +23,7 @@ struct LegacyRandomRule: Rule {
|
||||
}
|
||||
|
||||
private extension LegacyRandomRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private static let legacyRandomFunctions: Set<String> = [
|
||||
"arc4random",
|
||||
"arc4random_uniform",
|
||||
|
||||
@@ -24,7 +24,7 @@ struct NoExtensionAccessModifierRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension NoExtensionAccessModifierRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: ExtensionDeclSyntax) {
|
||||
|
||||
@@ -15,7 +15,7 @@ struct NoFallthroughOnlyRule: Rule {
|
||||
}
|
||||
|
||||
private extension NoFallthroughOnlyRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: SwitchCaseListSyntax) {
|
||||
let cases = node.compactMap { $0.as(SwitchCaseSyntax.self) }
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct NoMagicNumbersRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct NoMagicNumbersRule: OptInRule {
|
||||
var configuration = NoMagicNumbersConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -90,27 +91,17 @@ struct NoMagicNumbersRule: SwiftSyntaxRule, OptInRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate, testParentClasses: configuration.testParentClasses)
|
||||
}
|
||||
}
|
||||
|
||||
private extension NoMagicNumbersRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let testParentClasses: Set<String>
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private var testClasses: Set<String> = []
|
||||
private var nonTestClasses: Set<String> = []
|
||||
private var possibleViolations: [String: Set<AbsolutePosition>] = [:]
|
||||
|
||||
init(viewMode: SyntaxTreeViewMode, testParentClasses: Set<String>) {
|
||||
self.testParentClasses = testParentClasses
|
||||
super.init(viewMode: viewMode)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
let className = node.name.text
|
||||
if node.isXCTestCase(testParentClasses) {
|
||||
if node.isXCTestCase(configuration.testParentClasses) {
|
||||
testClasses.insert(className)
|
||||
removeViolations(forClassName: className)
|
||||
} else {
|
||||
@@ -133,7 +124,7 @@ private extension NoMagicNumbersRule {
|
||||
}
|
||||
|
||||
private func collectViolation(forNode node: some ExprSyntaxProtocol) {
|
||||
if node.isMemberOfATestClass(testParentClasses) {
|
||||
if node.isMemberOfATestClass(configuration.testParentClasses) {
|
||||
return
|
||||
}
|
||||
if node.isOperandOfBitwiseShiftOperation() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ObjectLiteralRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ObjectLiteralRule: OptInRule {
|
||||
var configuration = ObjectLiteralConfiguration<Self>()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -30,32 +31,19 @@ struct ObjectLiteralRule: SwiftSyntaxRule, OptInRule {
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(validateImageLiteral: configuration.imageLiteral, validateColorLiteral: configuration.colorLiteral)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ObjectLiteralRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let validateImageLiteral: Bool
|
||||
private let validateColorLiteral: Bool
|
||||
|
||||
init(validateImageLiteral: Bool, validateColorLiteral: Bool) {
|
||||
self.validateImageLiteral = validateImageLiteral
|
||||
self.validateColorLiteral = validateColorLiteral
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard validateColorLiteral || validateImageLiteral else {
|
||||
guard configuration.colorLiteral || configuration.imageLiteral else {
|
||||
return
|
||||
}
|
||||
|
||||
let name = node.calledExpression.trimmedDescription
|
||||
if validateImageLiteral, isImageNamedInit(node: node, name: name) {
|
||||
if configuration.imageLiteral, isImageNamedInit(node: node, name: name) {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
} else if validateColorLiteral, isColorInit(node: node, name: name) {
|
||||
} else if configuration.colorLiteral, isColorInit(node: node, name: name) {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,16 +36,16 @@ struct PatternMatchingKeywordsRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension PatternMatchingKeywordsRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: SwitchCaseItemSyntax) {
|
||||
let localViolations = TupleVisitor(viewMode: .sourceAccurate)
|
||||
let localViolations = TupleVisitor(configuration: configuration, file: file)
|
||||
.walk(tree: node.pattern, handler: \.violations)
|
||||
violations.append(contentsOf: localViolations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class TupleVisitor: ViolationsSyntaxVisitor {
|
||||
private final class TupleVisitor<Configuration: RuleConfiguration>: ViolationsSyntaxVisitor<Configuration> {
|
||||
override func visitPost(_ node: LabeledExprListSyntax) {
|
||||
let list = node.flatteningEnumPatterns()
|
||||
.compactMap { elem in
|
||||
|
||||
@@ -25,7 +25,7 @@ struct PreferNimbleRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension PreferNimbleRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
if let expr = node.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
expr.baseName.text.starts(with: "XCTAssert") {
|
||||
|
||||
@@ -44,7 +44,7 @@ struct PreferZeroOverExplicitInitRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
}
|
||||
|
||||
private extension PreferZeroOverExplicitInitRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
if node.hasViolation {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import SwiftSyntax
|
||||
|
||||
@SwiftSyntaxRule
|
||||
struct PrivateOverFilePrivateRule: SwiftSyntaxCorrectableRule {
|
||||
var configuration = PrivateOverFilePrivateConfiguration()
|
||||
|
||||
@@ -54,10 +55,6 @@ struct PrivateOverFilePrivateRule: SwiftSyntaxCorrectableRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(validateExtensions: configuration.validateExtensions)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
Rewriter(
|
||||
validateExtensions: configuration.validateExtensions,
|
||||
@@ -68,14 +65,7 @@ struct PrivateOverFilePrivateRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension PrivateOverFilePrivateRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let validateExtensions: Bool
|
||||
|
||||
init(validateExtensions: Bool) {
|
||||
self.validateExtensions = validateExtensions
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
if let privateModifier = node.modifiers.fileprivateModifier {
|
||||
violations.append(privateModifier.positionAfterSkippingLeadingTrivia)
|
||||
@@ -84,7 +74,7 @@ private extension PrivateOverFilePrivateRule {
|
||||
}
|
||||
|
||||
override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
if validateExtensions, let privateModifier = node.modifiers.fileprivateModifier {
|
||||
if configuration.validateExtensions, let privateModifier = node.modifiers.fileprivateModifier {
|
||||
violations.append(privateModifier.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
return .skipChildren
|
||||
|
||||
@@ -31,7 +31,7 @@ struct RedundantNilCoalescingRule: OptInRule, SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension RedundantNilCoalescingRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: TokenSyntax) {
|
||||
if node.tokenKind.isNilCoalescingOperator,
|
||||
node.nextToken(viewMode: .sourceAccurate)?.tokenKind == .keyword(.nil) {
|
||||
|
||||
@@ -18,15 +18,15 @@ struct RedundantObjcAttributeRule: SwiftSyntaxRule, SubstitutionCorrectableRule
|
||||
corrections: RedundantObjcAttributeRuleExamples.corrections
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: AttributeListSyntax) {
|
||||
if let objcAttribute = node.violatingObjCAttribute {
|
||||
violations.append(objcAttribute.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
||||
return Visitor(viewMode: .sourceAccurate)
|
||||
return Visitor(configuration: configuration, file: file)
|
||||
}
|
||||
|
||||
func violationRanges(in file: SwiftLintFile) -> [NSRange] {
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ struct RedundantOptionalInitializationRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension RedundantOptionalInitializationRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard node.bindingSpecifier.tokenKind == .keyword(.var),
|
||||
!node.modifiers.contains(keyword: .lazy) else {
|
||||
|
||||
@@ -61,7 +61,7 @@ struct RedundantSetAccessControlRule: Rule {
|
||||
}
|
||||
|
||||
private extension RedundantSetAccessControlRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
[FunctionDeclSyntax.self]
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ struct RedundantStringEnumValueRule: Rule {
|
||||
}
|
||||
|
||||
private extension RedundantStringEnumValueRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: EnumDeclSyntax) {
|
||||
guard node.isStringEnum else {
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ReturnValueFromVoidFunctionRule: OptInRule, SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ReturnValueFromVoidFunctionRule: OptInRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -12,14 +13,10 @@ struct ReturnValueFromVoidFunctionRule: OptInRule, SwiftSyntaxRule {
|
||||
nonTriggeringExamples: ReturnValueFromVoidFunctionRuleExamples.nonTriggeringExamples,
|
||||
triggeringExamples: ReturnValueFromVoidFunctionRuleExamples.triggeringExamples
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ReturnValueFromVoidFunctionRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ReturnStmtSyntax) {
|
||||
if node.expression != nil,
|
||||
let functionNode = Syntax(node).enclosingFunction(),
|
||||
|
||||
@@ -89,7 +89,7 @@ struct ShorthandOptionalBindingRule: OptInRule, SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension ShorthandOptionalBindingRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: OptionalBindingConditionSyntax) {
|
||||
if node.isShadowingOptionalBinding {
|
||||
violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -79,7 +79,7 @@ struct StaticOperatorRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension StaticOperatorRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct StrictFilePrivateRule: OptInRule, SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct StrictFilePrivateRule: OptInRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -122,10 +123,6 @@ struct StrictFilePrivateRule: OptInRule, SwiftSyntaxRule {
|
||||
""", excludeFromDocumentation: true)
|
||||
}
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate, file: file.syntaxTree)
|
||||
}
|
||||
}
|
||||
|
||||
private enum ProtocolRequirementType: Equatable {
|
||||
@@ -135,16 +132,10 @@ private enum ProtocolRequirementType: Equatable {
|
||||
}
|
||||
|
||||
private extension StrictFilePrivateRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let file: SourceFileSyntax
|
||||
|
||||
init(viewMode: SyntaxTreeViewMode, file: SourceFileSyntax) {
|
||||
self.file = file
|
||||
super.init(viewMode: viewMode)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private lazy var protocols = {
|
||||
ProtocolCollector(viewMode: .sourceAccurate).walk(tree: file, handler: \.protocols)
|
||||
ProtocolCollector(configuration: configuration, file: file)
|
||||
.walk(tree: file.syntaxTree, handler: \.protocols)
|
||||
}()
|
||||
|
||||
override func visitPost(_ node: DeclModifierSyntax) {
|
||||
@@ -212,7 +203,7 @@ private extension StrictFilePrivateRule {
|
||||
}
|
||||
}
|
||||
|
||||
private final class ProtocolCollector: ViolationsSyntaxVisitor {
|
||||
private final class ProtocolCollector<Configuration: RuleConfiguration>: ViolationsSyntaxVisitor<Configuration> {
|
||||
private(set) var protocols = [String: [ProtocolRequirementType]]()
|
||||
private var currentProtocolName: String = ""
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ struct ToggleBoolRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
}
|
||||
|
||||
private extension ToggleBoolRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ExprListSyntax) {
|
||||
if node.hasToggleBoolViolation {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -34,7 +34,7 @@ struct TrailingSemicolonRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension TrailingSemicolonRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: TokenSyntax) {
|
||||
if node.isTrailingSemicolon {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import Foundation
|
||||
import SwiftSyntax
|
||||
|
||||
struct TypeNameRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct TypeNameRule: Rule {
|
||||
var configuration = TypeNameConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -16,21 +17,10 @@ struct TypeNameRule: SwiftSyntaxRule {
|
||||
nonTriggeringExamples: TypeNameRuleExamples.nonTriggeringExamples,
|
||||
triggeringExamples: TypeNameRuleExamples.triggeringExamples
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(configuration: configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private extension TypeNameRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: TypeNameConfiguration
|
||||
|
||||
init(configuration: TypeNameConfiguration) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: StructDeclSyntax) {
|
||||
if let violation = violation(identifier: node.name, modifiers: node.modifiers,
|
||||
inheritedTypes: node.inheritanceClause?.inheritedTypes) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct UnavailableConditionRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct UnavailableConditionRule: Rule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -68,14 +69,10 @@ struct UnavailableConditionRule: SwiftSyntaxRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
}
|
||||
|
||||
private extension UnavailableConditionRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: IfExprSyntax) {
|
||||
guard node.body.statements.isEmpty else {
|
||||
return
|
||||
|
||||
@@ -73,7 +73,7 @@ struct UnavailableFunctionRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension UnavailableFunctionRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
guard !node.returnsNever,
|
||||
!node.attributes.hasUnavailableAttribute,
|
||||
|
||||
@@ -12,6 +12,7 @@ private func embedInSwitch(
|
||||
""", file: file, line: line)
|
||||
}
|
||||
|
||||
@SwiftSyntaxRule
|
||||
struct UnneededBreakInSwitchRule: SwiftSyntaxCorrectableRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
@@ -86,10 +87,6 @@ struct UnneededBreakInSwitchRule: SwiftSyntaxCorrectableRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
Rewriter(
|
||||
locationConverter: file.locationConverter,
|
||||
@@ -99,7 +96,7 @@ struct UnneededBreakInSwitchRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension UnneededBreakInSwitchRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: SwitchCaseSyntax) {
|
||||
guard let statement = node.unneededBreak else {
|
||||
return
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ struct UnneededSynthesizedInitializerRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension UnneededSynthesizedInitializerRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
.allExcept(StructDeclSyntax.self, ClassDeclSyntax.self)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import SwiftSyntax
|
||||
|
||||
@SwiftSyntaxRule
|
||||
struct UntypedErrorInCatchRule: OptInRule, SwiftSyntaxCorrectableRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
@@ -85,10 +86,6 @@ struct UntypedErrorInCatchRule: OptInRule, SwiftSyntaxCorrectableRule {
|
||||
Example("do {\n try foo() \n} ↓catch (let error) {}"): Example("do {\n try foo() \n} catch {}")
|
||||
])
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
Rewriter(
|
||||
locationConverter: file.locationConverter,
|
||||
@@ -120,7 +117,7 @@ private extension CatchItemSyntax {
|
||||
}
|
||||
|
||||
private extension UntypedErrorInCatchRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: CatchClauseSyntax) {
|
||||
guard let item = node.catchItems.onlyElement, item.isIdentifierPattern else {
|
||||
return
|
||||
|
||||
@@ -30,7 +30,7 @@ struct UnusedEnumeratedRule: Rule {
|
||||
}
|
||||
|
||||
private extension UnusedEnumeratedRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ForStmtSyntax) {
|
||||
guard let tuplePattern = node.pattern.as(TuplePatternSyntax.self),
|
||||
tuplePattern.elements.count == 2,
|
||||
|
||||
+3
-6
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct VoidFunctionInTernaryConditionRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct VoidFunctionInTernaryConditionRule: Rule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -105,14 +106,10 @@ struct VoidFunctionInTernaryConditionRule: SwiftSyntaxRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate)
|
||||
}
|
||||
}
|
||||
|
||||
private extension VoidFunctionInTernaryConditionRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: TernaryExprSyntax) {
|
||||
guard node.thenExpression.is(FunctionCallExprSyntax.self),
|
||||
node.elseExpression.is(FunctionCallExprSyntax.self),
|
||||
|
||||
@@ -37,7 +37,7 @@ struct XCTFailMessageRule: Rule {
|
||||
}
|
||||
|
||||
private extension XCTFailMessageRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard
|
||||
let expression = node.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import SwiftOperators
|
||||
import SwiftSyntax
|
||||
|
||||
struct XCTSpecificMatcherRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct XCTSpecificMatcherRule: OptInRule {
|
||||
var configuration = XCTSpecificMatcherConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -12,21 +13,10 @@ struct XCTSpecificMatcherRule: SwiftSyntaxRule, OptInRule {
|
||||
nonTriggeringExamples: XCTSpecificMatcherRuleExamples.nonTriggeringExamples,
|
||||
triggeringExamples: XCTSpecificMatcherRuleExamples.triggeringExamples
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(configuration: configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private extension XCTSpecificMatcherRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
let configuration: XCTSpecificMatcherConfiguration
|
||||
|
||||
init(configuration: XCTSpecificMatcherConfiguration) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
if configuration.matchers.contains(.twoArgumentAsserts),
|
||||
let suggestion = TwoArgsXCTAssert.violations(in: node) {
|
||||
|
||||
@@ -38,9 +38,9 @@ struct AnyObjectProtocolRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
warnDeprecatedOnce()
|
||||
return Visitor(viewMode: .sourceAccurate)
|
||||
return Visitor(configuration: configuration, file: file)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
@@ -52,7 +52,7 @@ struct AnyObjectProtocolRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
}
|
||||
|
||||
private extension AnyObjectProtocolRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ClassRestrictionTypeSyntax) {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ struct ArrayInitRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension ArrayInitRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard let memberAccess = node.calledExpression.as(MemberAccessExprSyntax.self),
|
||||
memberAccess.declName.baseName.text == "map",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct BalancedXCTestLifecycleRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct BalancedXCTestLifecycleRule: OptInRule {
|
||||
var configuration = BalancedXCTestLifecycleConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -103,30 +104,20 @@ struct BalancedXCTestLifecycleRule: SwiftSyntaxRule, OptInRule {
|
||||
"""#)
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(viewMode: .sourceAccurate, testParentClasses: configuration.testParentClasses)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private extension BalancedXCTestLifecycleRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let testParentClasses: Set<String>
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
init(viewMode: SyntaxTreeViewMode, testParentClasses: Set<String>) {
|
||||
self.testParentClasses = testParentClasses
|
||||
super.init(viewMode: viewMode)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
guard node.isXCTestCase(testParentClasses) else {
|
||||
guard node.isXCTestCase(configuration.testParentClasses) else {
|
||||
return
|
||||
}
|
||||
|
||||
let methods = SetupTearDownVisitor(viewMode: .sourceAccurate)
|
||||
let methods = SetupTearDownVisitor(configuration: configuration, file: file)
|
||||
.walk(tree: node.memberBlock, handler: \.methods)
|
||||
guard methods.contains(.setUp) != methods.contains(.tearDown) else {
|
||||
return
|
||||
@@ -137,7 +128,7 @@ private extension BalancedXCTestLifecycleRule {
|
||||
}
|
||||
}
|
||||
|
||||
private final class SetupTearDownVisitor: ViolationsSyntaxVisitor {
|
||||
private final class SetupTearDownVisitor<Configuration: RuleConfiguration>: ViolationsSyntaxVisitor<Configuration> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
private(set) var methods: Set<XCTMethod> = []
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ struct ClassDelegateProtocolRule: Rule {
|
||||
}
|
||||
|
||||
private extension ClassDelegateProtocolRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
.allExcept(ProtocolDeclSyntax.self)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ struct CompilerProtocolInitRule: Rule {
|
||||
}
|
||||
|
||||
private extension CompilerProtocolInitRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard node.trailingClosure == nil else {
|
||||
return
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct DeploymentTargetRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct DeploymentTargetRule {
|
||||
fileprivate typealias Version = DeploymentTargetConfiguration.Version
|
||||
var configuration = DeploymentTargetConfiguration()
|
||||
|
||||
@@ -13,50 +14,39 @@ struct DeploymentTargetRule: SwiftSyntaxRule {
|
||||
nonTriggeringExamples: DeploymentTargetRuleExamples.nonTriggeringExamples,
|
||||
triggeringExamples: DeploymentTargetRuleExamples.triggeringExamples
|
||||
)
|
||||
}
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(platformToConfiguredMinVersion: platformToConfiguredMinVersion)
|
||||
}
|
||||
private enum AvailabilityType {
|
||||
case condition
|
||||
case attribute
|
||||
case negativeCondition
|
||||
|
||||
private var platformToConfiguredMinVersion: [String: Version] {
|
||||
return [
|
||||
"iOS": configuration.iOSDeploymentTarget,
|
||||
"iOSApplicationExtension": configuration.iOSAppExtensionDeploymentTarget,
|
||||
"macOS": configuration.macOSDeploymentTarget,
|
||||
"macOSApplicationExtension": configuration.macOSAppExtensionDeploymentTarget,
|
||||
"OSX": configuration.macOSDeploymentTarget,
|
||||
"tvOS": configuration.tvOSDeploymentTarget,
|
||||
"tvOSApplicationExtension": configuration.tvOSAppExtensionDeploymentTarget,
|
||||
"watchOS": configuration.watchOSDeploymentTarget,
|
||||
"watchOSApplicationExtension": configuration.watchOSAppExtensionDeploymentTarget
|
||||
]
|
||||
}
|
||||
|
||||
private enum AvailabilityType {
|
||||
case condition
|
||||
case attribute
|
||||
case negativeCondition
|
||||
|
||||
var displayString: String {
|
||||
switch self {
|
||||
case .condition:
|
||||
return "condition"
|
||||
case .attribute:
|
||||
return "attribute"
|
||||
case .negativeCondition:
|
||||
return "negative condition"
|
||||
}
|
||||
var displayString: String {
|
||||
switch self {
|
||||
case .condition:
|
||||
return "condition"
|
||||
case .attribute:
|
||||
return "attribute"
|
||||
case .negativeCondition:
|
||||
return "negative condition"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension DeploymentTargetRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let platformToConfiguredMinVersion: [String: Version]
|
||||
|
||||
init(platformToConfiguredMinVersion: [String: Version]) {
|
||||
self.platformToConfiguredMinVersion = platformToConfiguredMinVersion
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private var platformToConfiguredMinVersion: [String: Version] {
|
||||
[
|
||||
"iOS": configuration.iOSDeploymentTarget,
|
||||
"iOSApplicationExtension": configuration.iOSAppExtensionDeploymentTarget,
|
||||
"macOS": configuration.macOSDeploymentTarget,
|
||||
"macOSApplicationExtension": configuration.macOSAppExtensionDeploymentTarget,
|
||||
"OSX": configuration.macOSDeploymentTarget,
|
||||
"tvOS": configuration.tvOSDeploymentTarget,
|
||||
"tvOSApplicationExtension": configuration.tvOSAppExtensionDeploymentTarget,
|
||||
"watchOS": configuration.watchOSDeploymentTarget,
|
||||
"watchOSApplicationExtension": configuration.watchOSAppExtensionDeploymentTarget
|
||||
]
|
||||
}
|
||||
|
||||
override func visitPost(_ node: AttributeSyntax) {
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ struct DiscardedNotificationCenterObserverRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension DiscardedNotificationCenterObserverRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard
|
||||
let calledExpression = node.calledExpression.as(MemberAccessExprSyntax.self),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct DiscouragedDirectInitRule: SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct DiscouragedDirectInitRule: Rule {
|
||||
var configuration = DiscouragedDirectInitConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -34,24 +35,13 @@ struct DiscouragedDirectInitRule: SwiftSyntaxRule {
|
||||
Example("let foo = bar(bundle: ↓Bundle.init(), device: ↓UIDevice.init(), error: ↓NSError.init())")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(discouragedInits: configuration.discouragedInits)
|
||||
}
|
||||
}
|
||||
|
||||
private extension DiscouragedDirectInitRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let discouragedInits: Set<String>
|
||||
|
||||
init(discouragedInits: Set<String>) {
|
||||
self.discouragedInits = discouragedInits
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard node.arguments.isEmpty, node.trailingClosure == nil,
|
||||
discouragedInits.contains(node.calledExpression.trimmedDescription) else {
|
||||
configuration.discouragedInits.contains(node.calledExpression.trimmedDescription) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ struct DuplicateConditionsRule: Rule {
|
||||
}
|
||||
|
||||
private extension DuplicateConditionsRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: IfExprSyntax) {
|
||||
if node.parent?.is(IfExprSyntax.self) == true {
|
||||
// We can skip these cases - they will be picked up when we visit the top level `if`
|
||||
|
||||
@@ -58,7 +58,7 @@ struct DuplicateEnumCasesRule: Rule {
|
||||
}
|
||||
|
||||
private extension DuplicateEnumCasesRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: EnumDeclSyntax) {
|
||||
let enumElements = node.memberBlock.members
|
||||
.flatMap { member -> EnumCaseElementListSyntax in
|
||||
|
||||
@@ -80,7 +80,7 @@ struct DuplicatedKeyInDictionaryLiteralRule: Rule {
|
||||
}
|
||||
|
||||
private extension DuplicatedKeyInDictionaryLiteralRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ list: DictionaryElementListSyntax) {
|
||||
let keys = list.map(\.key).compactMap { expr -> DictionaryKey? in
|
||||
expr.stringContent.map {
|
||||
|
||||
@@ -25,7 +25,7 @@ struct DynamicInlineRule: Rule {
|
||||
}
|
||||
|
||||
private extension DynamicInlineRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
if node.modifiers.contains(where: { $0.name.text == "dynamic" }),
|
||||
node.attributes.contains(where: { $0.as(AttributeSyntax.self)?.isInlineAlways == true }) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct EmptyXCTestMethodRule: OptInRule, SwiftSyntaxRule {
|
||||
@SwiftSyntaxRule
|
||||
struct EmptyXCTestMethodRule: OptInRule {
|
||||
var configuration = EmptyXCTestMethodConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -11,24 +12,14 @@ struct EmptyXCTestMethodRule: OptInRule, SwiftSyntaxRule {
|
||||
nonTriggeringExamples: EmptyXCTestMethodRuleExamples.nonTriggeringExamples,
|
||||
triggeringExamples: EmptyXCTestMethodRuleExamples.triggeringExamples
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(testParentClasses: configuration.testParentClasses)
|
||||
}
|
||||
}
|
||||
|
||||
private extension EmptyXCTestMethodRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
private let testParentClasses: Set<String>
|
||||
|
||||
init(testParentClasses: Set<String>) {
|
||||
self.testParentClasses = testParentClasses
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
node.isXCTestCase(testParentClasses) ? .visitChildren : .skipChildren
|
||||
node.isXCTestCase(configuration.testParentClasses) ? .visitChildren : .skipChildren
|
||||
}
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
|
||||
@@ -27,7 +27,7 @@ struct IBInspectableInExtensionRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension IBInspectableInExtensionRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
.allExcept(ExtensionDeclSyntax.self, VariableDeclSyntax.self)
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ struct IdenticalOperandsRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension IdenticalOperandsRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: InfixOperatorExprSyntax) {
|
||||
guard let operatorNode = node.operator.as(BinaryOperatorExprSyntax.self),
|
||||
IdenticalOperandsRule.operators.contains(operatorNode.operator.text) else {
|
||||
|
||||
@@ -83,14 +83,14 @@ struct InertDeferRule: SwiftSyntaxRule, OptInRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
warnDeprecatedOnce()
|
||||
return Visitor(viewMode: .sourceAccurate)
|
||||
return Visitor(configuration: configuration, file: file)
|
||||
}
|
||||
}
|
||||
|
||||
private extension InertDeferRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: DeferStmtSyntax) {
|
||||
guard node.isLastStatement else {
|
||||
return
|
||||
|
||||
@@ -40,20 +40,25 @@ struct LocalDocCommentRule: SwiftSyntaxRule, OptInRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(classifications: file.syntaxClassifications.filter { $0.kind != .none })
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
Visitor(
|
||||
configuration: configuration,
|
||||
file: file,
|
||||
classifications: file.syntaxClassifications.filter { $0.kind != .none }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private extension LocalDocCommentRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private let docCommentRanges: [ByteSourceRange]
|
||||
|
||||
init(classifications: [SyntaxClassifiedRange]) {
|
||||
init(configuration: ConfigurationType, file: SwiftLintFile,
|
||||
classifications: [SyntaxClassifiedRange]) {
|
||||
self.docCommentRanges = classifications
|
||||
.filter { $0.kind == .docLineComment || $0.kind == .docBlockComment }
|
||||
.map(\.range)
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
super.init(configuration: configuration, file: file)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
|
||||
@@ -90,7 +90,7 @@ struct LowerACLThanParentRule: OptInRule, SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension LowerACLThanParentRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: DeclModifierSyntax) {
|
||||
if node.isHigherACLThanParent {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -34,7 +34,7 @@ struct NSLocalizedStringKeyRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension NSLocalizedStringKeyRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard node.calledExpression.as(DeclReferenceExprSyntax.self)?.baseName.text == "NSLocalizedString" else {
|
||||
return
|
||||
|
||||
@@ -43,7 +43,7 @@ struct NSLocalizedStringRequireBundleRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension NSLocalizedStringRequireBundleRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
if let identifierExpr = node.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
identifierExpr.baseName.tokenKind == .identifier("NSLocalizedString"),
|
||||
|
||||
@@ -26,7 +26,7 @@ struct NSNumberInitAsFunctionReferenceRule: Rule {
|
||||
}
|
||||
|
||||
private extension NSNumberInitAsFunctionReferenceRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: MemberAccessExprSyntax) {
|
||||
guard node.declName.argumentNames.isEmptyOrNil,
|
||||
node.declName.baseName.text == "init",
|
||||
|
||||
@@ -15,7 +15,7 @@ struct NSObjectPreferIsEqualRule: Rule {
|
||||
}
|
||||
|
||||
private extension NSObjectPreferIsEqualRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .extensionsAndProtocols }
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
|
||||
@@ -15,7 +15,7 @@ struct NotificationCenterDetachmentRule: Rule {
|
||||
}
|
||||
|
||||
private extension NotificationCenterDetachmentRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
guard node.isNotificationCenterDettachmentCall,
|
||||
let arg = node.arguments.first,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct OverriddenSuperCallRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct OverriddenSuperCallRule: OptInRule {
|
||||
var configuration = OverriddenSuperCallConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -73,31 +74,18 @@ struct OverriddenSuperCallRule: SwiftSyntaxRule, OptInRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(resolvedMethodNames: configuration.resolvedMethodNames)
|
||||
}
|
||||
}
|
||||
|
||||
private extension OverriddenSuperCallRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let resolvedMethodNames: [String]
|
||||
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
[ProtocolDeclSyntax.self]
|
||||
}
|
||||
|
||||
init(resolvedMethodNames: [String]) {
|
||||
self.resolvedMethodNames = resolvedMethodNames
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
guard let body = node.body,
|
||||
node.modifiers.contains(keyword: .override),
|
||||
!node.modifiers.containsStaticOrClass,
|
||||
case let name = node.resolvedName(),
|
||||
resolvedMethodNames.contains(name) else {
|
||||
configuration.resolvedMethodNames.contains(name) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -33,20 +33,27 @@ struct OverrideInExtensionRule: OptInRule, SwiftSyntaxRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
let allowedExtensions = ClassNameCollectingVisitor(viewMode: .sourceAccurate)
|
||||
.walk(tree: file.syntaxTree, handler: \.classNames)
|
||||
return Visitor(allowedExtensions: allowedExtensions)
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
let allowedExtensions = ClassNameCollectingVisitor(
|
||||
configuration: configuration,
|
||||
file: file
|
||||
).walk(tree: file.syntaxTree, handler: \.classNames)
|
||||
return Visitor(
|
||||
configuration: configuration,
|
||||
file: file,
|
||||
allowedExtensions: allowedExtensions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private extension OverrideInExtensionRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private let allowedExtensions: Set<String>
|
||||
|
||||
init(allowedExtensions: Set<String>) {
|
||||
init(configuration: ConfigurationType, file: SwiftLintFile,
|
||||
allowedExtensions: Set<String>) {
|
||||
self.allowedExtensions = allowedExtensions
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
super.init(configuration: configuration, file: file)
|
||||
}
|
||||
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .allExcept(ExtensionDeclSyntax.self) }
|
||||
@@ -72,14 +79,14 @@ private extension OverrideInExtensionRule {
|
||||
return .visitChildren
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ClassNameCollectingVisitor: ViolationsSyntaxVisitor {
|
||||
private(set) var classNames: Set<String> = []
|
||||
final class ClassNameCollectingVisitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private(set) var classNames: Set<String> = []
|
||||
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
classNames.insert(node.name.text)
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
classNames.insert(node.name.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ struct PrivateActionRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension PrivateActionRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
node.modifiers.containsPrivateOrFileprivate() ? .skipChildren : .visitChildren
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct PrivateOutletRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct PrivateOutletRule: OptInRule {
|
||||
var configuration = PrivateOutletConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -75,21 +76,10 @@ struct PrivateOutletRule: SwiftSyntaxRule, OptInRule {
|
||||
""", configuration: ["allow_private_set": false], excludeFromDocumentation: true)
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(allowPrivateSet: configuration.allowPrivateSet)
|
||||
}
|
||||
}
|
||||
|
||||
private extension PrivateOutletRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let allowPrivateSet: Bool
|
||||
|
||||
init(allowPrivateSet: Bool) {
|
||||
self.allowPrivateSet = allowPrivateSet
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: MemberBlockItemSyntax) {
|
||||
guard
|
||||
let decl = node.decl.as(VariableDeclSyntax.self),
|
||||
@@ -99,7 +89,7 @@ private extension PrivateOutletRule {
|
||||
return
|
||||
}
|
||||
|
||||
if allowPrivateSet && decl.modifiers.containsPrivateOrFileprivate(setOnly: true) {
|
||||
if configuration.allowPrivateSet && decl.modifiers.containsPrivateOrFileprivate(setOnly: true) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ struct PrivateSubjectRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension PrivateSubjectRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private let subjectTypes: Set<String> = ["PassthroughSubject", "CurrentValueSubject"]
|
||||
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
|
||||
@@ -196,7 +196,7 @@ struct PrivateSwiftUIStatePropertyRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension PrivateSwiftUIStatePropertyRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
[ProtocolDeclSyntax.self]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Foundation
|
||||
import SwiftSyntax
|
||||
|
||||
@SwiftSyntaxRule
|
||||
struct PrivateUnitTestRule: SwiftSyntaxCorrectableRule {
|
||||
var configuration = PrivateUnitTestConfiguration()
|
||||
|
||||
@@ -125,10 +126,6 @@ struct PrivateUnitTestRule: SwiftSyntaxCorrectableRule {
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(configuration: configuration)
|
||||
}
|
||||
|
||||
func makeRewriter(file: SwiftLintFile) -> (some ViolationsSyntaxRewriter)? {
|
||||
Rewriter(
|
||||
configuration: configuration,
|
||||
@@ -139,16 +136,9 @@ struct PrivateUnitTestRule: SwiftSyntaxCorrectableRule {
|
||||
}
|
||||
|
||||
private extension PrivateUnitTestRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: PrivateUnitTestConfiguration
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
init(configuration: PrivateUnitTestConfiguration) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
!node.isPrivate && node.hasParent(configuredIn: configuration) ? .visitChildren : .skipChildren
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ struct ProhibitedInterfaceBuilderRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension ProhibitedInterfaceBuilderRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
if node.isIBOutlet {
|
||||
violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SwiftSyntax
|
||||
|
||||
struct ProhibitedSuperRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct ProhibitedSuperRule: OptInRule {
|
||||
var configuration = ProhibitedSuperConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -69,31 +70,18 @@ struct ProhibitedSuperRule: SwiftSyntaxRule, OptInRule {
|
||||
""")
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(resolvedMethodNames: configuration.resolvedMethodNames)
|
||||
}
|
||||
}
|
||||
|
||||
private extension ProhibitedSuperRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let resolvedMethodNames: [String]
|
||||
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] {
|
||||
[ProtocolDeclSyntax.self]
|
||||
}
|
||||
|
||||
init(resolvedMethodNames: [String]) {
|
||||
self.resolvedMethodNames = resolvedMethodNames
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
guard let body = node.body,
|
||||
node.modifiers.contains(keyword: .override),
|
||||
!node.modifiers.containsStaticOrClass,
|
||||
case let name = node.resolvedName(),
|
||||
resolvedMethodNames.contains(name),
|
||||
configuration.resolvedMethodNames.contains(name),
|
||||
node.numberOfCallsToSuper() > 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ struct QuickDiscouragedFocusedTestRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension QuickDiscouragedFocusedTestRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
|
||||
@@ -15,7 +15,7 @@ struct QuickDiscouragedPendingTestRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension QuickDiscouragedPendingTestRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: FunctionCallExprSyntax) {
|
||||
|
||||
@@ -94,7 +94,7 @@ struct RawValueForCamelCasedCodableEnumRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension RawValueForCamelCasedCodableEnumRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private let codableTypes = Set(["Codable", "Decodable", "Encodable"])
|
||||
|
||||
override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind {
|
||||
|
||||
@@ -69,22 +69,22 @@ struct RequiredDeinitRule: OptInRule {
|
||||
}
|
||||
|
||||
private extension RequiredDeinitRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
let visitor = DeinitVisitor(viewMode: .sourceAccurate)
|
||||
let visitor = DeinitVisitor(configuration: configuration, file: file)
|
||||
if !visitor.walk(tree: node.memberBlock, handler: \.hasDeinit) {
|
||||
violations.append(node.classKeyword.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DeinitVisitor: ViolationsSyntaxVisitor {
|
||||
private(set) var hasDeinit = false
|
||||
final class DeinitVisitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private(set) var hasDeinit = false
|
||||
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: DeinitializerDeclSyntax) {
|
||||
hasDeinit = true
|
||||
override func visitPost(_ node: DeinitializerDeclSyntax) {
|
||||
hasDeinit = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,8 @@ import SwiftSyntax
|
||||
/// case accountCreated
|
||||
/// }
|
||||
/// ````
|
||||
struct RequiredEnumCaseRule: SwiftSyntaxRule, OptInRule {
|
||||
@SwiftSyntaxRule
|
||||
struct RequiredEnumCaseRule: OptInRule {
|
||||
var configuration = RequiredEnumCaseConfiguration()
|
||||
|
||||
private static let exampleConfiguration = [
|
||||
@@ -130,21 +131,10 @@ struct RequiredEnumCaseRule: SwiftSyntaxRule, OptInRule {
|
||||
""", configuration: exampleConfiguration)
|
||||
]
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(configuration: configuration)
|
||||
}
|
||||
}
|
||||
|
||||
private extension RequiredEnumCaseRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let configuration: RequiredEnumCaseConfiguration
|
||||
|
||||
init(configuration: RequiredEnumCaseConfiguration) {
|
||||
self.configuration = configuration
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: EnumDeclSyntax) {
|
||||
guard configuration.protocols.isNotEmpty else {
|
||||
return
|
||||
|
||||
@@ -93,7 +93,7 @@ struct SelfInPropertyInitializationRule: Rule {
|
||||
}
|
||||
|
||||
private extension SelfInPropertyInitializationRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard !node.modifiers.contains(keyword: .lazy),
|
||||
!node.modifiers.containsStaticOrClass,
|
||||
|
||||
@@ -37,7 +37,7 @@ struct StrongIBOutletRule: SwiftSyntaxCorrectableRule, OptInRule {
|
||||
}
|
||||
|
||||
private extension StrongIBOutletRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
if let violationPosition = node.violationPosition {
|
||||
violations.append(violationPosition)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Foundation
|
||||
import SwiftSyntax
|
||||
|
||||
struct TestCaseAccessibilityRule: SwiftSyntaxRule, OptInRule,
|
||||
SubstitutionCorrectableRule {
|
||||
@SwiftSyntaxRule
|
||||
struct TestCaseAccessibilityRule: OptInRule, SubstitutionCorrectableRule {
|
||||
var configuration = TestCaseAccessibilityConfiguration()
|
||||
|
||||
static let description = RuleDescription(
|
||||
@@ -15,10 +15,6 @@ struct TestCaseAccessibilityRule: SwiftSyntaxRule, OptInRule,
|
||||
corrections: TestCaseAccessibilityRuleExamples.corrections
|
||||
)
|
||||
|
||||
func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
|
||||
Visitor(allowedPrefixes: configuration.allowedPrefixes, testParentClasses: configuration.testParentClasses)
|
||||
}
|
||||
|
||||
func violationRanges(in file: SwiftLintFile) -> [NSRange] {
|
||||
makeVisitor(file: file)
|
||||
.walk(tree: file.syntaxTree, handler: \.violations)
|
||||
@@ -33,101 +29,84 @@ struct TestCaseAccessibilityRule: SwiftSyntaxRule, OptInRule,
|
||||
}
|
||||
|
||||
private extension TestCaseAccessibilityRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor {
|
||||
private let allowedPrefixes: Set<String>
|
||||
private let testParentClasses: Set<String>
|
||||
|
||||
init(allowedPrefixes: Set<String>, testParentClasses: Set<String>) {
|
||||
self.allowedPrefixes = allowedPrefixes
|
||||
self.testParentClasses = testParentClasses
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
guard !testParentClasses.isDisjoint(with: node.inheritedTypes) else {
|
||||
guard !configuration.testParentClasses.isDisjoint(with: node.inheritedTypes) else {
|
||||
return
|
||||
}
|
||||
|
||||
violations.append(
|
||||
contentsOf: XCTestClassVisitor(allowedPrefixes: allowedPrefixes)
|
||||
contentsOf: XCTestClassVisitor(configuration: configuration, file: file)
|
||||
.walk(tree: node.memberBlock, handler: \.violations)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class XCTestClassVisitor: ViolationsSyntaxVisitor {
|
||||
private let allowedPrefixes: Set<String>
|
||||
final class XCTestClassVisitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
init(allowedPrefixes: Set<String>) {
|
||||
self.allowedPrefixes = allowedPrefixes
|
||||
super.init(viewMode: .sourceAccurate)
|
||||
}
|
||||
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard !node.modifiers.containsPrivateOrFileprivate(),
|
||||
!XCTestHelpers.isXCTestVariable(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
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard !node.modifiers.containsPrivateOrFileprivate(),
|
||||
!XCTestHelpers.isXCTestVariable(node) else {
|
||||
return
|
||||
}
|
||||
|
||||
violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia)
|
||||
return
|
||||
}
|
||||
}
|
||||
for binding in node.bindings {
|
||||
guard let pattern = binding.pattern.as(IdentifierPatternSyntax.self),
|
||||
case let name = pattern.identifier.text,
|
||||
!configuration.allowedPrefixes.contains(where: name.hasPrefix) else {
|
||||
continue
|
||||
}
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
guard hasViolation(modifiers: node.modifiers, identifierToken: node.name),
|
||||
!XCTestHelpers.isXCTestFunction(node) else {
|
||||
return
|
||||
violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
guard hasViolation(modifiers: node.modifiers, identifierToken: node.name),
|
||||
!XCTestHelpers.isXCTestFunction(node) else {
|
||||
return
|
||||
}
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
if hasViolation(modifiers: node.modifiers, identifierToken: node.name) {
|
||||
violations.append(node.classKeyword.positionAfterSkippingLeadingTrivia)
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
|
||||
override func visitPost(_ node: EnumDeclSyntax) {
|
||||
if hasViolation(modifiers: node.modifiers, identifierToken: node.name) {
|
||||
violations.append(node.enumKeyword.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()
|
||||
&& !configuration.allowedPrefixes.contains(where: identifierToken.text.hasPrefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user