Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harmonize rule extensions #5272

Merged
merged 2 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,44 +74,46 @@ struct ExplicitTypeInterfaceRule: OptInRule, ConfigurationProviderRule, SwiftSyn
}
}

private class Visitor: ViolationsSyntaxVisitor {
let configuration: ExplicitTypeInterfaceConfiguration
private extension ExplicitTypeInterfaceRule {
final class Visitor: ViolationsSyntaxVisitor {
let configuration: ExplicitTypeInterfaceConfiguration

override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }
override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] }

init(configuration: ExplicitTypeInterfaceConfiguration) {
self.configuration = configuration
super.init(viewMode: .sourceAccurate)
}
init(configuration: ExplicitTypeInterfaceConfiguration) {
self.configuration = configuration
super.init(viewMode: .sourceAccurate)
}

override func visitPost(_ node: VariableDeclSyntax) {
if node.modifiers.contains(keyword: .class) {
if configuration.allowedKinds.contains(.class) {
checkViolation(node)
}
} else if node.modifiers.contains(keyword: .static) {
if configuration.allowedKinds.contains(.static) {
checkViolation(node)
}
} else if node.parent?.is(MemberBlockItemSyntax.self) == true {
if configuration.allowedKinds.contains(.instance) {
checkViolation(node)
}
} else if node.parent?.is(CodeBlockItemSyntax.self) == true {
if configuration.allowedKinds.contains(.local) {
checkViolation(node)
override func visitPost(_ node: VariableDeclSyntax) {
if node.modifiers.contains(keyword: .class) {
if configuration.allowedKinds.contains(.class) {
checkViolation(node)
}
} else if node.modifiers.contains(keyword: .static) {
if configuration.allowedKinds.contains(.static) {
checkViolation(node)
}
} else if node.parent?.is(MemberBlockItemSyntax.self) == true {
if configuration.allowedKinds.contains(.instance) {
checkViolation(node)
}
} else if node.parent?.is(CodeBlockItemSyntax.self) == true {
if configuration.allowedKinds.contains(.local) {
checkViolation(node)
}
}
}
}

private func checkViolation(_ node: VariableDeclSyntax) {
for binding in node.bindings {
if configuration.allowRedundancy, let initializer = binding.initializer,
initializer.isTypeConstructor || initializer.isTypeReference {
continue
}
if binding.typeAnnotation == nil {
violations.append(binding.positionAfterSkippingLeadingTrivia)
private func checkViolation(_ node: VariableDeclSyntax) {
for binding in node.bindings {
if configuration.allowRedundancy, let initializer = binding.initializer,
initializer.isTypeConstructor || initializer.isTypeReference {
continue
}
if binding.typeAnnotation == nil {
violations.append(binding.positionAfterSkippingLeadingTrivia)
}
}
}
}
Expand Down
20 changes: 11 additions & 9 deletions Source/SwiftLintBuiltInRules/Rules/Idiomatic/ForceCastRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@ struct ForceCastRule: ConfigurationProviderRule, SwiftSyntaxRule {
)

func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
ForceCastRuleVisitor(viewMode: .sourceAccurate)
Visitor(viewMode: .sourceAccurate)
}
}

private final class ForceCastRuleVisitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: AsExprSyntax) {
if node.questionOrExclamationMark?.tokenKind == .exclamationMark {
violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia)
private extension ForceCastRule {
final class Visitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: AsExprSyntax) {
if node.questionOrExclamationMark?.tokenKind == .exclamationMark {
violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia)
}
}
}

override func visitPost(_ node: UnresolvedAsExprSyntax) {
if node.questionOrExclamationMark?.tokenKind == .exclamationMark {
violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia)
override func visitPost(_ node: UnresolvedAsExprSyntax) {
if node.questionOrExclamationMark?.tokenKind == .exclamationMark {
violations.append(node.asKeyword.positionAfterSkippingLeadingTrivia)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@ struct ForceUnwrappingRule: OptInRule, SwiftSyntaxRule, ConfigurationProviderRul
)

func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
ForceUnwrappingVisitor(viewMode: .sourceAccurate)
Visitor(viewMode: .sourceAccurate)
}
}

private final class ForceUnwrappingVisitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: ForceUnwrapExprSyntax) {
violations.append(node.exclamationMark.positionAfterSkippingLeadingTrivia)
private extension ForceUnwrappingRule {
final class Visitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: ForceUnwrapExprSyntax) {
violations.append(node.exclamationMark.positionAfterSkippingLeadingTrivia)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,31 @@ private extension PatternMatchingKeywordsRule {
violations.append(contentsOf: localViolations)
}
}
}

final class TupleVisitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: LabeledExprListSyntax) {
let list = node.flatteningEnumPatterns()
.compactMap { elem in
elem.expression.asValueBindingPattern()
}

guard list.count > 1,
let firstLetOrVar = list.first?.bindingSpecifier.tokenKind else {
return
private final class TupleVisitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: LabeledExprListSyntax) {
let list = node.flatteningEnumPatterns()
.compactMap { elem in
elem.expression.asValueBindingPattern()
}

let hasViolation = list.allSatisfy { elem in
elem.bindingSpecifier.tokenKind == firstLetOrVar
}
guard list.count > 1,
let firstLetOrVar = list.first?.bindingSpecifier.tokenKind else {
return
}

guard hasViolation else {
return
}
let hasViolation = list.allSatisfy { elem in
elem.bindingSpecifier.tokenKind == firstLetOrVar
}

violations.append(contentsOf: list.compactMap { elem in
return elem.bindingSpecifier.positionAfterSkippingLeadingTrivia
})
guard hasViolation else {
return
}

violations.append(contentsOf: list.compactMap { elem in
return elem.bindingSpecifier.positionAfterSkippingLeadingTrivia
})
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ private extension PreferZeroOverExplicitInitRule {
}
}

private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
private(set) var correctionPositions: [AbsolutePosition] = []
let locationConverter: SourceLocationConverter
let disabledRegions: [SourceRange]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private extension PrivateOverFilePrivateRule {
}
}

