diff --git a/CHANGELOG.md b/CHANGELOG.md index 06179da475..428bf65763 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,16 @@ [#3399](https://github.com/realm/SwiftLint/issues/3399) [#3605](https://github.com/realm/SwiftLint/issues/3605) +* Speed up linting by up to 6% updating to use a newer version of + `SwiftSyntax`. + [JP Simard](https://github.com/jpsim) + +* Catch more valid `legacy_multiple` violations. + [JP Simard](https://github.com/jpsim) + +* Catch more valid `no_magic_numbers` violations. + [JP Simard](https://github.com/jpsim) + #### Bug Fixes * Report violations in all `_length` rules when the error threshold is @@ -125,6 +135,10 @@ [Mathias Schreck](https://github.com/lo1tuma) [#4772](https://github.com/realm/SwiftLint/issues/4772) +* Fix false positives in `attributes` rule when using property wrappers + with keypath arguments. + [JP Simard](https://github.com/jpsim) + ## 0.50.3: Bundle of Towels #### Breaking diff --git a/Package.resolved b/Package.resolved index 8282a3cfca..17cc333058 100644 --- a/Package.resolved +++ b/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-syntax.git", "state" : { - "revision" : "edd2d0cdb988ac45e2515e0dd0624e4a6de54a94", - "version" : "0.50800.0-SNAPSHOT-2022-12-29-a" + "revision" : "013a48e2312e57b7b355db25bd3ea75282ebf274", + "version" : "0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a" } }, { diff --git a/Package.swift b/Package.swift index 61ded2816f..b21debcd91 100644 --- a/Package.swift +++ b/Package.swift @@ -30,7 +30,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.2.1")), - .package(url: "https://github.com/apple/swift-syntax.git", exact: "0.50800.0-SNAPSHOT-2022-12-29-a"), + .package(url: "https://github.com/apple/swift-syntax.git", exact: "0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a"), .package(url: "https://github.com/jpsim/SourceKitten.git", .upToNextMinor(from: "0.34.0")), .package(url: "https://github.com/jpsim/Yams.git", from: "5.0.4"), .package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.9.0"), diff --git a/Source/SwiftLintFramework/Extensions/SwiftLintFile+BodyLineCount.swift b/Source/SwiftLintFramework/Extensions/SwiftLintFile+BodyLineCount.swift index ad270a832e..9c90827bf7 100644 --- a/Source/SwiftLintFramework/Extensions/SwiftLintFile+BodyLineCount.swift +++ b/Source/SwiftLintFramework/Extensions/SwiftLintFile+BodyLineCount.swift @@ -44,7 +44,9 @@ extension SwiftLintFile { .tokens(viewMode: .sourceAccurate) .reduce(into: []) { linesWithTokens, token in if case .stringSegment = token.tokenKind { - let sourceRange = token.withoutTrivia().sourceRange(converter: locationConverter) + let sourceRange = token + .trimmed + .sourceRange(converter: locationConverter) let startLine = sourceRange.start.line! let endLine = sourceRange.end.line! linesWithTokens.formUnion(startLine...endLine) diff --git a/Source/SwiftLintFramework/Extensions/SwiftSyntax+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/SwiftSyntax+SwiftLint.swift index 581ed62279..55a939e640 100644 --- a/Source/SwiftLintFramework/Extensions/SwiftSyntax+SwiftLint.swift +++ b/Source/SwiftLintFramework/Extensions/SwiftSyntax+SwiftLint.swift @@ -8,7 +8,7 @@ extension SyntaxVisitor: SwiftLintSyntaxVisitor {} extension SwiftLintSyntaxVisitor { func walk(tree: SyntaxType, handler: (Self) -> T) -> T { - #if DEBUG +#if DEBUG // workaround for stack overflow when running in debug // https://bugs.swift.org/browse/SR-11170 let lock = NSLock() @@ -31,10 +31,10 @@ extension SwiftLintSyntaxVisitor { } return handler(self) - #else +#else walk(tree) return handler(self) - #endif +#endif } func walk(file: SwiftLintFile, handler: (Self) -> [T]) -> [T] { @@ -107,19 +107,17 @@ extension StringLiteralExprSyntax { extension TokenKind { var isEqualityComparison: Bool { - self == .spacedBinaryOperator("==") || - self == .spacedBinaryOperator("!=") || - self == .unspacedBinaryOperator("==") + self == .binaryOperator("==") || self == .binaryOperator("!=") } } extension ModifierListSyntax? { var containsLazy: Bool { - contains(tokenKind: .contextualKeyword("lazy")) + contains(tokenKind: .keyword(.lazy)) } var containsOverride: Bool { - contains(tokenKind: .contextualKeyword("override")) + contains(tokenKind: .keyword(.override)) } var containsStaticOrClass: Bool { @@ -127,15 +125,15 @@ extension ModifierListSyntax? { } var isStatic: Bool { - contains(tokenKind: .staticKeyword) + contains(tokenKind: .keyword(.static)) } var isClass: Bool { - contains(tokenKind: .classKeyword) + contains(tokenKind: .keyword(.class)) } var isFileprivate: Bool { - contains(tokenKind: .fileprivateKeyword) + contains(tokenKind: .keyword(.fileprivate)) } var isPrivateOrFileprivate: Bool { @@ -144,13 +142,13 @@ extension ModifierListSyntax? { } return modifiers.contains { elem in - (elem.name.tokenKind == .privateKeyword || elem.name.tokenKind == .fileprivateKeyword) && + (elem.name.tokenKind == .keyword(.private) || elem.name.tokenKind == .keyword(.fileprivate)) && elem.detail == nil } } var isFinal: Bool { - contains(tokenKind: .contextualKeyword("final")) + contains(tokenKind: .keyword(.final)) } private func contains(tokenKind: TokenKind) -> Bool { @@ -162,17 +160,34 @@ extension ModifierListSyntax? { } } +extension AttributeSyntax { + var attributeNameText: String { + attributeName.as(SimpleTypeIdentifierSyntax.self)?.name.text ?? + attributeName.description + } +} + +extension AttributeListSyntax? { + func contains(attributeNamed attributeName: String) -> Bool { + self?.contains { $0.as(AttributeSyntax.self)?.attributeNameText == attributeName } == true + } +} + +extension TokenKind { + var isUnavailableKeyword: Bool { + self == .keyword(.unavailable) || self == .identifier("unavailable") + } +} + extension VariableDeclSyntax { var isIBOutlet: Bool { - attributes?.contains { attr in - attr.as(AttributeSyntax.self)?.attributeName.tokenKind == .identifier("IBOutlet") - } ?? false + attributes.contains(attributeNamed: "IBOutlet") } var weakOrUnownedModifier: DeclModifierSyntax? { modifiers?.first { decl in - decl.name.tokenKind == .contextualKeyword("weak") || - decl.name.tokenKind == .contextualKeyword("unowned") + decl.name.tokenKind == .keyword(.weak) || + decl.name.tokenKind == .keyword(.unowned) } } @@ -207,9 +222,7 @@ public extension EnumDeclSyntax { extension FunctionDeclSyntax { var isIBAction: Bool { - attributes?.contains { attr in - attr.as(AttributeSyntax.self)?.attributeName.tokenKind == .identifier("IBAction") - } ?? false + attributes.contains(attributeNamed: "IBAction") } /// Returns the signature including arguments, e.g "setEditing(_:animated:)" @@ -241,13 +254,13 @@ extension FunctionDeclSyntax { extension AccessorBlockSyntax { var getAccessor: AccessorDeclSyntax? { accessors.first { accessor in - accessor.accessorKind.tokenKind == .contextualKeyword("get") + accessor.accessorKind.tokenKind == .keyword(.get) } } var setAccessor: AccessorDeclSyntax? { accessors.first { accessor in - accessor.accessorKind.tokenKind == .contextualKeyword("set") + accessor.accessorKind.tokenKind == .keyword(.set) } } diff --git a/Source/SwiftLintFramework/Helpers/LegacyFunctionRuleHelper.swift b/Source/SwiftLintFramework/Helpers/LegacyFunctionRuleHelper.swift index ae959be20c..fa4a902888 100644 --- a/Source/SwiftLintFramework/Helpers/LegacyFunctionRuleHelper.swift +++ b/Source/SwiftLintFramework/Helpers/LegacyFunctionRuleHelper.swift @@ -62,7 +62,7 @@ enum LegacyFunctionRuleHelper { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let trimmedArguments = node.argumentList.map { $0.trimmed() } + let trimmedArguments = node.argumentList.map { $0.trimmingTrailingComma() } let rewriteStrategy = legacyFunctions[funcName] let expr: ExprSyntax @@ -82,8 +82,8 @@ enum LegacyFunctionRuleHelper { } return expr - .withLeadingTrivia(node.leadingTrivia ?? .zero) - .withTrailingTrivia(node.trailingTrivia ?? .zero) + .with(\.leadingTrivia, node.leadingTrivia ?? .zero) + .with(\.trailingTrivia, node.trailingTrivia ?? .zero) } } } @@ -103,10 +103,7 @@ private extension FunctionCallExprSyntax { } private extension TupleExprElementSyntax { - func trimmed() -> TupleExprElementSyntax { - self - .withoutTrivia() - .withTrailingComma(nil) - .withoutTrivia() + func trimmingTrailingComma() -> TupleExprElementSyntax { + self.trimmed.with(\.trailingComma, nil).trimmed } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/BlockBasedKVORule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/BlockBasedKVORule.swift index b4ad6b77a4..5f39b0eb46 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/BlockBasedKVORule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/BlockBasedKVORule.swift @@ -53,7 +53,7 @@ private extension BlockBasedKVORule { } let types = parameterList - .compactMap { $0.type?.withoutTrivia().description.replacingOccurrences(of: " ", with: "") } + .compactMap { $0.type?.trimmedDescription.replacingOccurrences(of: " ", with: "") } let firstTypes = ["String?", "Any?", "[NSKeyValueChangeKey:Any]?", "UnsafeMutableRawPointer?"] let secondTypes = ["String?", "Any?", "Dictionary?", "UnsafeMutableRawPointer?"] if types == firstTypes || types == secondTypes { diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ConvenienceTypeRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ConvenienceTypeRule.swift index 8726f2aa8e..72b7f28ab2 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ConvenienceTypeRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ConvenienceTypeRule.swift @@ -198,15 +198,11 @@ private extension TypeInheritanceClauseSyntax? { private extension AttributeListSyntax? { var containsObjcMembers: Bool { - self?.contains { elem in - elem.as(AttributeSyntax.self)?.attributeName.tokenKind == .identifier("objcMembers") - } ?? false + contains(attributeNamed: "objcMembers") } var containsObjc: Bool { - self?.contains { elem in - elem.as(AttributeSyntax.self)?.attributeName.tokenKind == .contextualKeyword("objc") - } ?? false + contains(attributeNamed: "objc") } } @@ -218,12 +214,12 @@ private extension AttributeListSyntax? { return attrs.contains { elem in guard let attr = elem.as(AttributeSyntax.self), - let arguments = attr.argument?.as(AvailabilitySpecListSyntax.self) else { + let arguments = attr.argument?.as(AvailabilitySpecListSyntax.self) else { return false } - return attr.attributeName.tokenKind == .contextualKeyword("available") && arguments.contains { arg in - arg.entry.as(TokenSyntax.self)?.tokenKind == .contextualKeyword("unavailable") + return attr.attributeNameText == "available" && arguments.contains { arg in + arg.entry.as(TokenSyntax.self)?.tokenKind.isUnavailableKeyword == true } } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/DiscouragedAssertRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/DiscouragedAssertRule.swift index 5992d1d294..4c018c5780 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/DiscouragedAssertRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/DiscouragedAssertRule.swift @@ -39,11 +39,11 @@ struct DiscouragedAssertRule: SwiftSyntaxRule, OptInRule, ConfigurationProviderR private extension DiscouragedAssertRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: FunctionCallExprSyntax) { - guard node.calledExpression.as(IdentifierExprSyntax.self)?.identifier.withoutTrivia().text == "assert", + guard node.calledExpression.as(IdentifierExprSyntax.self)?.identifier.text == "assert", let firstArg = node.argumentList.first, firstArg.label == nil, let boolExpr = firstArg.expression.as(BooleanLiteralExprSyntax.self), - boolExpr.booleanLiteral.tokenKind == .falseKeyword else { + boolExpr.booleanLiteral.tokenKind == .keyword(.false) else { return } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitInitRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitInitRule.swift index aaf56e9dd6..0ef068e5a2 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitInitRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitInitRule.swift @@ -218,7 +218,8 @@ private extension ExplicitInitRule { } correctionPositions.append(violationPosition) - return super.visit(node.withCalledExpression("\(calledBase.withoutTrivia())")) + let newNode = node.with(\.calledExpression, calledBase.trimmed) + return super.visit(newNode) } } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTopLevelACLRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTopLevelACLRule.swift index b4f90ec83e..c3ecccb8c7 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTopLevelACLRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTopLevelACLRule.swift @@ -108,11 +108,11 @@ private extension ExplicitTopLevelACLRule { private extension DeclModifierSyntax { var isACLModifier: Bool { let aclModifiers: Set = [ - .privateKeyword, - .fileprivateKeyword, - .internalKeyword, - .publicKeyword, - .contextualKeyword("open") + .keyword(.private), + .keyword(.fileprivate), + .keyword(.internal), + .keyword(.public), + .keyword(.open) ] return detail == nil && aclModifiers.contains(name.tokenKind) diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift index 7fbe39c496..6f03d4ee11 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ExplicitTypeInterfaceRule.swift @@ -132,7 +132,7 @@ private extension InitializerClauseSyntax { } var isTypeReference: Bool { - value.as(MemberAccessExprSyntax.self)?.name.tokenKind == .selfKeyword + value.as(MemberAccessExprSyntax.self)?.name.tokenKind == .keyword(.self) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/FatalErrorMessageRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/FatalErrorMessageRule.swift index 63b438cb42..a8bff63364 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/FatalErrorMessageRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/FatalErrorMessageRule.swift @@ -45,7 +45,7 @@ private extension FatalErrorMessageRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: FunctionCallExprSyntax) { guard let expression = node.calledExpression.as(IdentifierExprSyntax.self), - expression.identifier.withoutTrivia().text == "fatalError", + expression.identifier.text == "fatalError", node.argumentList.isEmptyOrEmptyString else { return } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/FileNameRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/FileNameRule.swift index fda4725eb5..01d2c4b4a9 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/FileNameRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/FileNameRule.swift @@ -87,6 +87,6 @@ private class TypeNameCollectingVisitor: SyntaxVisitor { } override func visitPost(_ node: ExtensionDeclSyntax) { - names.insert(node.extendedType.withoutTrivia().description) + names.insert(node.extendedType.trimmedDescription) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ForWhereRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ForWhereRule.swift index c6a1c8c238..93961c287d 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ForWhereRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ForWhereRule.swift @@ -134,26 +134,26 @@ private extension ForWhereRule { override func visitPost(_ node: ForInStmtSyntax) { guard node.whereClause == nil, - case let statements = node.body.statements, - let ifStatement = statements.onlyElement?.item.as(IfStmtSyntax.self), - ifStatement.elseBody == nil, - !ifStatement.containsOptionalBinding, - !ifStatement.containsPatternCondition, - let condition = ifStatement.conditions.onlyElement, + let onlyExprStmt = node.body.statements.onlyElement?.item.as(ExpressionStmtSyntax.self), + let ifExpr = onlyExprStmt.expression.as(IfExprSyntax.self), + ifExpr.elseBody == nil, + !ifExpr.containsOptionalBinding, + !ifExpr.containsPatternCondition, + let condition = ifExpr.conditions.onlyElement, !condition.containsMultipleConditions else { return } - if allowForAsFilter, ifStatement.containsReturnStatement { + if allowForAsFilter, ifExpr.containsReturnStatement { return } - violations.append(ifStatement.positionAfterSkippingLeadingTrivia) + violations.append(ifExpr.positionAfterSkippingLeadingTrivia) } } } -private extension IfStmtSyntax { +private extension IfExprSyntax { var containsOptionalBinding: Bool { conditions.contains { element in element.condition.is(OptionalBindingConditionSyntax.self) diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/FunctionDefaultParameterAtEndRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/FunctionDefaultParameterAtEndRule.swift index a59d6c8978..c997f3cf6c 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/FunctionDefaultParameterAtEndRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/FunctionDefaultParameterAtEndRule.swift @@ -129,8 +129,6 @@ private extension FunctionParameterSyntax { return false } - return attrType.attributes?.contains { attr in - attr.as(AttributeSyntax.self)?.attributeName.tokenKind == .identifier("escaping") - } ?? false + return attrType.attributes.contains(attributeNamed: "escaping") } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/JoinedDefaultParameterRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/JoinedDefaultParameterRule.swift index 364be009d5..6b6faaf170 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/JoinedDefaultParameterRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/JoinedDefaultParameterRule.swift @@ -76,7 +76,7 @@ private extension JoinedDefaultParameterRule { } correctionPositions.append(violationPosition) - let newNode = node.withArgumentList(nil) + let newNode = node.with(\.argumentList, []) return super.visit(newNode) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstantRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstantRule.swift index 595bfe9306..b80ee66b17 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstantRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstantRule.swift @@ -63,8 +63,8 @@ private extension LegacyConstantRule { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) return ("\(raw: correction)" as ExprSyntax) - .withLeadingTrivia(node.leadingTrivia ?? .zero) - .withTrailingTrivia(node.trailingTrivia ?? .zero) + .with(\.leadingTrivia, node.leadingTrivia ?? .zero) + .with(\.trailingTrivia, node.trailingTrivia ?? .zero) } override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax { @@ -78,8 +78,8 @@ private extension LegacyConstantRule { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) return ("\(raw: calledExpression.identifier.text).pi" as ExprSyntax) - .withLeadingTrivia(node.leadingTrivia ?? .zero) - .withTrailingTrivia(node.trailingTrivia ?? .zero) + .with(\.leadingTrivia, node.leadingTrivia ?? .zero) + .with(\.trailingTrivia, node.trailingTrivia ?? .zero) } } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstructorRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstructorRule.swift index 23aa5069e6..0e2875c57a 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstructorRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyConstructorRule.swift @@ -140,7 +140,7 @@ private extension LegacyConstructorRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: FunctionCallExprSyntax) { if let identifierExpr = node.calledExpression.as(IdentifierExprSyntax.self), - constructorsToCorrectedNames[identifierExpr.identifier.withoutTrivia().text] != nil { + constructorsToCorrectedNames[identifierExpr.identifier.text] != nil { violations.append(node.positionAfterSkippingLeadingTrivia) } } @@ -158,7 +158,7 @@ private extension LegacyConstructorRule { override func visit(_ node: FunctionCallExprSyntax) -> ExprSyntax { guard let identifierExpr = node.calledExpression.as(IdentifierExprSyntax.self), - case let identifier = identifierExpr.identifier.withoutTrivia().text, + case let identifier = identifierExpr.identifier.text, let correctedName = constructorsToCorrectedNames[identifier], let args = constructorsToArguments[identifier], !node.isContainedIn(regions: disabledRegions, locationConverter: locationConverter) else { @@ -169,10 +169,11 @@ private extension LegacyConstructorRule { let arguments = TupleExprElementListSyntax(node.argumentList.map { elem in elem - .withLabel(.identifier(args[elem.indexInParent])) - .withColon(.colonToken(trailingTrivia: .space)) + .with(\.label, .identifier(args[elem.indexInParent])) + .with(\.colon, .colonToken(trailingTrivia: .space)) }) - let newExpression = identifierExpr.withIdentifier( + let newExpression = identifierExpr.with( + \.identifier, .identifier( correctedName, leadingTrivia: identifierExpr.identifier.leadingTrivia, @@ -180,8 +181,8 @@ private extension LegacyConstructorRule { ) ) let newNode = node - .withCalledExpression(ExprSyntax(newExpression)) - .withArgumentList(arguments) + .with(\.calledExpression, ExprSyntax(newExpression)) + .with(\.argumentList, arguments) return super.visit(newNode) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyHashingRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyHashingRule.swift index 851965d630..c0ecc77673 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyHashingRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyHashingRule.swift @@ -85,7 +85,7 @@ extension LegacyHashingRule { override func visitPost(_ node: VariableDeclSyntax) { guard node.parent?.is(MemberDeclListItemSyntax.self) == true, - node.letOrVarKeyword.tokenKind == .varKeyword, + node.letOrVarKeyword.tokenKind == .keyword(.var), let binding = node.bindings.onlyElement, let identifier = binding.pattern.as(IdentifierPatternSyntax.self), identifier.identifier.text == "hashValue", diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyMultipleRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyMultipleRule.swift index 7e25b0fd78..a86e1cb66f 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyMultipleRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyMultipleRule.swift @@ -52,7 +52,7 @@ private extension LegacyMultipleRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: InfixOperatorExprSyntax) { guard let operatorNode = node.operatorOperand.as(BinaryOperatorExprSyntax.self), - operatorNode.operatorToken.tokenKind == .spacedBinaryOperator("%"), + operatorNode.operatorToken.tokenKind == .binaryOperator("%"), let parent = node.parent?.as(InfixOperatorExprSyntax.self), let parentOperatorNode = parent.operatorOperand.as(BinaryOperatorExprSyntax.self), parentOperatorNode.isEqualityOrInequalityOperator else { @@ -80,8 +80,7 @@ private extension LegacyMultipleRule { private extension BinaryOperatorExprSyntax { var isEqualityOrInequalityOperator: Bool { - operatorToken.tokenKind == .spacedBinaryOperator("==") || - operatorToken.tokenKind == .unspacedBinaryOperator("==") || - operatorToken.tokenKind == .spacedBinaryOperator("!=") + operatorToken.tokenKind == .binaryOperator("==") || + operatorToken.tokenKind == .binaryOperator("!=") } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyRandomRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyRandomRule.swift index 8dd4f712b4..50221b5302 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/LegacyRandomRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/LegacyRandomRule.swift @@ -36,7 +36,7 @@ private extension LegacyRandomRule { ] override func visitPost(_ node: FunctionCallExprSyntax) { - if let function = node.calledExpression.as(IdentifierExprSyntax.self)?.identifier.withoutTrivia().text, + if let function = node.calledExpression.as(IdentifierExprSyntax.self)?.identifier.text, Self.legacyRandomFunctions.contains(function) { violations.append(node.positionAfterSkippingLeadingTrivia) } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ObjectLiteralRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ObjectLiteralRule.swift index e1a08e6927..fb48c3ef55 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ObjectLiteralRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ObjectLiteralRule.swift @@ -54,7 +54,7 @@ private extension ObjectLiteralRule { return } - let name = node.calledExpression.withoutTrivia().description + let name = node.calledExpression.trimmedDescription if validateImageLiteral, isImageNamedInit(node: node, name: name) { violations.append(node.positionAfterSkippingLeadingTrivia) } else if validateColorLiteral, isColorInit(node: node, name: name) { diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift index 734284e75a..f6dd04072d 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/PreferZeroOverExplicitInitRule.swift @@ -76,11 +76,12 @@ private extension PreferZeroOverExplicitInitRule { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let newNode: MemberAccessExprSyntax = "\(raw: name).zero" + let newNode = MemberAccessExprSyntax(name: "zero") + .with(\.base, "\(raw: name)") return super.visit( newNode - .withLeadingTrivia(node.leadingTrivia ?? .zero) - .withTrailingTrivia(node.trailingTrivia ?? .zero) + .with(\.leadingTrivia, node.leadingTrivia ?? .zero) + .with(\.trailingTrivia, node.trailingTrivia ?? .zero) ) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift index ac53d9dc31..705e5e8e83 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift @@ -155,7 +155,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } @@ -166,7 +166,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } @@ -177,7 +177,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } @@ -188,7 +188,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } @@ -199,7 +199,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } @@ -210,7 +210,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } @@ -221,7 +221,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } @@ -232,7 +232,7 @@ private extension PrivateOverFilePrivateRule { } correctionPositions.append(modifier.positionAfterSkippingLeadingTrivia) - let newNode = node.withModifiers(node.modifiers?.replacing(fileprivateModifier: modifier)) + let newNode = node.with(\.modifiers, node.modifiers?.replacing(fileprivateModifier: modifier)) return DeclSyntax(newNode) } } @@ -240,7 +240,7 @@ private extension PrivateOverFilePrivateRule { private extension ModifierListSyntax? { var fileprivateModifier: DeclModifierSyntax? { - self?.first { $0.name.tokenKind == .fileprivateKeyword } + self?.first { $0.name.tokenKind == .keyword(.fileprivate) } } } @@ -248,8 +248,10 @@ private extension ModifierListSyntax { func replacing(fileprivateModifier: DeclModifierSyntax) -> ModifierListSyntax? { replacing( childAt: fileprivateModifier.indexInParent, - with: fileprivateModifier.withName( - .privateKeyword( + with: fileprivateModifier.with( + \.name, + .keyword( + .private, leadingTrivia: fileprivateModifier.leadingTrivia ?? .zero, trailingTrivia: fileprivateModifier.trailingTrivia ?? .zero ) diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantNilCoalescingRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantNilCoalescingRule.swift index 5b92c4efd4..a14bb3bab2 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantNilCoalescingRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantNilCoalescingRule.swift @@ -38,7 +38,7 @@ struct RedundantNilCoalescingRule: OptInRule, SwiftSyntaxCorrectableRule, Config private extension RedundantNilCoalescingRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: TokenSyntax) { - if node.tokenKind.isNilCoalescingOperator && node.nextToken?.tokenKind == .nilKeyword { + if node.tokenKind.isNilCoalescingOperator && node.nextToken?.tokenKind == .keyword(.nil) { violations.append(node.position) } } @@ -66,7 +66,7 @@ private extension RedundantNilCoalescingRule { return super.visit(node) } - let newNode = node.removingLast().removingLast().withoutTrailingTrivia() + let newNode = node.removingLast().removingLast().with(\.trailingTrivia, []) correctionPositions.append(newNode.endPosition) return super.visit(newNode) } @@ -75,6 +75,6 @@ private extension RedundantNilCoalescingRule { private extension TokenKind { var isNilCoalescingOperator: Bool { - self == .spacedBinaryOperator("??") || self == .unspacedBinaryOperator("??") + self == .binaryOperator("??") } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantObjcAttributeRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantObjcAttributeRule.swift index edc2a4470b..d9b9ac049e 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantObjcAttributeRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantObjcAttributeRule.swift @@ -42,22 +42,15 @@ struct RedundantObjcAttributeRule: SwiftSyntaxRule, SubstitutionCorrectableRule, } private extension AttributeListSyntax { - var hasObjCMembers: Bool { - contains { $0.as(AttributeSyntax.self)?.attributeName.tokenKind == .identifier("objcMembers") } - } - var objCAttribute: AttributeSyntax? { lazy .compactMap { $0.as(AttributeSyntax.self) } - .first { attribute in - attribute.attributeName.tokenKind == .contextualKeyword("objc") && - attribute.argument == nil - } + .first { $0.attributeNameText == "objc" && $0.argument == nil } } var hasAttributeImplyingObjC: Bool { contains { element in - guard case let .identifier(attributeName) = element.as(AttributeSyntax.self)?.attributeName.tokenKind else { + guard let attributeName = element.as(AttributeSyntax.self)?.attributeNameText else { return false } @@ -89,7 +82,7 @@ private extension AttributeListSyntax { return objcAttribute } else if parent?.isFunctionOrStoredProperty == true, let parentClassDecl = parent?.parent?.parent?.parent?.parent?.as(ClassDeclSyntax.self), - parentClassDecl.attributes?.hasObjCMembers == true { + parentClassDecl.attributes.contains(attributeNamed: "objcMembers") { return objcAttribute } else if let parentExtensionDecl = parent?.parent?.parent?.parent?.parent?.as(ExtensionDeclSyntax.self), parentExtensionDecl.attributes?.objCAttribute != nil { diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantOptionalInitializationRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantOptionalInitializationRule.swift index eadaaee343..b6f713f0ba 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantOptionalInitializationRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantOptionalInitializationRule.swift @@ -121,7 +121,7 @@ struct RedundantOptionalInitializationRule: SwiftSyntaxCorrectableRule, Configur private extension RedundantOptionalInitializationRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: VariableDeclSyntax) { - guard node.letOrVarKeyword.tokenKind == .varKeyword, + guard node.letOrVarKeyword.tokenKind == .keyword(.var), !node.modifiers.containsLazy else { return } @@ -141,7 +141,7 @@ private extension RedundantOptionalInitializationRule { } override func visit(_ node: VariableDeclSyntax) -> DeclSyntax { - guard node.letOrVarKeyword.tokenKind == .varKeyword, + guard node.letOrVarKeyword.tokenKind == .keyword(.var), !node.modifiers.containsLazy else { return super.visit(node) } @@ -166,16 +166,16 @@ private extension RedundantOptionalInitializationRule { return binding } - let newBinding = binding.withInitializer(nil) + let newBinding = binding.with(\.initializer, nil) if newBinding.accessor == nil { - return newBinding.withTrailingTrivia(binding.initializer?.trailingTrivia ?? .zero) + return newBinding.with(\.trailingTrivia, binding.initializer?.trailingTrivia ?? .zero) } else { return newBinding } }) - return super.visit(node.withBindings(newBindings)) + return super.visit(node.with(\.bindings, newBindings)) } } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantSetAccessControlRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantSetAccessControlRule.swift index 7477566e1c..28854b3efd 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/RedundantSetAccessControlRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/RedundantSetAccessControlRule.swift @@ -82,11 +82,11 @@ private extension RedundantSetAccessControlRule { return } - if setAccessor.name.tokenKind == .fileprivateKeyword, + if setAccessor.name.tokenKind == .keyword(.fileprivate), modifiers.getAccessor == nil, let closestDeclModifiers = node.closestDecl()?.modifiers { let closestDeclIsFilePrivate = closestDeclModifiers.contains { - $0.name.tokenKind == .fileprivateKeyword + $0.name.tokenKind == .keyword(.fileprivate) } if closestDeclIsFilePrivate { @@ -95,12 +95,12 @@ private extension RedundantSetAccessControlRule { } } - if setAccessor.name.tokenKind == .internalKeyword, + if setAccessor.name.tokenKind == .keyword(.internal), modifiers.getAccessor == nil, let closesDecl = node.closestDecl(), let closestDeclModifiers = closesDecl.modifiers { let closestDeclIsInternal = closestDeclModifiers.isEmpty || closestDeclModifiers.contains { - $0.name.tokenKind == .internalKeyword + $0.name.tokenKind == .keyword(.internal) } if closestDeclIsInternal { @@ -144,7 +144,7 @@ private extension DeclSyntax { private extension ModifierListSyntax { var setAccessor: DeclModifierSyntax? { - first { $0.detail?.detail.tokenKind == .contextualKeyword("set") } + first { $0.detail?.detail.tokenKind == .keyword(.set) } } var getAccessor: DeclModifierSyntax? { diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ShorthandOptionalBindingRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ShorthandOptionalBindingRule.swift index 35a5aef4e9..862be34421 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ShorthandOptionalBindingRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ShorthandOptionalBindingRule.swift @@ -121,8 +121,8 @@ private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) let newNode = node - .withInitializer(nil) - .withPattern(node.pattern.withTrailingTrivia(node.trailingTrivia ?? .zero)) + .with(\.initializer, nil) + .with(\.pattern, node.pattern.with(\.trailingTrivia, node.trailingTrivia ?? .zero)) return super.visit(newNode) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/StaticOperatorRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/StaticOperatorRule.swift index 429a21b89e..1e5cc7044e 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/StaticOperatorRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/StaticOperatorRule.swift @@ -102,7 +102,7 @@ private extension FunctionDeclSyntax { var isOperator: Bool { switch identifier.tokenKind { - case .spacedBinaryOperator: + case .binaryOperator: return true default: return false diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/StrictFilePrivateRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/StrictFilePrivateRule.swift index 91aa918099..fe4b25f7f4 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/StrictFilePrivateRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/StrictFilePrivateRule.swift @@ -11,7 +11,10 @@ struct StrictFilePrivateRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxR description: "`fileprivate` should be avoided", kind: .idiomatic, nonTriggeringExamples: [ + Example("extension String {}"), + Example("private extension String {}"), Example(""" + public extension String { var i: Int { 1 } } @@ -180,7 +183,7 @@ private extension StrictFilePrivateRule { }() override func visitPost(_ node: DeclModifierSyntax) { - guard node.name.tokenKind == .fileprivateKeyword, let grandparent = node.parent?.parent else { + guard node.name.tokenKind == .keyword(.fileprivate), let grandparent = node.parent?.parent else { return } guard grandparent.is(FunctionDeclSyntax.self) || grandparent.is(VariableDeclSyntax.self) else { @@ -193,7 +196,7 @@ private extension StrictFilePrivateRule { return } if let varDecl = grandparent.as(VariableDeclSyntax.self) { - let isSpecificForSetter = node.detail?.detail.tokenKind == .contextualKeyword("set") + let isSpecificForSetter = node.detail?.detail.tokenKind == .keyword(.set) let firstImplementingProtocol = varDecl.bindings .flatMap { binding in let pattern = binding.pattern diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/SyntacticSugarRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/SyntacticSugarRule.swift index 4e6688f92f..f5b71f9859 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/SyntacticSugarRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/SyntacticSugarRule.swift @@ -166,11 +166,11 @@ private final class SyntacticSugarRuleVisitor: SyntaxVisitor { // Skip checks for 'self' or \T Dictionary.self if let parent = node.parent?.as(MemberAccessExprSyntax.self), let lastToken = Array(parent.tokens(viewMode: .sourceAccurate)).last?.tokenKind, - [.selfKeyword, .identifier("Type"), .identifier("none"), .identifier("Index")].contains(lastToken) { + [.keyword(.self), .identifier("Type"), .identifier("none"), .identifier("Index")].contains(lastToken) { return } - let typeName = node.expression.withoutTrivia().description + let typeName = node.expression.trimmedDescription if SugaredType(typeName: typeName) != nil { if let violation = violation(from: node) { diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift index 22e26653a1..0b648bc2c8 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ToggleBoolRule.swift @@ -73,11 +73,14 @@ private extension ToggleBoolRule { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) let newNode = node - .replacing(childAt: 0, with: "\(node.first!.withoutTrivia()).toggle()") + .replacing( + childAt: 0, + with: "\(node.first!.trimmed).toggle()" + ) .removingLast() .removingLast() - .withLeadingTrivia(node.leadingTrivia ?? .zero) - .withTrailingTrivia(node.trailingTrivia ?? .zero) + .with(\.leadingTrivia, node.leadingTrivia ?? .zero) + .with(\.trailingTrivia, node.trailingTrivia ?? .zero) return super.visit(newNode) } @@ -90,8 +93,8 @@ private extension ExprListSyntax { count == 3, dropFirst().first?.is(AssignmentExprSyntax.self) == true, last?.is(PrefixOperatorExprSyntax.self) == true, - let lhs = first?.withoutTrivia().description, - let rhs = last?.withoutTrivia().description, + let lhs = first?.trimmedDescription, + let rhs = last?.trimmedDescription, rhs == "!\(lhs)" else { return false diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableConditionRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableConditionRule.swift index f62f39b367..dd22961b23 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableConditionRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableConditionRule.swift @@ -77,8 +77,8 @@ struct UnavailableConditionRule: ConfigurationProviderRule, SwiftSyntaxRule { } private final class UnavailableConditionRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: IfStmtSyntax) { - guard node.body.statements.withoutTrivia().isEmpty else { + override func visitPost(_ node: IfExprSyntax) { + guard node.body.statements.isEmpty else { return } @@ -101,13 +101,13 @@ private final class UnavailableConditionRuleVisitor: ViolationsSyntaxVisitor { ) } - private func asAvailabilityCondition(_ condition: ConditionElementSyntax.Condition) -> SyntaxProtocol? { - condition.as(AvailabilityConditionSyntax.self) ?? - condition.as(UnavailabilityConditionSyntax.self) + private func asAvailabilityCondition(_ condition: ConditionElementSyntax.Condition) + -> AvailabilityConditionSyntax? { + condition.as(AvailabilityConditionSyntax.self) } - private func otherAvailabilityCheckInvolved(ifStmt: IfStmtSyntax) -> Bool { - if let elseBody = ifStmt.elseBody, let nestedIfStatement = elseBody.as(IfStmtSyntax.self) { + private func otherAvailabilityCheckInvolved(ifStmt: IfExprSyntax) -> Bool { + if let elseBody = ifStmt.elseBody, let nestedIfStatement = elseBody.as(IfExprSyntax.self) { if nestedIfStatement.conditions.map(\.condition).compactMap(asAvailabilityCondition).isNotEmpty { return true } @@ -116,11 +116,11 @@ private final class UnavailableConditionRuleVisitor: ViolationsSyntaxVisitor { return false } - private func reason(for check: SyntaxProtocol) -> String { - switch check { - case is AvailabilityConditionSyntax: + private func reason(for condition: AvailabilityConditionSyntax) -> String { + switch condition.availabilityKeyword.tokenKind { + case .poundAvailableKeyword: return "Use #unavailable instead of #available with an empty body" - case is UnavailabilityConditionSyntax: + case .poundUnavailableKeyword: return "Use #available instead of #unavailable with an empty body" default: queuedFatalError("Unknown availability check type.") diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableFunctionRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableFunctionRule.swift index a2d86402f1..5a9fce4abd 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableFunctionRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/UnavailableFunctionRule.swift @@ -105,7 +105,7 @@ private extension UnavailableFunctionRule { private extension FunctionDeclSyntax { var returnsNever: Bool { if let expr = signature.output?.returnType.as(SimpleTypeIdentifierSyntax.self) { - return expr.name.withoutTrivia().text == "Never" + return expr.name.text == "Never" } return false } @@ -123,8 +123,9 @@ private extension AttributeListSyntax? { return false } - return attr.attributeName.tokenKind == .contextualKeyword("available") && arguments.contains { arg in - arg.entry.as(TokenSyntax.self)?.tokenKind == .contextualKeyword("unavailable") + let attributeName = attr.attributeNameText + return attributeName == "available" && arguments.contains { arg in + arg.entry.as(TokenSyntax.self)?.tokenKind.isUnavailableKeyword == true } } } @@ -148,7 +149,7 @@ private extension CodeBlockSyntax? { return false } - return terminatingFunctions.contains(identifierExpr.identifier.withoutTrivia().text) + return terminatingFunctions.contains(identifierExpr.identifier.text) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/UntypedErrorInCatchRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/UntypedErrorInCatchRule.swift index b2b87d5c7f..4d531ff90d 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/UntypedErrorInCatchRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/UntypedErrorInCatchRule.swift @@ -154,8 +154,8 @@ private final class UntypedErrorInCatchRuleRewriter: SyntaxRewriter, ViolationsS correctionPositions.append(node.catchKeyword.positionAfterSkippingLeadingTrivia) return super.visit( node - .withCatchKeyword(node.catchKeyword.withTrailingTrivia(.spaces(1))) - .withCatchItems(CatchItemListSyntax([])) + .with(\.catchKeyword, node.catchKeyword.with(\.trailingTrivia, .spaces(1))) + .with(\.catchItems, CatchItemListSyntax([])) ) } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift index 0a95728e14..6f51ece540 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift @@ -68,7 +68,7 @@ private extension FunctionCallExprSyntax { var isEnumerated: Bool { guard let memberAccess = calledExpression.as(MemberAccessExprSyntax.self), memberAccess.base != nil, - memberAccess.name.withoutTrivia().text == "enumerated", + memberAccess.name.text == "enumerated", hasNoArguments else { return false } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/XCTSpecificMatcherRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/XCTSpecificMatcherRule.swift index daa4178787..3e5b20e48b 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/XCTSpecificMatcherRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/XCTSpecificMatcherRule.swift @@ -44,7 +44,7 @@ private extension XCTSpecificMatcherRule { */ let arguments = node.argumentList .prefix(2) - .map { $0.expression.withoutTrivia().description } + .map { $0.expression.trimmedDescription } .sorted { arg1, _ -> Bool in return Self.protectedArguments.contains(arg1) } diff --git a/Source/SwiftLintFramework/Rules/Lint/AnyObjectProtocolRule.swift b/Source/SwiftLintFramework/Rules/Lint/AnyObjectProtocolRule.swift index 792afd04da..bc7590fdd2 100644 --- a/Source/SwiftLintFramework/Rules/Lint/AnyObjectProtocolRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/AnyObjectProtocolRule.swift @@ -83,11 +83,12 @@ private extension AnyObjectProtocolRule { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) return super.visit( - node.withTypeName( + node.with( + \.typeName, TypeSyntax( SimpleTypeIdentifierSyntax(name: .identifier("AnyObject"), genericArgumentClause: nil) - .withLeadingTrivia(typeName.leadingTrivia ?? .zero) - .withTrailingTrivia(typeName.trailingTrivia ?? .zero) + .with(\.leadingTrivia, typeName.leadingTrivia ?? .zero) + .with(\.trailingTrivia, typeName.trailingTrivia ?? .zero) ) ) ) diff --git a/Source/SwiftLintFramework/Rules/Lint/ClassDelegateProtocolRule.swift b/Source/SwiftLintFramework/Rules/Lint/ClassDelegateProtocolRule.swift index 02b5dc2cd3..64e2f3fa78 100644 --- a/Source/SwiftLintFramework/Rules/Lint/ClassDelegateProtocolRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/ClassDelegateProtocolRule.swift @@ -55,7 +55,7 @@ private extension ClassDelegateProtocolRule { private extension ProtocolDeclSyntax { func hasObjCAttribute() -> Bool { - attributes?.contains { $0.as(AttributeSyntax.self)?.attributeName.text == "objc" } == true + attributes.contains(attributeNamed: "objc") } func isClassRestricted() -> Bool { diff --git a/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift b/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift index 3c30d58bea..153e7c5791 100644 --- a/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift @@ -83,36 +83,28 @@ private extension DeploymentTargetRule { } } - override func visitPost(_ node: UnavailabilityConditionSyntax) { - for elem in node.availabilitySpec { - guard let restriction = elem.entry.as(AvailabilityVersionRestrictionSyntax.self), - let versionString = restriction.version?.description, - let reason = reason(platform: restriction.platform, version: versionString, - violationType: .negativeCondition) else { - continue - } - - violations.append( - ReasonedRuleViolation( - position: node.poundUnavailableKeyword.positionAfterSkippingLeadingTrivia, - reason: reason - ) - ) + override func visitPost(_ node: AvailabilityConditionSyntax) { + let violationType: AvailabilityType + switch node.availabilityKeyword.tokenKind { + case .poundUnavailableKeyword: + violationType = .negativeCondition + case .poundAvailableKeyword: + violationType = .condition + default: + queuedFatalError("Unknown availability check type.") } - } - override func visitPost(_ node: AvailabilityConditionSyntax) { for elem in node.availabilitySpec { guard let restriction = elem.entry.as(AvailabilityVersionRestrictionSyntax.self), let versionString = restriction.version?.description, let reason = reason(platform: restriction.platform, version: versionString, - violationType: .condition) else { + violationType: violationType) else { continue } violations.append( ReasonedRuleViolation( - position: node.poundAvailableKeyword.positionAfterSkippingLeadingTrivia, + position: node.availabilityKeyword.positionAfterSkippingLeadingTrivia, reason: reason ) ) diff --git a/Source/SwiftLintFramework/Rules/Lint/DiscardedNotificationCenterObserverRule.swift b/Source/SwiftLintFramework/Rules/Lint/DiscardedNotificationCenterObserverRule.swift index da96243254..1553ce11a0 100644 --- a/Source/SwiftLintFramework/Rules/Lint/DiscardedNotificationCenterObserverRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/DiscardedNotificationCenterObserverRule.swift @@ -73,7 +73,7 @@ private extension DiscardedNotificationCenterObserverRule { let thirdParent = secondParent.parent?.as(CodeBlockItemListSyntax.self), let fourthParent = thirdParent.parent?.as(CodeBlockSyntax.self), let fifthParent = fourthParent.parent?.as(FunctionDeclSyntax.self), - fifthParent.attributes?.hasDiscardableResultAttribute != true + !fifthParent.attributes.hasDiscardableResultAttribute { return // result is returned from a function } else if node.parent?.is(TupleExprElementSyntax.self) == true { @@ -83,7 +83,7 @@ private extension DiscardedNotificationCenterObserverRule { } else if let previousToken = node.previousToken, case .equal = previousToken.tokenKind, - previousToken.previousToken?.tokenKind != .wildcardKeyword + previousToken.previousToken?.tokenKind != .wildcard { return // result is assigned to something other than the wildcard keyword (`_`) } @@ -93,8 +93,8 @@ private extension DiscardedNotificationCenterObserverRule { } } -private extension AttributeListSyntax { +private extension AttributeListSyntax? { var hasDiscardableResultAttribute: Bool { - contains { $0.as(AttributeSyntax.self)?.attributeName.tokenKind == .identifier("discardableResult") } == true + contains(attributeNamed: "discardableResult") } } diff --git a/Source/SwiftLintFramework/Rules/Lint/DiscouragedDirectInitRule.swift b/Source/SwiftLintFramework/Rules/Lint/DiscouragedDirectInitRule.swift index e85f120bec..dad553fcb4 100644 --- a/Source/SwiftLintFramework/Rules/Lint/DiscouragedDirectInitRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/DiscouragedDirectInitRule.swift @@ -53,7 +53,7 @@ private extension DiscouragedDirectInitRule { override func visitPost(_ node: FunctionCallExprSyntax) { guard node.argumentList.isEmpty, node.trailingClosure == nil, - discouragedInits.contains(node.calledExpression.withoutTrivia().description) else { + discouragedInits.contains(node.calledExpression.trimmedDescription) else { return } diff --git a/Source/SwiftLintFramework/Rules/Lint/DynamicInlineRule.swift b/Source/SwiftLintFramework/Rules/Lint/DynamicInlineRule.swift index 4316a07f2b..87a98919a3 100644 --- a/Source/SwiftLintFramework/Rules/Lint/DynamicInlineRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/DynamicInlineRule.swift @@ -47,7 +47,7 @@ private extension DynamicInlineRule { private extension AttributeSyntax { var isInlineAlways: Bool { - attributeName.text == "inline" && + attributeNameText == "inline" && argument?.firstToken?.tokenKind == .identifier("__always") } } diff --git a/Source/SwiftLintFramework/Rules/Lint/IBInspectableInExtensionRule.swift b/Source/SwiftLintFramework/Rules/Lint/IBInspectableInExtensionRule.swift index 724afa7786..9ecd37c29b 100644 --- a/Source/SwiftLintFramework/Rules/Lint/IBInspectableInExtensionRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/IBInspectableInExtensionRule.swift @@ -38,7 +38,7 @@ private extension IBInspectableInExtensionRule { } override func visitPost(_ node: AttributeSyntax) { - if node.attributeName.text == "IBInspectable" { + if node.attributeNameText == "IBInspectable" { violations.append(node.positionAfterSkippingLeadingTrivia) } } diff --git a/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift b/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift index d86afafdca..056a185cbe 100644 --- a/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift @@ -85,7 +85,7 @@ private extension IdenticalOperandsRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: InfixOperatorExprSyntax) { guard let operatorNode = node.operatorOperand.as(BinaryOperatorExprSyntax.self), - IdenticalOperandsRule.operators.contains(operatorNode.operatorToken.withoutTrivia().text) else { + IdenticalOperandsRule.operators.contains(operatorNode.operatorToken.text) else { return } diff --git a/Source/SwiftLintFramework/Rules/Lint/LowerACLThanParentRule.swift b/Source/SwiftLintFramework/Rules/Lint/LowerACLThanParentRule.swift index 2700b42736..168cf3b2e9 100644 --- a/Source/SwiftLintFramework/Rules/Lint/LowerACLThanParentRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/LowerACLThanParentRule.swift @@ -112,18 +112,17 @@ private extension LowerACLThanParentRule { } correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - let keyword: String - let trailingTrivia: Trivia - if node.name.tokenKind == .contextualKeyword("open") { - keyword = "public" - trailingTrivia = .space + let newNode: DeclModifierSyntax + if node.name.tokenKind == .keyword(.open) { + newNode = DeclModifierSyntax( + leadingTrivia: node.leadingTrivia ?? .zero, + name: .keyword(.public), + trailingTrivia: .space + ) } else { - keyword = "" - trailingTrivia = .zero + newNode = DeclModifierSyntax(name: .keyword(.internal, presence: .missing)) } - let newNode = node.withName( - .contextualKeyword(keyword, leadingTrivia: node.leadingTrivia ?? .zero, trailingTrivia: trailingTrivia) - ) + return super.visit(newNode) } } @@ -136,29 +135,29 @@ private extension DeclModifierSyntax { } switch name.tokenKind { - case .internalKeyword + case .keyword(.internal) where nearestNominalParent.modifiers.isPrivate || nearestNominalParent.modifiers.isFileprivate: return true - case .internalKeyword + case .keyword(.internal) where !nearestNominalParent.modifiers.containsACLModifier: guard let nominalExtension = nearestNominalParent.nearestNominalExtensionDeclParent() else { return false } return nominalExtension.modifiers.isPrivate || nominalExtension.modifiers.isFileprivate - case .publicKeyword + case .keyword(.public) where nearestNominalParent.modifiers.isPrivate || nearestNominalParent.modifiers.isFileprivate || nearestNominalParent.modifiers.isInternal: return true - case .publicKeyword + case .keyword(.public) where !nearestNominalParent.modifiers.containsACLModifier: guard let nominalExtension = nearestNominalParent.nearestNominalExtensionDeclParent() else { return true } return !nominalExtension.modifiers.isPublic - case .contextualKeyword("open") where !nearestNominalParent.modifiers.isOpen: + case .keyword(.open) where !nearestNominalParent.modifiers.isOpen: return true default: return false @@ -215,32 +214,33 @@ private extension Syntax { private extension ModifierListSyntax? { var isPrivate: Bool { - self?.contains(where: { $0.name.tokenKind == .privateKeyword }) == true + self?.contains(where: { $0.name.tokenKind == .keyword(.private) }) == true } var isInternal: Bool { - self?.contains(where: { $0.name.tokenKind == .internalKeyword }) == true + self?.contains(where: { $0.name.tokenKind == .keyword(.internal) }) == true } var isPublic: Bool { - self?.contains(where: { $0.name.tokenKind == .publicKeyword }) == true + self?.contains(where: { $0.name.tokenKind == .keyword(.public) }) == true } var isOpen: Bool { - self?.contains(where: { $0.name.tokenKind == .contextualKeyword("open") }) == true + self?.contains(where: { $0.name.tokenKind == .keyword(.open) }) == true } var containsACLModifier: Bool { guard self?.isEmpty == false else { return false } - let aclTokens: [TokenKind] = [ - .fileprivateKeyword, - .privateKeyword, - .internalKeyword, - .publicKeyword, - .contextualKeyword("open") + let aclTokens: Set = [ + .keyword(.private), + .keyword(.fileprivate), + .keyword(.internal), + .keyword(.public), + .keyword(.open) ] + return self?.contains(where: { aclTokens.contains($0.name.tokenKind) }) == true diff --git a/Source/SwiftLintFramework/Rules/Lint/NSObjectPreferIsEqualRule.swift b/Source/SwiftLintFramework/Rules/Lint/NSObjectPreferIsEqualRule.swift index e4aaacbf50..d944323d53 100644 --- a/Source/SwiftLintFramework/Rules/Lint/NSObjectPreferIsEqualRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/NSObjectPreferIsEqualRule.swift @@ -33,7 +33,7 @@ private extension NSObjectPreferIsEqualRule { private extension ClassDeclSyntax { var isObjC: Bool { - if attributes?.isObjc == true { + if attributes.isObjc { return true } @@ -58,8 +58,8 @@ private extension FunctionDeclSyntax { let rhs = parameterList.last, lhs.firstName?.text == "lhs", rhs.firstName?.text == "rhs", - let lhsTypeDescription = lhs.type?.withoutTrivia().description, - let rhsTypeDescription = rhs.type?.withoutTrivia().description, + let lhsTypeDescription = lhs.type?.trimmedDescription, + let rhsTypeDescription = rhs.type?.trimmedDescription, lhsTypeDescription == rhsTypeDescription else { return false @@ -85,8 +85,8 @@ private extension SyntaxProtocol { } } -private extension AttributeListSyntax { +private extension AttributeListSyntax? { var isObjc: Bool { - contains { ["objc", "objcMembers"].contains($0.as(AttributeSyntax.self)?.attributeName.text) } + contains(attributeNamed: "objc") || contains(attributeNamed: "objcMembers") } } diff --git a/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift b/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift index 7150d182b8..44ac1f6621 100644 --- a/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift @@ -26,7 +26,7 @@ private extension NotificationCenterDetachmentRule { let arg = node.argumentList.first, arg.label == nil, let expr = arg.expression.as(IdentifierExprSyntax.self), - expr.identifier.tokenKind == .selfKeyword else { + expr.identifier.tokenKind == .keyword(.self) else { return } diff --git a/Source/SwiftLintFramework/Rules/Lint/PrivateOutletRule.swift b/Source/SwiftLintFramework/Rules/Lint/PrivateOutletRule.swift index 0f99c2a107..eb437b5f25 100644 --- a/Source/SwiftLintFramework/Rules/Lint/PrivateOutletRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/PrivateOutletRule.swift @@ -95,7 +95,7 @@ private extension PrivateOutletRule { override func visitPost(_ node: MemberDeclListItemSyntax) { guard let decl = node.decl.as(VariableDeclSyntax.self), - decl.attributes?.hasIBOutlet == true, + decl.attributes.contains(attributeNamed: "IBOutlet"), decl.modifiers?.isPrivateOrFilePrivate != true else { return @@ -110,12 +110,6 @@ private extension PrivateOutletRule { } } -private extension AttributeListSyntax { - var hasIBOutlet: Bool { - contains { $0.as(AttributeSyntax.self)?.attributeName.text == "IBOutlet" } - } -} - private extension ModifierListSyntax { var isPrivateOrFilePrivate: Bool { contains(where: \.isPrivateOrFilePrivate) diff --git a/Source/SwiftLintFramework/Rules/Lint/PrivateUnitTestRule.swift b/Source/SwiftLintFramework/Rules/Lint/PrivateUnitTestRule.swift index 7ea916fd20..7ae33cea17 100644 --- a/Source/SwiftLintFramework/Rules/Lint/PrivateUnitTestRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/PrivateUnitTestRule.swift @@ -201,7 +201,7 @@ private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) let (modifiers, declKeyword) = withoutPrivate(modifiers: node.modifiers, declKeyword: node.classKeyword) - return super.visit(node.withModifiers(modifiers).withClassKeyword(declKeyword)) + return super.visit(node.with(\.modifiers, modifiers).with(\.classKeyword, declKeyword)) } override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax { @@ -215,7 +215,7 @@ private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) let (modifiers, declKeyword) = withoutPrivate(modifiers: node.modifiers, declKeyword: node.funcKeyword) - return super.visit(node.withModifiers(modifiers).withFuncKeyword(declKeyword)) + return super.visit(node.with(\.modifiers, modifiers).with(\.funcKeyword, declKeyword)) } private func withoutPrivate(modifiers: ModifierListSyntax?, @@ -227,14 +227,14 @@ private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { var leadingTrivia = Trivia.zero for modifier in modifiers { let accumulatedLeadingTrivia = leadingTrivia + (modifier.leadingTrivia ?? .zero) - if modifier.name.tokenKind == .privateKeyword { + if modifier.name.tokenKind == .keyword(.private) { leadingTrivia = accumulatedLeadingTrivia } else { - filteredModifiers.append(modifier.withLeadingTrivia(accumulatedLeadingTrivia)) + filteredModifiers.append(modifier.with(\.leadingTrivia, accumulatedLeadingTrivia)) leadingTrivia = .zero } } - let declKeyword = declKeyword.withLeadingTrivia(leadingTrivia + (declKeyword.leadingTrivia ?? .zero)) + let declKeyword = declKeyword.with(\.leadingTrivia, leadingTrivia + (declKeyword.leadingTrivia ?? .zero)) return (ModifierListSyntax(filteredModifiers), declKeyword) } } @@ -269,11 +269,11 @@ private extension FunctionDeclSyntax { private extension ModifierListSyntax { var hasPrivate: Bool { - contains { $0.name.tokenKind == .privateKeyword } + contains { $0.name.tokenKind == .keyword(.private) } } var hasStatic: Bool { - contains { $0.name.tokenKind == .staticKeyword } + contains { $0.name.tokenKind == .keyword(.static) } } } @@ -281,8 +281,6 @@ private func resultInPrivateProperty(modifiers: ModifierListSyntax?, attributes: guard let modifiers, modifiers.hasPrivate else { return false } - guard let attributes else { - return true - } - return !attributes.contains { $0.as(AttributeSyntax.self)?.attributeName.tokenKind == .contextualKeyword("objc") } + + return !attributes.contains(attributeNamed: "objc") } diff --git a/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedFocusedTestRule.swift b/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedFocusedTestRule.swift index 55125768d4..521a628980 100644 --- a/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedFocusedTestRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedFocusedTestRule.swift @@ -25,7 +25,7 @@ private extension QuickDiscouragedFocusedTestRule { override func visitPost(_ node: FunctionCallExprSyntax) { if let identifierExpr = node.calledExpression.as(IdentifierExprSyntax.self), - case let name = identifierExpr.identifier.withoutTrivia().text, + case let name = identifierExpr.identifier.text, QuickFocusedCallKind(rawValue: name) != nil { violations.append(node.positionAfterSkippingLeadingTrivia) } diff --git a/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedPendingTestRule.swift b/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedPendingTestRule.swift index f6591eb72c..bec1e18c66 100644 --- a/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedPendingTestRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/QuickDiscouragedPendingTestRule.swift @@ -25,7 +25,7 @@ private extension QuickDiscouragedPendingTestRule { override func visitPost(_ node: FunctionCallExprSyntax) { if let identifierExpr = node.calledExpression.as(IdentifierExprSyntax.self), - case let name = identifierExpr.identifier.withoutTrivia().text, + case let name = identifierExpr.identifier.text, QuickPendingCallKind(rawValue: name) != nil { violations.append(node.positionAfterSkippingLeadingTrivia) } diff --git a/Source/SwiftLintFramework/Rules/Lint/SelfInPropertyInitializationRule.swift b/Source/SwiftLintFramework/Rules/Lint/SelfInPropertyInitializationRule.swift index b55af881ab..334d3e0f46 100644 --- a/Source/SwiftLintFramework/Rules/Lint/SelfInPropertyInitializationRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/SelfInPropertyInitializationRule.swift @@ -107,7 +107,7 @@ private extension SelfInPropertyInitializationRule { return } - let visitor = IdentifierUsageVisitor(identifier: .selfKeyword) + let visitor = IdentifierUsageVisitor(identifier: .keyword(.self)) for binding in node.bindings { guard let initializer = binding.initializer, visitor.walk(tree: initializer.value, handler: \.isTokenUsed) else { diff --git a/Source/SwiftLintFramework/Rules/Lint/StrongIBOutletRule.swift b/Source/SwiftLintFramework/Rules/Lint/StrongIBOutletRule.swift index f505d53b3e..a15f942967 100644 --- a/Source/SwiftLintFramework/Rules/Lint/StrongIBOutletRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/StrongIBOutletRule.swift @@ -70,7 +70,7 @@ private extension StrongIBOutletRule { } let newModifiers = ModifierListSyntax(modifiers.filter { $0 != weakOrUnownedModifier }) - let newNode = node.withModifiers(newModifiers) + let newNode = node.with(\.modifiers, newModifiers) correctionPositions.append(violationPosition) return super.visit(newNode) } diff --git a/Source/SwiftLintFramework/Rules/Lint/UnownedVariableCaptureRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnownedVariableCaptureRule.swift index 547eab00fa..908e132c4b 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnownedVariableCaptureRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnownedVariableCaptureRule.swift @@ -16,7 +16,16 @@ struct UnownedVariableCaptureRule: SwiftSyntaxRule, OptInRule, ConfigurationProv Example("foo { [weak bar] in _ }"), Example("foo { [weak bar] param in _ }"), Example("foo { bar in _ }"), - Example("foo { $0 }") + Example("foo { $0 }"), + Example(""" + final class First {} + final class Second { + unowned var value: First + init(value: First) { + self.value = value + } + } + """) ], triggeringExamples: [ Example("foo { [↓unowned self] in _ }"), @@ -31,23 +40,9 @@ struct UnownedVariableCaptureRule: SwiftSyntaxRule, OptInRule, ConfigurationProv } private final class UnownedVariableCaptureRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: ClosureCaptureItemSyntax) { - if let token = node.unownedToken { - violations.append(token.positionAfterSkippingLeadingTrivia) - } - } - - override func visitPost(_ node: TokenListSyntax) { - if case .contextualKeyword("unowned") = node.first?.tokenKind { + override func visitPost(_ node: TokenSyntax) { + if case .keyword(.unowned) = node.tokenKind, node.parent?.is(ClosureCaptureItemSpecifierSyntax.self) == true { violations.append(node.positionAfterSkippingLeadingTrivia) } } } - -private extension ClosureCaptureItemSyntax { - var unownedToken: TokenSyntax? { - specifier?.first { token in - token.tokenKind == .identifier("unowned") - } - } -} diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift index ec9045c2c2..335528756a 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift @@ -142,7 +142,7 @@ private extension UnusedCaptureListRule { final class Visitor: ViolationsSyntaxVisitor { override func visitPost(_ node: ClosureExprSyntax) { guard let captureItems = node.signature?.capture?.items, - captureItems.isNotEmpty else { + captureItems.isNotEmpty else { return } @@ -152,12 +152,14 @@ private extension UnusedCaptureListRule { return (name.text, item) } else if let expr = item.expression.as(IdentifierExprSyntax.self) { // allow "[unowned self]" - if expr.identifier.tokenKind == .selfKeyword && item.specifier.containsUnowned { + if expr.identifier.tokenKind == .keyword(.self), + item.specifier?.specifier.tokenKind == .keyword(.unowned) { return nil } // allow "[self]" capture (SE-0269) - if expr.identifier.tokenKind == .selfKeyword && item.specifier.isNilOrEmpty { + if expr.identifier.tokenKind == .keyword(.self), + item.specifier == nil { return nil } @@ -203,15 +205,3 @@ private final class IdentifierReferenceVisitor: SyntaxVisitor { } } } - -private extension TokenListSyntax? { - var containsUnowned: Bool { - self?.contains { token in - token.tokenKind == .contextualKeyword("unowned") - } ?? false - } - - var isNilOrEmpty: Bool { - self?.isEmpty ?? true - } -} diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift index 1604828206..8923c7e28b 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift @@ -79,27 +79,26 @@ private extension UnusedClosureParameterRule { continue } - if name.tokenKind == .wildcardKeyword { + if name.tokenKind == .wildcard { continue } else if referencedIdentifiers.contains(name.text.removingDollarsAndBackticks) { continue } correctionPositions.append(name.positionAfterSkippingLeadingTrivia) - newParams = newParams.withParameterList( - newParams.parameterList.replacing( - childAt: index, - with: param.withFirstName(name.withKind(.wildcardKeyword)) - ) + let newParameterList = newParams.parameterList.replacing( + childAt: index, + with: param.with(\.firstName, name.withKind(.wildcard)) ) + newParams = newParams.with(\.parameterList, newParameterList) } - let newNode = node.withSignature(signature.withInput(.init(newParams))) + let newNode = node.with(\.signature, signature.with(\.input, .init(newParams))) return super.visit(newNode) } var newParams = params for (index, param) in params.enumerated() { - if param.name.tokenKind == .wildcardKeyword { + if param.name.tokenKind == .wildcard { continue } else if referencedIdentifiers.contains(param.name.text.removingDollarsAndBackticks) { continue @@ -108,10 +107,10 @@ private extension UnusedClosureParameterRule { correctionPositions.append(param.name.positionAfterSkippingLeadingTrivia) newParams = newParams.replacing( childAt: index, - with: param.withName(param.name.withKind(.wildcardKeyword)) + with: param.with(\.name, param.name.withKind(.wildcard)) ) } - let newNode = node.withSignature(signature.withInput(.init(newParams))) + let newNode = node.with(\.signature, signature.with(\.input, .init(newParams))) return super.visit(newNode) } } @@ -141,7 +140,7 @@ private extension ClosureExprSyntax { var namedParameters: [ClosureParam] { if let params = signature?.input?.as(ClosureParamListSyntax.self) { return params.compactMap { param in - if param.name.tokenKind == .wildcardKeyword { + if param.name.tokenKind == .wildcard { return nil } return ClosureParam( @@ -151,7 +150,7 @@ private extension ClosureExprSyntax { } } else if let params = signature?.input?.as(ParameterClauseSyntax.self)?.parameterList { return params.compactMap { param in - if param.firstName?.tokenKind == .wildcardKeyword { + if param.firstName?.tokenKind == .wildcard { return nil } return param.firstName.map { name in diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift index afb865e1ca..10bb4b54d6 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift @@ -122,7 +122,7 @@ private extension UnusedControlFlowLabelRule { return super.visit(node) } - let newNode = node.statement.withLeadingTrivia(node.leadingTrivia ?? .zero) + let newNode = node.statement.with(\.leadingTrivia, node.leadingTrivia ?? .zero) correctionPositions.append(violationPosition) return visit(newNode).as(StmtSyntax.self) ?? newNode } @@ -133,7 +133,7 @@ private extension LabeledStmtSyntax { var violationPosition: AbsolutePosition? { let visitor = BreakAndContinueLabelCollector(viewMode: .sourceAccurate) let labels = visitor.walk(tree: self, handler: \.labels) - guard !labels.contains(labelName.withoutTrivia().text) else { + guard !labels.contains(labelName.text) else { return nil } @@ -145,13 +145,13 @@ private class BreakAndContinueLabelCollector: SyntaxVisitor { private(set) var labels: Set = [] override func visitPost(_ node: BreakStmtSyntax) { - if let label = node.label?.withoutTrivia().text { + if let label = node.label?.text { labels.insert(label) } } override func visitPost(_ node: ContinueStmtSyntax) { - if let label = node.label?.withoutTrivia().text { + if let label = node.label?.text { labels.insert(label) } } diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift index cb82697941..148497f0ac 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift @@ -139,11 +139,11 @@ private extension UnusedSetterValueRule { override var skippableDeclarations: [DeclSyntaxProtocol.Type] { [ProtocolDeclSyntax.self] } override func visitPost(_ node: AccessorDeclSyntax) { - guard node.accessorKind.tokenKind == .contextualKeyword("set") else { + guard node.accessorKind.tokenKind == .keyword(.set) else { return } - let variableName = node.parameter?.name.withoutTrivia().text ?? "newValue" + let variableName = node.parameter?.name.text ?? "newValue" let visitor = NewValueUsageVisitor(variableName: variableName) if !visitor.walk(tree: node, handler: \.isVariableUsed) { if (Syntax(node).closestVariableOrSubscript()?.modifiers).containsOverride, @@ -166,7 +166,7 @@ private extension UnusedSetterValueRule { } override func visitPost(_ node: IdentifierExprSyntax) { - if node.identifier.withoutTrivia().text == variableName { + if node.identifier.text == variableName { isVariableUsed = true } } diff --git a/Source/SwiftLintFramework/Rules/Lint/ValidIBInspectableRule.swift b/Source/SwiftLintFramework/Rules/Lint/ValidIBInspectableRule.swift index 9d1b884b7d..3d24f196fa 100644 --- a/Source/SwiftLintFramework/Rules/Lint/ValidIBInspectableRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/ValidIBInspectableRule.swift @@ -170,9 +170,7 @@ private extension ValidIBInspectableRule { private extension VariableDeclSyntax { var isIBInspectable: Bool { - attributes?.contains { attr in - attr.as(AttributeSyntax.self)?.attributeName.text == "IBInspectable" - } ?? false + attributes.contains(attributeNamed: "IBInspectable") } var hasViolation: Bool { @@ -180,7 +178,7 @@ private extension VariableDeclSyntax { } var isReadOnlyProperty: Bool { - if letOrVarKeyword.tokenKind == .letKeyword { + if letOrVarKeyword.tokenKind == .keyword(.let) { return true } @@ -212,7 +210,7 @@ private extension VariableDeclSyntax { return false } - return ValidIBInspectableRule.supportedTypes.contains(type.type.withoutTrivia().description) + return ValidIBInspectableRule.supportedTypes.contains(type.type.trimmedDescription) } } } diff --git a/Source/SwiftLintFramework/Rules/Lint/WeakDelegateRule.swift b/Source/SwiftLintFramework/Rules/Lint/WeakDelegateRule.swift index e67998ecbc..3e50e20067 100644 --- a/Source/SwiftLintFramework/Rules/Lint/WeakDelegateRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/WeakDelegateRule.swift @@ -114,7 +114,7 @@ private extension VariableDeclSyntax { return false } - return pattern.identifier.withoutTrivia().text.lowercased().hasSuffix("delegate") + return pattern.identifier.text.lowercased().hasSuffix("delegate") } } @@ -142,12 +142,12 @@ private extension VariableDeclSyntax { ] return attributes?.contains { attr in - guard let customAttr = attr.as(CustomAttributeSyntax.self), + guard case let .attribute(customAttr) = attr, let typeIdentifier = customAttr.attributeName.as(SimpleTypeIdentifierSyntax.self) else { return false } - return ignoredAttributes.contains(typeIdentifier.name.withoutTrivia().text) + return ignoredAttributes.contains(typeIdentifier.name.text) } ?? false } } diff --git a/Source/SwiftLintFramework/Rules/Lint/YodaConditionRule.swift b/Source/SwiftLintFramework/Rules/Lint/YodaConditionRule.swift index 39a3c04759..b39d69918b 100644 --- a/Source/SwiftLintFramework/Rules/Lint/YodaConditionRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/YodaConditionRule.swift @@ -42,7 +42,7 @@ struct YodaConditionRule: OptInRule, ConfigurationProviderRule, SwiftSyntaxRule } private final class YodaConditionRuleVisitor: ViolationsSyntaxVisitor { - override func visitPost(_ node: IfStmtSyntax) { + override func visitPost(_ node: IfExprSyntax) { visit(conditions: node.conditions) } diff --git a/Source/SwiftLintFramework/Rules/Metrics/EnumCaseAssociatedValuesLengthRule.swift b/Source/SwiftLintFramework/Rules/Metrics/EnumCaseAssociatedValuesLengthRule.swift index 350c471ccd..aeb81bcdd9 100644 --- a/Source/SwiftLintFramework/Rules/Metrics/EnumCaseAssociatedValuesLengthRule.swift +++ b/Source/SwiftLintFramework/Rules/Metrics/EnumCaseAssociatedValuesLengthRule.swift @@ -67,7 +67,7 @@ private extension EnumCaseAssociatedValuesLengthRule { violationSeverity = .warning } - let reason = "Enum case \(node.identifier.withoutTrivia().text) should contain " + let reason = "Enum case \(node.identifier.text) should contain " + "less than \(configuration.warning) associated values: " + "currently contains \(enumCaseAssociatedValueCount)" violations.append( diff --git a/Source/SwiftLintFramework/Rules/Performance/ContainsOverFilterCountRule.swift b/Source/SwiftLintFramework/Rules/Performance/ContainsOverFilterCountRule.swift index d230799d5d..fd434285bf 100644 --- a/Source/SwiftLintFramework/Rules/Performance/ContainsOverFilterCountRule.swift +++ b/Source/SwiftLintFramework/Rules/Performance/ContainsOverFilterCountRule.swift @@ -60,10 +60,8 @@ private extension ContainsOverFilterCountRule { private extension TokenKind { var isZeroComparison: Bool { - self == .spacedBinaryOperator("==") || - self == .spacedBinaryOperator("!=") || - self == .unspacedBinaryOperator("==") || - self == .spacedBinaryOperator(">") || - self == .unspacedBinaryOperator(">") + self == .binaryOperator("==") || + self == .binaryOperator("!=") || + self == .binaryOperator(">") } } diff --git a/Source/SwiftLintFramework/Rules/Performance/EmptyCountRule.swift b/Source/SwiftLintFramework/Rules/Performance/EmptyCountRule.swift index 31da0eeddd..a67f08383e 100644 --- a/Source/SwiftLintFramework/Rules/Performance/EmptyCountRule.swift +++ b/Source/SwiftLintFramework/Rules/Performance/EmptyCountRule.swift @@ -98,7 +98,7 @@ private extension ExprSyntax { private extension TokenSyntax { var binaryOperator: String? { switch tokenKind { - case .spacedBinaryOperator(let str), .unspacedBinaryOperator(let str): + case .binaryOperator(let str): return str default: return nil diff --git a/Source/SwiftLintFramework/Rules/Performance/ReduceBooleanRule.swift b/Source/SwiftLintFramework/Rules/Performance/ReduceBooleanRule.swift index 7603db7ee0..73a39efaef 100644 --- a/Source/SwiftLintFramework/Rules/Performance/ReduceBooleanRule.swift +++ b/Source/SwiftLintFramework/Rules/Performance/ReduceBooleanRule.swift @@ -43,7 +43,7 @@ private extension ReduceBooleanRule { return } - let suggestedFunction = bool.booleanLiteral.tokenKind == .trueKeyword ? "allSatisfy" : "contains" + let suggestedFunction = bool.booleanLiteral.tokenKind == .keyword(.true) ? "allSatisfy" : "contains" violations.append( ReasonedRuleViolation( position: calledExpression.name.positionAfterSkippingLeadingTrivia, diff --git a/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift b/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift index 4939c6c19d..63c2646728 100644 --- a/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift @@ -121,7 +121,7 @@ private struct RuleHelper { func hasViolation( locationConverter: SourceLocationConverter, - attributesAndPlacements: [(SyntaxProtocol, AttributePlacement)] + attributesAndPlacements: [(AttributeSyntax, AttributePlacement)] ) -> Bool { var linesWithAttributes: Set = [keywordLine] for (attribute, placement) in attributesAndPlacements { @@ -147,75 +147,40 @@ private struct RuleHelper { } } -private enum Attribute { - case builtIn(AttributeSyntax) - case custom(CustomAttributeSyntax) - - static func from(syntax: SyntaxProtocol) -> Self? { - if let attribute = syntax.as(AttributeSyntax.self) { - return .builtIn(attribute) - } - if let attribute = syntax.as(CustomAttributeSyntax.self) { - return .custom(attribute) - } - return nil - } - - var hasArguments: Bool { - switch self { - case let .builtIn(attribute): - return attribute.argument != nil - case let .custom(attribute): - return attribute.argumentList != nil - } - } - - var name: String? { - switch self { - case let .builtIn(attribute): - return attribute.attributeName.text - case let .custom(attribute): - return attribute.attributeName.as(SimpleTypeIdentifierSyntax.self)?.typeName - } - } - - var syntaxNode: SyntaxProtocol { - switch self { - case let .builtIn(attribute): - return attribute - case let .custom(attribute): - return attribute - } - } -} - private extension AttributeListSyntax { func attributesAndPlacements(configuration: AttributesConfiguration, shouldBeOnSameLine: Bool) - -> [(SyntaxProtocol, AttributePlacement)] { - self.children(viewMode: .sourceAccurate) - .compactMap { Attribute.from(syntax: $0) } - .compactMap { attribute in - guard let attributeName = attribute.name else { - return nil - } - let atPrefixedName = "@\(attributeName)" + -> [(AttributeSyntax, AttributePlacement)] { + self + .children(viewMode: .sourceAccurate) + .compactMap { $0.as(AttributeSyntax.self) } + .map { attribute in + let atPrefixedName = "@\(attribute.attributeNameText)" if configuration.alwaysOnSameLine.contains(atPrefixedName) { - return (attribute.syntaxNode, .sameLineAsDeclaration) + return (attribute, .sameLineAsDeclaration) } else if configuration.alwaysOnNewLine.contains(atPrefixedName) { - return (attribute.syntaxNode, .dedicatedLine) - } else if attribute.hasArguments { - return (attribute.syntaxNode, .dedicatedLine) + return (attribute, .dedicatedLine) + } else if attribute.argument != nil { + return (attribute, .dedicatedLine) } - return shouldBeOnSameLine - ? (attribute.syntaxNode, .sameLineAsDeclaration) - : (attribute.syntaxNode, .dedicatedLine) + return shouldBeOnSameLine ? (attribute, .sameLineAsDeclaration) : (attribute, .dedicatedLine) } } + var hasAttributeWithKeypathArgument: Bool { + contains { element in + switch element { + case .attribute(let attribute): + return attribute.hasKeypathArgument + case .ifConfigDecl: + return false + } + } + } + // swiftlint:disable:next cyclomatic_complexity func makeHelper(locationConverter: SourceLocationConverter) -> RuleHelper? { - guard let parent else { + guard let parent, !hasAttributeWithKeypathArgument else { return nil } @@ -263,3 +228,9 @@ private extension AttributeListSyntax { ) } } + +private extension AttributeSyntax { + var hasKeypathArgument: Bool { + argument?.as(TupleExprElementListSyntax.self)?.first?.expression.is(KeyPathExprSyntax.self) == true + } +} diff --git a/Source/SwiftLintFramework/Rules/Style/AttributesRuleExamples.swift b/Source/SwiftLintFramework/Rules/Style/AttributesRuleExamples.swift index 15f90e1136..ea98e94c95 100644 --- a/Source/SwiftLintFramework/Rules/Style/AttributesRuleExamples.swift +++ b/Source/SwiftLintFramework/Rules/Style/AttributesRuleExamples.swift @@ -80,7 +80,17 @@ internal struct AttributesRuleExamples { @NSApplicationMain @MainActor final class AppDelegate: NSAppDelegate {} - """) + """), + Example(#""" + final class MyView: View { + @SwiftUI.Environment(\.colorScheme) var colorScheme: ColorScheme + } + """#), + Example(#""" + final class MyView: View { + @Environment(\.colorScheme) var colorScheme: ColorScheme + } + """#) ] static let triggeringExamples = [ diff --git a/Source/SwiftLintFramework/Rules/Style/ClosingBraceRule.swift b/Source/SwiftLintFramework/Rules/Style/ClosingBraceRule.swift index 9ec9081bff..2ac4e968fd 100644 --- a/Source/SwiftLintFramework/Rules/Style/ClosingBraceRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ClosingBraceRule.swift @@ -63,7 +63,7 @@ private extension ClosingBraceRule { } correctionPositions.append(node.positionAfterSkippingLeadingTrivia) - return super.visit(node.withTrailingTrivia(.zero)) + return super.visit(node.with(\.trailingTrivia, .zero)) } } } diff --git a/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift b/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift index a7e9a27740..abe1961fe9 100644 --- a/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift @@ -103,16 +103,16 @@ private final class ClosureSpacingRuleRewriter: SyntaxRewriter, ViolationsSyntax let violations = node.violations if violations.leftBraceLeftSpace { - node.leftBrace = node.leftBrace.withLeadingTrivia(.spaces(1)) + node.leftBrace = node.leftBrace.with(\.leadingTrivia, .spaces(1)) } if violations.leftBraceRightSpace { - node.leftBrace = node.leftBrace.withTrailingTrivia(.spaces(1)) + node.leftBrace = node.leftBrace.with(\.trailingTrivia, .spaces(1)) } if violations.rightBraceLeftSpace { - node.rightBrace = node.rightBrace.withLeadingTrivia(.spaces(1)) + node.rightBrace = node.rightBrace.with(\.leadingTrivia, .spaces(1)) } if violations.rightBraceRightSpace { - node.rightBrace = node.rightBrace.withTrailingTrivia(.spaces(1)) + node.rightBrace = node.rightBrace.with(\.trailingTrivia, .spaces(1)) } if violations.hasViolations { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) diff --git a/Source/SwiftLintFramework/Rules/Style/ComputedAccessorsOrderRule.swift b/Source/SwiftLintFramework/Rules/Style/ComputedAccessorsOrderRule.swift index aa86ec32d8..ccad3caf03 100644 --- a/Source/SwiftLintFramework/Rules/Style/ComputedAccessorsOrderRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ComputedAccessorsOrderRule.swift @@ -67,11 +67,11 @@ private extension AccessorBlockSyntax { } let tokens = accessors.map(\.accessorKind.tokenKind) - if tokens == [.contextualKeyword("get"), .contextualKeyword("set")] { + if tokens == [.keyword(.get), .keyword(.set)] { return .getSet } - if tokens == [.contextualKeyword("set"), .contextualKeyword("get")] { + if tokens == [.keyword(.set), .keyword(.get)] { return .setGet } diff --git a/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift b/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift index 1262981196..baebeae127 100644 --- a/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift @@ -53,7 +53,7 @@ private extension ConditionalReturnsOnNewlineRule { super.init(viewMode: .sourceAccurate) } - override func visitPost(_ node: IfStmtSyntax) { + override func visitPost(_ node: IfExprSyntax) { if isReturn(node.body.statements.lastReturn, onTheSameLineAs: node.ifKeyword) { violations.append(node.ifKeyword.positionAfterSkippingLeadingTrivia) return diff --git a/Source/SwiftLintFramework/Rules/Style/DirectReturnRule.swift b/Source/SwiftLintFramework/Rules/Style/DirectReturnRule.swift index 37c746582f..2b52c4a6ed 100644 --- a/Source/SwiftLintFramework/Rules/Style/DirectReturnRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/DirectReturnRule.swift @@ -210,22 +210,30 @@ private class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { .enumerated() .map { index, item in if index == bindingList.count - 2 { - return item.withTrailingComma(false) + return item.with(\.trailingComma, nil) } return item } if newBindingList.isNotEmpty { newStmtList.append(CodeBlockItemSyntax( - item: .decl(DeclSyntax(varDecl.withBindings(PatternBindingListSyntax(newBindingList)))) + item: .decl(DeclSyntax(varDecl.with(\.bindings, PatternBindingListSyntax(newBindingList)))) )) newStmtList.append(CodeBlockItemSyntax( - item: .stmt(StmtSyntax(returnStmt.withExpression(initExpression))) + item: .stmt(StmtSyntax(returnStmt.with(\.expression, initExpression))) )) } else { let leadingTrivia = (binding.trailingTrivia ?? .zero) + (returnStmt.leadingTrivia ?? .zero) - newStmtList.append(CodeBlockItemSyntax( - item: .stmt(StmtSyntax(returnStmt.withExpression(initExpression).withLeadingTrivia(leadingTrivia))) - )) + newStmtList.append( + CodeBlockItemSyntax( + item: .stmt( + StmtSyntax( + returnStmt + .with(\.expression, initExpression) + .with(\.leadingTrivia, leadingTrivia) + ) + ) + ) + ) } return super.visit(CodeBlockItemListSyntax(newStmtList)) } diff --git a/Source/SwiftLintFramework/Rules/Style/EmptyEnumArgumentsRule.swift b/Source/SwiftLintFramework/Rules/Style/EmptyEnumArgumentsRule.swift index 9a334a3c83..26850376c7 100644 --- a/Source/SwiftLintFramework/Rules/Style/EmptyEnumArgumentsRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/EmptyEnumArgumentsRule.swift @@ -159,7 +159,7 @@ private extension EmptyEnumArgumentsRule { } correctionPositions.append(violationPosition) - return super.visit(node.withPattern(newPattern)) + return super.visit(node.with(\.pattern, newPattern)) } override func visit(_ node: MatchingPatternConditionSyntax) -> MatchingPatternConditionSyntax { @@ -171,7 +171,7 @@ private extension EmptyEnumArgumentsRule { } correctionPositions.append(violationPosition) - return super.visit(node.withPattern(newPattern)) + return super.visit(node.with(\.pattern, newPattern)) } } } @@ -200,7 +200,7 @@ private extension PatternSyntax { private extension FunctionCallExprSyntax { var argumentsHasViolation: Bool { !calledExpression.is(IdentifierExprSyntax.self) && - calledExpression.as(MemberAccessExprSyntax.self)?.lastToken?.tokenKind != .initKeyword && + calledExpression.as(MemberAccessExprSyntax.self)?.lastToken?.tokenKind != .keyword(.`init`) && argumentList.allSatisfy(\.expression.isDiscardAssignmentOrFunction) } @@ -222,19 +222,19 @@ private extension FunctionCallExprSyntax { if argumentList.allSatisfy({ $0.expression.is(DiscardAssignmentExprSyntax.self) }) { let newCalledExpression = calledExpression - .withTrailingTrivia(rightParen?.trailingTrivia ?? .zero) + .with(\.trailingTrivia, rightParen?.trailingTrivia ?? .zero) let newExpression = self - .withCalledExpression(ExprSyntax(newCalledExpression)) - .withLeftParen(nil) - .withArgumentList(nil) - .withRightParen(nil) + .with(\.calledExpression, ExprSyntax(newCalledExpression)) + .with(\.leftParen, nil) + .with(\.argumentList, []) + .with(\.rightParen, nil) return ExprSyntax(newExpression) } var copy = self for (index, arg) in argumentList.enumerated() { if let newArgExpr = arg.expression.as(FunctionCallExprSyntax.self) { - let newArg = arg.withExpression(newArgExpr.removingInnermostDiscardArguments) + let newArg = arg.with(\.expression, newArgExpr.removingInnermostDiscardArguments) copy.argumentList = copy.argumentList.replacing(childAt: index, with: newArg) } } diff --git a/Source/SwiftLintFramework/Rules/Style/EmptyParametersRule.swift b/Source/SwiftLintFramework/Rules/Style/EmptyParametersRule.swift index 64248d7902..ea81edcce1 100644 --- a/Source/SwiftLintFramework/Rules/Style/EmptyParametersRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/EmptyParametersRule.swift @@ -75,7 +75,7 @@ private extension EmptyParametersRule { } correctionPositions.append(violationPosition) - return super.visit(node.withArguments(TupleTypeElementListSyntax([]))) + return super.visit(node.with(\.arguments, TupleTypeElementListSyntax([]))) } } } diff --git a/Source/SwiftLintFramework/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift b/Source/SwiftLintFramework/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift index 8f1e053599..f84f42cf91 100644 --- a/Source/SwiftLintFramework/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/EmptyParenthesesWithTrailingClosureRule.swift @@ -88,9 +88,9 @@ private extension EmptyParenthesesWithTrailingClosureRule { } let newNode = node - .withLeftParen(nil) - .withRightParen(nil) - .withTrailingClosure(node.trailingClosure?.withLeadingTrivia(.spaces(1))) + .with(\.leftParen, nil) + .with(\.rightParen, nil) + .with(\.trailingClosure, node.trailingClosure?.with(\.leadingTrivia, .spaces(1))) correctionPositions.append(violationPosition) return super.visit(newNode) } diff --git a/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift b/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift index 8e7dae6f36..573da55902 100644 --- a/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift @@ -36,8 +36,7 @@ private final class ImplicitGetterRuleVisitor: ViolationsSyntaxVisitor { override func visitPost(_ node: AccessorBlockSyntax) { guard let getAccessor = node.getAccessor, node.setAccessor == nil, - getAccessor.asyncKeyword == nil, - getAccessor.throwsKeyword == nil, + getAccessor.effectSpecifiers == nil, getAccessor.modifier == nil, (getAccessor.attributes == nil || getAccessor.attributes?.isEmpty == true), getAccessor.body != nil else { diff --git a/Source/SwiftLintFramework/Rules/Style/NoSpaceInMethodCallRule.swift b/Source/SwiftLintFramework/Rules/Style/NoSpaceInMethodCallRule.swift index 547febf207..d4c369514e 100644 --- a/Source/SwiftLintFramework/Rules/Style/NoSpaceInMethodCallRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/NoSpaceInMethodCallRule.swift @@ -89,7 +89,7 @@ private extension NoSpaceInMethodCallRule { correctionPositions.append(node.calledExpression.endPositionBeforeTrailingTrivia) let newNode = node - .withCalledExpression(node.calledExpression.withoutTrailingTrivia()) + .with(\.calledExpression, node.calledExpression.with(\.trailingTrivia, [])) return super.visit(newNode) } diff --git a/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift b/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift index be9aff0529..68d0b2865d 100644 --- a/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift @@ -88,7 +88,8 @@ private extension NumberSeparatorRule { return super.visit(node) } - let newNode = node.withFloatingDigits(node.floatingDigits.withKind(.floatingLiteral(violation.correction))) + let newNode = node.with(\.floatingDigits, + node.floatingDigits.withKind(.floatingLiteral(violation.correction))) correctionPositions.append(violation.position) return super.visit(newNode) } @@ -101,7 +102,7 @@ private extension NumberSeparatorRule { return super.visit(node) } - let newNode = node.withDigits(node.digits.withKind(.integerLiteral(violation.correction))) + let newNode = node.with(\.digits, node.digits.withKind(.integerLiteral(violation.correction))) correctionPositions.append(violation.position) return super.visit(newNode) } @@ -140,7 +141,7 @@ private enum NumberSeparatorViolation { private extension NumberSeparatorValidator { func violation(token: TokenSyntax) -> NumberSeparatorViolation? { - let content = token.withoutTrivia().text + let content = token.text guard isDecimal(number: content), !isInValidRanges(number: content) else { diff --git a/Source/SwiftLintFramework/Rules/Style/OperatorFunctionWhitespaceRule.swift b/Source/SwiftLintFramework/Rules/Style/OperatorFunctionWhitespaceRule.swift index 1127aff6d3..9eef080f9a 100644 --- a/Source/SwiftLintFramework/Rules/Style/OperatorFunctionWhitespaceRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/OperatorFunctionWhitespaceRule.swift @@ -45,7 +45,7 @@ private extension OperatorFunctionWhitespaceRule { private extension FunctionDeclSyntax { var isOperatorDeclaration: Bool { switch identifier.tokenKind { - case .spacedBinaryOperator, .unspacedBinaryOperator: + case .binaryOperator: return true default: return false diff --git a/Source/SwiftLintFramework/Rules/Style/OperatorUsageWhitespaceRule.swift b/Source/SwiftLintFramework/Rules/Style/OperatorUsageWhitespaceRule.swift index 25002cecf0..ddb525c283 100644 --- a/Source/SwiftLintFramework/Rules/Style/OperatorUsageWhitespaceRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/OperatorUsageWhitespaceRule.swift @@ -183,7 +183,7 @@ private class OperatorUsageWhitespaceVisitor: SyntaxVisitor { let noSpacingAfter = operatorToken.trailingTrivia.isEmpty && nextToken.leadingTrivia.isEmpty let noSpacing = noSpacingBefore || noSpacingAfter - let operatorText = operatorToken.withoutTrivia().text + let operatorText = operatorToken.text if noSpacing && allowedNoSpaceOperators.contains(operatorText) { return nil } @@ -230,7 +230,7 @@ private extension Trivia { switch element { case .blockComment, .docLineComment, .docBlockComment, .lineComment: return true - case .carriageReturnLineFeeds, .carriageReturns, .formfeeds, .newlines, + case .backslashes, .carriageReturnLineFeeds, .carriageReturns, .formfeeds, .newlines, .pounds, .shebang, .spaces, .tabs, .unexpectedText, .verticalTabs: return false } diff --git a/Source/SwiftLintFramework/Rules/Style/OptionalEnumCaseMatchingRule.swift b/Source/SwiftLintFramework/Rules/Style/OptionalEnumCaseMatchingRule.swift index 22f4cf36dd..60da061cd4 100644 --- a/Source/SwiftLintFramework/Rules/Style/OptionalEnumCaseMatchingRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/OptionalEnumCaseMatchingRule.swift @@ -209,11 +209,11 @@ private extension OptionalEnumCaseMatchingRule { !expression.expression.isDiscardAssignmentOrBoolLiteral { let violationPosition = expression.questionMark.positionAfterSkippingLeadingTrivia correctionPositions.append(violationPosition) - let newExpression = ExprSyntax(expression.withQuestionMark(nil)) - let newPattern = PatternSyntax(pattern.withExpression(newExpression)) + let newPattern = PatternSyntax(pattern.with(\.expression, expression.expression)) let newNode = node - .withPattern(newPattern) - .withWhereClause(node.whereClause?.withLeadingTrivia(expression.questionMark.trailingTrivia)) + .with(\.pattern, newPattern) + .with(\.whereClause, + node.whereClause?.with(\.leadingTrivia, expression.questionMark.trailingTrivia)) return super.visit(newNode) } else if let expression = pattern.expression.as(TupleExprSyntax.self) { var newExpression = expression @@ -228,14 +228,13 @@ private extension OptionalEnumCaseMatchingRule { let violationPosition = optionalChainingExpression.questionMark.positionAfterSkippingLeadingTrivia correctionPositions.append(violationPosition) - let newElementExpression = ExprSyntax(optionalChainingExpression.withQuestionMark(nil)) - let newElement = element.withExpression(newElementExpression) + let newElement = element.with(\.expression, optionalChainingExpression.expression) newExpression.elementList = newExpression.elementList .replacing(childAt: index, with: newElement) } - let newPattern = PatternSyntax(pattern.withExpression(ExprSyntax(newExpression))) - let newNode = node.withPattern(newPattern) + let newPattern = PatternSyntax(pattern.with(\.expression, ExprSyntax(newExpression))) + let newNode = node.with(\.pattern, newPattern) return super.visit(newNode) } diff --git a/Source/SwiftLintFramework/Rules/Style/PreferSelfInStaticReferencesRule.swift b/Source/SwiftLintFramework/Rules/Style/PreferSelfInStaticReferencesRule.swift index dbb8484e0b..2762ae41ab 100644 --- a/Source/SwiftLintFramework/Rules/Style/PreferSelfInStaticReferencesRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/PreferSelfInStaticReferencesRule.swift @@ -296,7 +296,7 @@ private class Visitor: ViolationsSyntaxVisitor { override func visit(_ node: MemberAccessExprSyntax) -> SyntaxVisitorContinueKind { if case .likeClass = parentDeclScopes.last { - if node.name.tokenKind == .selfKeyword { + if node.name.tokenKind == .keyword(.self) { return .skipChildren } } diff --git a/Source/SwiftLintFramework/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift b/Source/SwiftLintFramework/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift index c6d22122ef..d92383c4f9 100644 --- a/Source/SwiftLintFramework/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/PreferSelfTypeOverTypeOfSelfRule.swift @@ -147,11 +147,12 @@ private extension PreferSelfTypeOverTypeOfSelfRule { correctionPositions.append(function.positionAfterSkippingLeadingTrivia) - let base: IdentifierExprSyntax = "Self" + // swiftlint:disable:next rule_id + let base = IdentifierExprSyntax(identifier: "Self") let baseWithTrivia = base - .withLeadingTrivia(function.leadingTrivia ?? .zero) - .withTrailingTrivia(function.trailingTrivia ?? .zero) - return super.visit(node.withBase(ExprSyntax(baseWithTrivia))) + .with(\.leadingTrivia, function.leadingTrivia ?? .zero) + .with(\.trailingTrivia, function.trailingTrivia ?? .zero) + return super.visit(node.with(\.base, ExprSyntax(baseWithTrivia))) } } } @@ -160,7 +161,7 @@ private extension FunctionCallExprSyntax { var hasViolation: Bool { return isTypeOfSelfCall && argumentList.map(\.label?.text) == ["of"] && - argumentList.first?.expression.as(IdentifierExprSyntax.self)?.identifier.tokenKind == .selfKeyword + argumentList.first?.expression.as(IdentifierExprSyntax.self)?.identifier.tokenKind == .keyword(.self) } var isTypeOfSelfCall: Bool { diff --git a/Source/SwiftLintFramework/Rules/Style/PrefixedTopLevelConstantRule.swift b/Source/SwiftLintFramework/Rules/Style/PrefixedTopLevelConstantRule.swift index aa1f5a92da..f1e1498188 100644 --- a/Source/SwiftLintFramework/Rules/Style/PrefixedTopLevelConstantRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/PrefixedTopLevelConstantRule.swift @@ -87,7 +87,7 @@ private extension PrefixedTopLevelConstantRule { override var skippableDeclarations: [DeclSyntaxProtocol.Type] { .all } override func visitPost(_ node: VariableDeclSyntax) { - guard node.letOrVarKeyword.tokenKind == .letKeyword else { + guard node.letOrVarKeyword.tokenKind == .keyword(.let) else { return } diff --git a/Source/SwiftLintFramework/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift b/Source/SwiftLintFramework/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift index 99d05682d6..f8bc0cfddf 100644 --- a/Source/SwiftLintFramework/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ProtocolPropertyAccessorsOrderRule.swift @@ -73,7 +73,7 @@ private extension ProtocolPropertyAccessorsOrderRule { let reversedAccessors = AccessorListSyntax(Array(node.accessors.reversed())) return super.visit( - node.withAccessors(reversedAccessors) + node.with(\.accessors, reversedAccessors) ) } } @@ -83,7 +83,7 @@ private extension AccessorBlockSyntax { var hasViolation: Bool { guard accessors.count == 2, accessors.allSatisfy({ $0.body == nil }), - accessors.first?.accessorKind.tokenKind == .contextualKeyword("set") else { + accessors.first?.accessorKind.tokenKind == .keyword(.set) else { return false } diff --git a/Source/SwiftLintFramework/Rules/Style/RedundantDiscardableLetRule.swift b/Source/SwiftLintFramework/Rules/Style/RedundantDiscardableLetRule.swift index 7d69ccba10..53f0664899 100644 --- a/Source/SwiftLintFramework/Rules/Style/RedundantDiscardableLetRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/RedundantDiscardableLetRule.swift @@ -69,8 +69,8 @@ private extension RedundantDiscardableLetRule { correctionPositions.append(node.positionAfterSkippingLeadingTrivia) let newNode = node - .withLetOrVarKeyword(nil) - .withBindings(node.bindings.withLeadingTrivia(node.letOrVarKeyword.leadingTrivia)) + .with(\.letOrVarKeyword, .keyword(.let, presence: .missing)) + .with(\.bindings, node.bindings.with(\.leadingTrivia, node.letOrVarKeyword.leadingTrivia)) return super.visit(newNode) } } @@ -78,7 +78,7 @@ private extension RedundantDiscardableLetRule { private extension VariableDeclSyntax { var hasRedundantDiscardableLetViolation: Bool { - letOrVarKeyword.tokenKind == .letKeyword && + letOrVarKeyword.tokenKind == .keyword(.let) && bindings.count == 1 && bindings.first!.pattern.is(WildcardPatternSyntax.self) && bindings.first!.typeAnnotation == nil && diff --git a/Source/SwiftLintFramework/Rules/Style/ReturnArrowWhitespaceRule.swift b/Source/SwiftLintFramework/Rules/Style/ReturnArrowWhitespaceRule.swift index 7ba0e51bf2..a7c3f5e1ef 100644 --- a/Source/SwiftLintFramework/Rules/Style/ReturnArrowWhitespaceRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ReturnArrowWhitespaceRule.swift @@ -93,7 +93,7 @@ private extension ReturnArrowWhitespaceRule { private(set) var corrections: [ArrowViolation] = [] override func visitPost(_ node: FunctionTypeSyntax) { - guard let violation = node.arrow.arrowViolation else { + guard let violation = node.output.arrow.arrowViolation else { return } diff --git a/Source/SwiftLintFramework/Rules/Style/SelfBindingRule.swift b/Source/SwiftLintFramework/Rules/Style/SelfBindingRule.swift index cbaed9daff..add85d050f 100644 --- a/Source/SwiftLintFramework/Rules/Style/SelfBindingRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/SelfBindingRule.swift @@ -120,36 +120,36 @@ private final class SelfBindingRuleRewriter: SyntaxRewriter, ViolationsSyntaxRew initializerIdentifier.identifier.text == "self" { correctionPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia) - return super.visit( - node.withPattern( - PatternSyntax( - identifierPattern.withIdentifier( - identifierPattern.identifier.withKind(.identifier(bindIdentifier)) - ) - ) + let newPattern = PatternSyntax( + identifierPattern + .with(\.identifier, + identifierPattern.identifier.withKind(.identifier(bindIdentifier)) ) ) + + return super.visit(node.with(\.pattern, newPattern)) } else if node.initializer == nil, identifierPattern.identifier.text == "self", bindIdentifier != "self" { correctionPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia) - let newNode = node - .withPattern( - PatternSyntax( - identifierPattern.withIdentifier( - identifierPattern.identifier.withKind(.identifier(bindIdentifier)) - ) - ) - ) - .withInitializer( - InitializerClauseSyntax( - value: IdentifierExprSyntax( - identifier: .selfKeyword( - leadingTrivia: .space, - trailingTrivia: identifierPattern.trailingTrivia ?? .space - ) - ) + let newPattern = PatternSyntax( + identifierPattern + .with(\.identifier, + identifierPattern.identifier.withKind(.identifier(bindIdentifier))) + ) + + let newInitializer = InitializerClauseSyntax( + value: IdentifierExprSyntax( + identifier: .keyword( + .`self`, + leadingTrivia: .space, + trailingTrivia: identifierPattern.trailingTrivia ?? .space ) ) + ) + + let newNode = node + .with(\.pattern, newPattern) + .with(\.initializer, newInitializer) return super.visit(newNode) } else { return super.visit(node) diff --git a/Source/SwiftLintFramework/Rules/Style/ShorthandOperatorRule.swift b/Source/SwiftLintFramework/Rules/Style/ShorthandOperatorRule.swift index 8df47d4d29..46e5c5be74 100644 --- a/Source/SwiftLintFramework/Rules/Style/ShorthandOperatorRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ShorthandOperatorRule.swift @@ -62,8 +62,8 @@ private extension ShorthandOperatorRule { guard node.operatorOperand.is(AssignmentExprSyntax.self), let rightExpr = node.rightOperand.as(InfixOperatorExprSyntax.self), let binaryOperatorExpr = rightExpr.operatorOperand.as(BinaryOperatorExprSyntax.self), - ShorthandOperatorRule.allOperators.contains(binaryOperatorExpr.operatorToken.withoutTrivia().text), - node.leftOperand.withoutTrivia().description == rightExpr.leftOperand.withoutTrivia().description + ShorthandOperatorRule.allOperators.contains(binaryOperatorExpr.operatorToken.text), + node.leftOperand.trimmedDescription == rightExpr.leftOperand.trimmedDescription else { return } @@ -86,7 +86,7 @@ private extension ShorthandOperatorRule { private extension TokenSyntax { var binaryOperator: String? { switch tokenKind { - case .spacedBinaryOperator(let str), .unspacedBinaryOperator(let str): + case .binaryOperator(let str): return str default: return nil diff --git a/Source/SwiftLintFramework/Rules/Style/SwitchCaseAlignmentRule.swift b/Source/SwiftLintFramework/Rules/Style/SwitchCaseAlignmentRule.swift index 67c8b9ee09..49d8cbd711 100644 --- a/Source/SwiftLintFramework/Rules/Style/SwitchCaseAlignmentRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/SwitchCaseAlignmentRule.swift @@ -56,7 +56,7 @@ extension SwitchCaseAlignmentRule { super.init(viewMode: .sourceAccurate) } - override func visitPost(_ node: SwitchStmtSyntax) { + override func visitPost(_ node: SwitchExprSyntax) { let switchPosition = node.switchKeyword.positionAfterSkippingLeadingTrivia guard let switchColumn = locationConverter.location(for: switchPosition).column, diff --git a/Source/SwiftLintFramework/Rules/Style/TrailingCommaRule.swift b/Source/SwiftLintFramework/Rules/Style/TrailingCommaRule.swift index d79a2b4b45..0977409d4f 100644 --- a/Source/SwiftLintFramework/Rules/Style/TrailingCommaRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/TrailingCommaRule.swift @@ -135,16 +135,15 @@ private extension TrailingCommaRule { switch (lastElement.trailingComma, mandatoryComma) { case (let commaToken?, false): correctionPositions.append(commaToken.positionAfterSkippingLeadingTrivia) + let newTrailingTrivia = (lastElement.valueExpression.trailingTrivia ?? .zero) + .appending(trivia: commaToken.leadingTrivia) + .appending(trivia: commaToken.trailingTrivia) let newNode = node .replacing( childAt: lastElement.indexInParent, with: lastElement - .withTrailingComma(nil) - .withTrailingTrivia( - (lastElement.valueExpression.trailingTrivia ?? .zero) - .appending(trivia: commaToken.leadingTrivia) - .appending(trivia: commaToken.trailingTrivia) - ) + .with(\.trailingComma, nil) + .with(\.trailingTrivia, newTrailingTrivia) ) return super.visit(newNode) case (nil, true) where !locationConverter.isSingleLine(node: node): @@ -153,9 +152,9 @@ private extension TrailingCommaRule { .replacing( childAt: lastElement.indexInParent, with: lastElement - .withoutTrailingTrivia() - .withTrailingComma(.commaToken()) - .withTrailingTrivia(lastElement.trailingTrivia ?? .zero) + .with(\.trailingTrivia, []) + .with(\.trailingComma, .commaToken()) + .with(\.trailingTrivia, lastElement.trailingTrivia ?? .zero) ) return super.visit(newNode) case (_, true), (nil, false): @@ -176,11 +175,11 @@ private extension TrailingCommaRule { .replacing( childAt: lastElement.indexInParent, with: lastElement - .withTrailingComma(nil) - .withTrailingTrivia( - (lastElement.expression.trailingTrivia ?? .zero) - .appending(trivia: commaToken.leadingTrivia) - .appending(trivia: commaToken.trailingTrivia) + .with(\.trailingComma, nil) + .with(\.trailingTrivia, + (lastElement.expression.trailingTrivia ?? .zero) + .appending(trivia: commaToken.leadingTrivia) + .appending(trivia: commaToken.trailingTrivia) ) ) return super.visit(newNode) @@ -189,9 +188,9 @@ private extension TrailingCommaRule { let newNode = node.replacing( childAt: lastElement.indexInParent, with: lastElement - .withExpression(lastElement.expression.withoutTrailingTrivia()) - .withTrailingComma(.commaToken()) - .withTrailingTrivia(lastElement.expression.trailingTrivia ?? .zero) + .with(\.expression, lastElement.expression.with(\.trailingTrivia, [])) + .with(\.trailingComma, .commaToken()) + .with(\.trailingTrivia, lastElement.expression.trailingTrivia ?? .zero) ) return super.visit(newNode) case (_, true), (nil, false): diff --git a/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift b/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift index 359ec18bb6..6b81886bf6 100644 --- a/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift @@ -133,7 +133,7 @@ private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter { correctionPositions.append(clause.positionAfterSkippingLeadingTrivia) - let paramList = ClosureParamListSyntax(items).withTrailingTrivia(.spaces(1)) - return super.visit(node.withInput(.init(paramList))) + let paramList = ClosureParamListSyntax(items).with(\.trailingTrivia, .spaces(1)) + return super.visit(node.with(\.input, .init(paramList))) } } diff --git a/bazel/repos.bzl b/bazel/repos.bzl index a8d92a8502..cb8141bde4 100644 --- a/bazel/repos.bzl +++ b/bazel/repos.bzl @@ -20,10 +20,10 @@ def swiftlint_repos(bzlmod = False): http_archive( name = "com_github_apple_swift_syntax", - sha256 = "2024415299a487fcb3b2d7500d2e7c149b4bc4f3b94408edd601457ee27f6b11", # SwiftSyntax sha256 + sha256 = "ef9701634ad34e2dd08a2cd85bb5437af17512175bf6b4623c7d2d28068b6786", # SwiftSyntax sha256 build_file = "@SwiftLint//bazel:SwiftSyntax.BUILD", - strip_prefix = "swift-syntax-0.50800.0-SNAPSHOT-2022-12-29-a", - url = "https://github.com/apple/swift-syntax/archive/refs/tags/0.50800.0-SNAPSHOT-2022-12-29-a.tar.gz", + strip_prefix = "swift-syntax-0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a", + url = "https://github.com/apple/swift-syntax/archive/refs/tags/0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a.tar.gz", ) http_archive(