private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
private(set) var correctionPositions: [AbsolutePosition] = []
private let validateExtensions: Bool
private let locationConverter: SourceLocationConverter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private extension RedundantNilCoalescingRule {
}
}

private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
private(set) var correctionPositions: [AbsolutePosition] = []
let locationConverter: SourceLocationConverter
let disabledRegions: [SourceRange]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ struct ReturnValueFromVoidFunctionRule: ConfigurationProviderRule, OptInRule, Sw
)

func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor {
ReturnValueFromVoidFunctionVisitor(viewMode: .sourceAccurate)
Visitor(viewMode: .sourceAccurate)
}
}

private final class ReturnValueFromVoidFunctionVisitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: ReturnStmtSyntax) {
if node.expression != nil,
let functionNode = Syntax(node).enclosingFunction(),
functionNode.returnsVoid {
violations.append(node.positionAfterSkippingLeadingTrivia)
private extension ReturnValueFromVoidFunctionRule {
final class Visitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: ReturnStmtSyntax) {
if node.expression != nil,
let functionNode = Syntax(node).enclosingFunction(),
functionNode.returnsVoid {
violations.append(node.positionAfterSkippingLeadingTrivia)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,37 +88,39 @@ struct ShorthandOptionalBindingRule: OptInRule, SwiftSyntaxCorrectableRule, Conf
}
}

private class Visitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: OptionalBindingConditionSyntax) {
if node.isShadowingOptionalBinding {
violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia)
private extension ShorthandOptionalBindingRule {
final class Visitor: ViolationsSyntaxVisitor {
override func visitPost(_ node: OptionalBindingConditionSyntax) {
if node.isShadowingOptionalBinding {
violations.append(node.bindingSpecifier.positionAfterSkippingLeadingTrivia)
}
}
}
}

private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
private(set) var correctionPositions: [AbsolutePosition] = []
private let locationConverter: SourceLocationConverter
private let disabledRegions: [SourceRange]

init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) {
self.locationConverter = locationConverter
self.disabledRegions = disabledRegions
}
final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
private(set) var correctionPositions: [AbsolutePosition] = []
private let locationConverter: SourceLocationConverter
private let disabledRegions: [SourceRange]

override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax {
guard
node.isShadowingOptionalBinding,
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter)
else {
return super.visit(node)
init(locationConverter: SourceLocationConverter, disabledRegions: [SourceRange]) {
self.locationConverter = locationConverter
self.disabledRegions = disabledRegions
}

correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
let newNode = node
.with(\.initializer, nil)
.with(\.pattern, node.pattern.with(\.trailingTrivia, node.trailingTrivia))
return super.visit(newNode)
override func visit(_ node: OptionalBindingConditionSyntax) -> OptionalBindingConditionSyntax {
guard
node.isShadowingOptionalBinding,
!node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter)
else {
return super.visit(node)
}

correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
let newNode = node
.with(\.initializer, nil)
.with(\.pattern, node.pattern.with(\.trailingTrivia, node.trailingTrivia))
return super.visit(newNode)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,39 +135,6 @@ private enum ProtocolRequirementType: Equatable {
}

private extension StrictFilePrivateRule {
final class ProtocolCollector: ViolationsSyntaxVisitor {
private(set) var protocols = [String: [ProtocolRequirementType]]()
private var currentProtocolName: String = ""

override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .allExcept(ProtocolDeclSyntax.self) }

override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind {
currentProtocolName = node.name.text
return .visitChildren
}

override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
protocols[currentProtocolName, default: []].append(.method(node.name.text))
return .skipChildren
}

override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
for binding in node.bindings {
guard let name = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.text,
let accessorBlock = binding.accessorBlock else {
continue
}
if accessorBlock.specifiesGetAccessor {
protocols[currentProtocolName, default: []].append(.getter(name))
}
if accessorBlock.specifiesSetAccessor {
protocols[currentProtocolName, default: []].append(.setter(name))
}
}
return .skipChildren
}
}

final class Visitor: ViolationsSyntaxVisitor {
private let file: SourceFileSyntax

Expand Down Expand Up @@ -245,6 +212,39 @@ private extension StrictFilePrivateRule {
}
}

private final class ProtocolCollector: ViolationsSyntaxVisitor {
private(set) var protocols = [String: [ProtocolRequirementType]]()
private var currentProtocolName: String = ""

override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .allExcept(ProtocolDeclSyntax.self) }

override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind {
currentProtocolName = node.name.text
return .visitChildren
}

override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
protocols[currentProtocolName, default: []].append(.method(node.name.text))
return .skipChildren
}

override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
for binding in node.bindings {
guard let name = binding.pattern.as(IdentifierPatternSyntax.self)?.identifier.text,
let accessorBlock = binding.accessorBlock else {
continue
}
if accessorBlock.specifiesGetAccessor {
protocols[currentProtocolName, default: []].append(.getter(name))
}
if accessorBlock.specifiesSetAccessor {
protocols[currentProtocolName, default: []].append(.setter(name))
}
}
return .skipChildren
}
}

private extension InheritanceClauseSyntax? {
var inheritedTypeNames: [String] {
self?.inheritedTypes.compactMap { $0.type.as(IdentifierTypeSyntax.self)?.name.text } ?? []
Expand Down
Loading