Compare commits

...

1 Commits

Author SHA1 Message Date
JP Simard aa1e2e5170
Use SwiftSyntax's new SwiftParser 2022-09-12 04:05:22 -04:00
42 changed files with 177 additions and 97 deletions

6
BUILD
View File

@ -21,9 +21,9 @@ swift_library(
visibility = ["//visibility:public"],
deps = [
"@com_github_jpsim_sourcekitten//:SourceKittenFramework",
"@com_github_keith_swift_syntax//:SwiftSyntax",
"@com_github_keith_swift_syntax//:SwiftSyntaxBuilder",
"@com_github_keith_swift_syntax//:SwiftSyntaxParser",
"@com_github_apple_swift_syntax//:SwiftSyntax",
"@com_github_apple_swift_syntax//:SwiftSyntaxBuilder",
"@com_github_apple_swift_syntax//:SwiftParser",
"@sourcekitten_com_github_jpsim_yams//:Yams",
] + select({
"@platforms//os:linux": ["@com_github_krzyzanowskim_cryptoswift//:CryptoSwift"],

View File

@ -24,8 +24,8 @@
"repositoryURL": "https://github.com/apple/swift-argument-parser.git",
"state": {
"branch": null,
"revision": "df9ee6676cd5b3bf5b330ec7568a5644f547201b",
"version": "1.1.3"
"revision": "9f39744e025c7d377987f30b03770805dcb0bcd1",
"version": "1.1.4"
}
},
{
@ -33,8 +33,8 @@
"repositoryURL": "https://github.com/apple/swift-syntax.git",
"state": {
"branch": null,
"revision": "0b6c22b97f8e9320bca62e82cdbee601cf37ad3f",
"version": "0.50600.1"
"revision": "e6fa90ca5e47803439ab478d51ee1c833619e8f8",
"version": null
}
},
{

View File

@ -3,21 +3,18 @@ import PackageDescription
#if os(macOS)
private let addCryptoSwift = false
private let staticSwiftSyntax = true
#else
private let addCryptoSwift = true
private let staticSwiftSyntax = false
#endif
let frameworkDependencies: [Target.Dependency] = [
.product(name: "SourceKittenFramework", package: "SourceKitten"),
.product(name: "SwiftSyntax", package: "SwiftSyntax"),
.product(name: "SwiftSyntaxBuilder", package: "SwiftSyntax"),
.product(name: "SwiftSyntaxParser", package: "SwiftSyntax"),
.product(name: "SwiftParser", package: "SwiftSyntax"),
"Yams",
]
+ (addCryptoSwift ? ["CryptoSwift"] : [])
+ (staticSwiftSyntax ? ["lib_InternalSwiftSyntaxParser"] : [])
let package = Package(
name: "SwiftLint",
@ -28,7 +25,7 @@ let package = Package(
],
dependencies: [
.package(name: "swift-argument-parser", url: "https://github.com/apple/swift-argument-parser.git", .upToNextMinor(from: "1.1.3")),
.package(name: "SwiftSyntax", url: "https://github.com/apple/swift-syntax.git", .exact("0.50600.1")),
.package(name: "SwiftSyntax", url: "https://github.com/apple/swift-syntax.git", .revision("e6fa90ca5e47803439ab478d51ee1c833619e8f8")),
.package(url: "https://github.com/jpsim/SourceKitten.git", from: "0.33.0"),
.package(url: "https://github.com/jpsim/Yams.git", from: "5.0.1"),
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.9.0"),
@ -46,11 +43,7 @@ let package = Package(
),
.target(
name: "SwiftLintFramework",
dependencies: frameworkDependencies,
// Pass `-dead_strip_dylibs` to ignore the dynamic version of `lib_InternalSwiftSyntaxParser`
// that ships with SwiftSyntax because we want the static version from
// `StaticInternalSwiftSyntaxParser`.
linkerSettings: staticSwiftSyntax ? [.unsafeFlags(["-Xlinker", "-dead_strip_dylibs"])] : []
dependencies: frameworkDependencies
),
.testTarget(
name: "SwiftLintFrameworkTests",
@ -61,9 +54,5 @@ let package = Package(
"Resources",
]
),
] + (staticSwiftSyntax ? [.binaryTarget(
name: "lib_InternalSwiftSyntaxParser",
url: "https://github.com/keith/StaticInternalSwiftSyntaxParser/releases/download/5.6/lib_InternalSwiftSyntaxParser.xcframework.zip",
checksum: "88d748f76ec45880a8250438bd68e5d6ba716c8042f520998a438db87083ae9d"
)] : [])
]
)

View File

@ -2,7 +2,7 @@ import SwiftSyntax
extension SourceFileSyntax {
func windowsOfThreeTokens() -> [(TokenSyntax, TokenSyntax, TokenSyntax)] {
Array(tokens)
Array(tokens(viewMode: .sourceAccurate))
.windows(ofCount: 3)
.map { tokens in
let previous = tokens[tokens.startIndex]

View File

@ -1,9 +1,7 @@
import Foundation
import SourceKittenFramework
import SwiftParser
import SwiftSyntax
#if canImport(SwiftSyntaxParser)
import SwiftSyntaxParser
#endif
private let warnSyntaxParserFailureOnceImpl: Void = {
queuedPrintError("Could not parse the syntax tree for at least one file. Results may be invalid.")
@ -38,7 +36,7 @@ private var structureDictionaryCache = Cache({ file in
private var syntaxTreeCache = Cache({ file -> SourceFileSyntax? in
do {
return try SyntaxParser.parse(source: file.contents)
return try Parser.parse(source: file.contents)
} catch {
warnSyntaxParserFailureOnce()
return nil

View File

@ -9,7 +9,7 @@ final class CommandVisitor: SyntaxVisitor {
init(locationConverter: SourceLocationConverter) {
self.locationConverter = locationConverter
super.init()
super.init(viewMode: .sourceAccurate)
}
override func visitPost(_ node: TokenSyntax) {

View File

@ -36,7 +36,7 @@ public struct BlockBasedKVORule: SwiftSyntaxRule, ConfigurationProviderRule {
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -15,7 +15,7 @@ public struct DiscouragedOptionalBooleanRule: OptInRule, ConfigurationProviderRu
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -17,7 +17,7 @@ public struct ForceCastRule: ConfigurationProviderRule, SwiftSyntaxRule {
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
ForceCastRuleVisitor()
ForceCastRuleVisitor(viewMode: .sourceAccurate)
}
}
@ -29,4 +29,10 @@ private final class ForceCastRuleVisitor: SyntaxVisitor, ViolationsSyntaxVisitor
violationPositions.append(node.asTok.positionAfterSkippingLeadingTrivia)
}
}
override func visitPost(_ node: UnresolvedAsExprSyntax) {
if node.questionOrExclamationMark?.tokenKind == .exclamationMark {
violationPositions.append(node.asTok.positionAfterSkippingLeadingTrivia)
}
}
}

View File

@ -27,7 +27,7 @@ public struct ForceTryRule: ConfigurationProviderRule, SwiftSyntaxRule {
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -68,7 +68,7 @@ public struct ForceUnwrappingRule: OptInRule, SwiftSyntaxRule, ConfigurationProv
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
ForceUnwrappingVisitor()
ForceUnwrappingVisitor(viewMode: .sourceAccurate)
}
}

View File

@ -24,7 +24,7 @@ public struct RedundantNilCoalescingRule: OptInRule, SwiftSyntaxCorrectableRule,
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
public func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? {

View File

@ -16,7 +16,7 @@ public struct ReturnValueFromVoidFunctionRule: ConfigurationProviderRule, OptInR
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
ReturnValueFromVoidFunctionVisitor()
ReturnValueFromVoidFunctionVisitor(viewMode: .sourceAccurate)
}
}

View File

@ -18,7 +18,7 @@ public struct SyntacticSugarRule: CorrectableRule, ConfigurationProviderRule, So
)
public func validate(file: SwiftLintFile) -> [StyleViolation] {
let visitor = SyntacticSugarRuleVisitor()
let visitor = SyntacticSugarRuleVisitor(viewMode: .sourceAccurate)
return visitor.walk(file: file) { visitor in
flattenViolations(visitor.violations)
}.map { violation in
@ -34,7 +34,7 @@ public struct SyntacticSugarRule: CorrectableRule, ConfigurationProviderRule, So
}
public func correct(file: SwiftLintFile) -> [Correction] {
let visitor = SyntacticSugarRuleVisitor()
let visitor = SyntacticSugarRuleVisitor(viewMode: .sourceAccurate)
return visitor.walk(file: file) { visitor in
var context = CorrectingContext(rule: self, file: file, contents: file.contents)
context.correctViolations(visitor.violations)
@ -144,6 +144,17 @@ private final class SyntacticSugarRuleVisitor: SyntaxVisitor {
}
}
override func visitPost(_ node: UnresolvedAsExprSyntax) {
// json["recommendations"] as? Array<[String: Any]>
if
let parent = node.parent,
let typeName = parent.children(viewMode: .sourceAccurate).last?.as(TypeExprSyntax.self),
let violation = violation(in: typeName.type)
{
violations.append(violation)
}
}
override func visitPost(_ node: TypeInitializerClauseSyntax) {
// typealias Document = Dictionary<String, AnyBSON?>
if let violation = violation(in: node.value) {
@ -172,7 +183,7 @@ private final class SyntacticSugarRuleVisitor: SyntaxVisitor {
// let x = Array<String>.array(of: object)
// Skip checks for 'self' or \T Dictionary<Key, Value>.self
if let parent = node.parent?.as(MemberAccessExprSyntax.self),
let lastToken = Array(parent.tokens).last?.tokenKind,
let lastToken = Array(parent.tokens(viewMode: .sourceAccurate)).last?.tokenKind,
[.selfKeyword, .identifier("Type"), .identifier("none"), .identifier("Index")].contains(lastToken) {
return
}

View File

@ -1,5 +1,4 @@
import SwiftSyntax
import SwiftSyntaxBuilder
public struct ToggleBoolRule: SwiftSyntaxCorrectableRule, ConfigurationProviderRule, OptInRule {
public var configuration = SeverityConfiguration(.warning)
@ -32,7 +31,7 @@ public struct ToggleBoolRule: SwiftSyntaxCorrectableRule, ConfigurationProviderR
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
public func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? {
@ -81,19 +80,18 @@ private extension ToggleBoolRule {
correctionPositions.append(node.positionAfterSkippingLeadingTrivia)
let functionCall = FunctionCallExprSyntax { functionCall in
functionCall.useCalledExpression(
ExprSyntax(
MemberAccessExprSyntax { memberAccess in
memberAccess.useBase(node.first!.withoutTrivia())
memberAccess.useDot(.period)
memberAccess.useName(.identifier("toggle"))
}
let functionCall = FunctionCallExprSyntax(
calledExpression: ExprSyntax(
MemberAccessExprSyntax(
base: node.first!.withoutTrivia(),
dot: .periodToken(),
name: .identifier("toggle"),
declNameArguments: nil
)
)
functionCall.useLeftParen(.leftParen)
functionCall.useRightParen(.rightParen)
}
),
leftParen: .leftParenToken(), argumentList: .init([]), rightParen: .rightParenToken(),
trailingClosure: nil, additionalTrailingClosures: nil
)
let newNode = node
.replacing(childAt: 0, with: ExprSyntax(functionCall))

View File

@ -73,7 +73,7 @@ public struct UnavailableConditionRule: ConfigurationProviderRule, SourceKitFree
)
public func validate(file: SwiftLintFile) -> [StyleViolation] {
let visitor = UnavailableConditionRuleVisitor()
let visitor = UnavailableConditionRuleVisitor(viewMode: .sourceAccurate)
return visitor.walk(file: file, handler: \.availabilityChecks).map { check in
StyleViolation(
ruleDescription: Self.description,

View File

@ -51,7 +51,7 @@ public struct UnneededBreakInSwitchRule: SwiftSyntaxRule, ConfigurationProviderR
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
UnneededBreakInSwitchRuleVisitor()
UnneededBreakInSwitchRuleVisitor(viewMode: .sourceAccurate)
}
}

View File

@ -88,7 +88,7 @@ public struct UntypedErrorInCatchRule: OptInRule, ConfigurationProviderRule, Swi
])
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
UntypedErrorInCatchRuleVisitor()
UntypedErrorInCatchRuleVisitor(viewMode: .sourceAccurate)
}
public func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? {
@ -167,7 +167,7 @@ private final class UntypedErrorInCatchRuleRewriter: SyntaxRewriter, ViolationsS
return super.visit(
node
.withCatchKeyword(node.catchKeyword.withTrailingTrivia(.spaces(1)))
.withCatchItems(SyntaxFactory.makeBlankCatchItemList())
.withCatchItems(CatchItemListSyntax([]))
)
}
}

View File

@ -109,7 +109,7 @@ public struct VoidFunctionInTernaryConditionRule: ConfigurationProviderRule, Swi
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
VoidFunctionInTernaryConditionVisitor()
VoidFunctionInTernaryConditionVisitor(viewMode: .sourceAccurate)
}
}
@ -130,11 +130,26 @@ private class VoidFunctionInTernaryConditionVisitor: SyntaxVisitor, ViolationsSy
violationPositions.append(node.questionMark.positionAfterSkippingLeadingTrivia)
}
override func visitPost(_ node: UnresolvedTernaryExprSyntax) {
guard node.firstChoice.is(FunctionCallExprSyntax.self),
let parent = node.parent?.as(ExprListSyntax.self),
parent.last?.is(FunctionCallExprSyntax.self) == true,
!parent.containsAssignment,
let grandparent = parent.parent,
grandparent.is(SequenceExprSyntax.self),
let blockItem = grandparent.parent?.as(CodeBlockItemSyntax.self),
!blockItem.isImplicitReturn else {
return
}
violationPositions.append(node.questionMark.positionAfterSkippingLeadingTrivia)
}
}
private extension ExprListSyntax {
var containsAssignment: Bool {
return children.contains(where: { $0.is(AssignmentExprSyntax.self) })
return children(viewMode: .sourceAccurate).contains(where: { $0.is(AssignmentExprSyntax.self) })
}
}
@ -151,7 +166,7 @@ private extension CodeBlockItemSyntax {
return false
}
return parent.children.count == 1 && grandparent.is(ClosureExprSyntax.self)
return parent.children(viewMode: .sourceAccurate).count == 1 && grandparent.is(ClosureExprSyntax.self)
}
var isFunctionImplicitReturn: Bool {
@ -160,7 +175,7 @@ private extension CodeBlockItemSyntax {
return false
}
return parent.children.count == 1 && functionDecl.signature.allowsImplicitReturns
return parent.children(viewMode: .sourceAccurate).count == 1 && functionDecl.signature.allowsImplicitReturns
}
var isVariableImplicitReturn: Bool {
@ -169,7 +184,7 @@ private extension CodeBlockItemSyntax {
}
let isVariableDecl = parent.parent?.parent?.as(PatternBindingSyntax.self) != nil
return parent.children.count == 1 && isVariableDecl
return parent.children(viewMode: .sourceAccurate).count == 1 && isVariableDecl
}
var isSubscriptImplicitReturn: Bool {
@ -178,7 +193,7 @@ private extension CodeBlockItemSyntax {
return false
}
return parent.children.count == 1 && subscriptDecl.allowsImplicitReturns
return parent.children(viewMode: .sourceAccurate).count == 1 && subscriptDecl.allowsImplicitReturns
}
var isAcessorImplicitReturn: Bool {
@ -187,7 +202,7 @@ private extension CodeBlockItemSyntax {
return false
}
return parent.children.count == 1
return parent.children(viewMode: .sourceAccurate).count == 1
}
}

View File

@ -37,7 +37,7 @@ public struct XCTFailMessageRule: SwiftSyntaxRule, ConfigurationProviderRule {
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -1,5 +1,4 @@
import SwiftSyntax
import SwiftSyntaxBuilder
private let warnDeprecatedOnceImpl: Void = {
queuedPrintError("""
@ -45,7 +44,7 @@ public struct AnyObjectProtocolRule: SwiftSyntaxCorrectableRule, OptInRule, Conf
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
warnDeprecatedOnce()
return Visitor()
return Visitor(viewMode: .sourceAccurate)
}
public func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? {
@ -95,7 +94,7 @@ private extension AnyObjectProtocolRule {
return super.visit(
node.withTypeName(
TypeSyntax(
SimpleTypeIdentifierSyntax { $0.useName(.identifier("AnyObject")) }
SimpleTypeIdentifierSyntax(name: .identifier("AnyObject"), genericArgumentClause: nil)
.withLeadingTrivia(typeName.leadingTrivia ?? .zero)
.withTrailingTrivia(typeName.trailingTrivia ?? .zero)
)

View File

@ -52,7 +52,7 @@ public struct ArrayInitRule: SwiftSyntaxRule, ConfigurationProviderRule, OptInRu
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -32,7 +32,7 @@ public struct ClassDelegateProtocolRule: SwiftSyntaxRule, ConfigurationProviderR
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -15,7 +15,7 @@ public struct EmptyXCTestMethodRule: OptInRule, ConfigurationProviderRule, Swift
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
EmptyXCTestMethodRuleVisitor()
EmptyXCTestMethodRuleVisitor(viewMode: .sourceAccurate)
}
}

View File

@ -26,7 +26,7 @@ public struct UnownedVariableCaptureRule: SwiftSyntaxRule, OptInRule, Configurat
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
UnownedVariableCaptureRuleVisitor()
UnownedVariableCaptureRuleVisitor(viewMode: .sourceAccurate)
}
}
@ -38,6 +38,12 @@ private final class UnownedVariableCaptureRuleVisitor: SyntaxVisitor, Violations
violationPositions.append(token.positionAfterSkippingLeadingTrivia)
}
}
override func visitPost(_ node: TokenListSyntax) {
if case .contextualKeyword("unowned") = node.first?.tokenKind {
violationPositions.append(node.positionAfterSkippingLeadingTrivia)
}
}
}
private extension ClosureCaptureItemSyntax {

View File

@ -37,7 +37,7 @@ public struct YodaConditionRule: OptInRule, ConfigurationProviderRule, SwiftSynt
])
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
YodaConditionRuleVisitor()
YodaConditionRuleVisitor(viewMode: .sourceAccurate)
}
}
@ -65,7 +65,7 @@ private final class YodaConditionRuleVisitor: SyntaxVisitor, ViolationsSyntaxVis
}
private func visit(condition: ExprSyntax) {
guard let children = condition.as(SequenceExprSyntax.self)?.elements.children else {
guard let children = condition.as(SequenceExprSyntax.self)?.elements.children(viewMode: .sourceAccurate) else {
return
}
let comparisonOperators = children

View File

@ -15,7 +15,7 @@ public struct LargeTupleRule: SourceKitFreeRule, ConfigurationProviderRule {
)
public func validate(file: SwiftLintFile) -> [StyleViolation] {
LargeTupleRuleVisitor()
LargeTupleRuleVisitor(viewMode: .sourceAccurate)
.walk(file: file, handler: \.violationPositions)
.sorted(by: { $0.position < $1.position })
.compactMap { position, size in

View File

@ -25,7 +25,7 @@ public struct EmptyStringRule: ConfigurationProviderRule, OptInRule, SwiftSyntax
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -20,7 +20,7 @@ public struct FlatMapOverMapReduceRule: SwiftSyntaxRule, OptInRule, Configuratio
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -24,7 +24,7 @@ public struct ClosingBraceRule: SwiftSyntaxCorrectableRule, ConfigurationProvide
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
public func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? {

View File

@ -60,6 +60,7 @@ private final class ClosureSpacingRuleVisitor: SyntaxVisitor, ViolationsSyntaxVi
init(locationConverter: SourceLocationConverter) {
self.locationConverter = locationConverter
super.init(viewMode: .sourceAccurate)
}
override func visitPost(_ node: ClosureExprSyntax) {

View File

@ -32,7 +32,7 @@ public struct ColonRule: SubstitutionCorrectableRule, ConfigurationProviderRule,
return []
}
let visitor = ColonRuleVisitor()
let visitor = ColonRuleVisitor(viewMode: .sourceAccurate)
visitor.walk(syntaxTree)
let positionsToSkip = visitor.positionsToSkip
let dictionaryPositions = visitor.dictionaryPositions
@ -101,7 +101,7 @@ private final class ColonRuleVisitor: SyntaxVisitor {
override func visitPost(_ node: DeclNameArgumentsSyntax) {
positionsToSkip.append(
contentsOf: node.tokens
contentsOf: node.tokens(viewMode: .sourceAccurate)
.filter { $0.tokenKind == .colon }
.map(\.position)
)
@ -117,6 +117,10 @@ private final class ColonRuleVisitor: SyntaxVisitor {
positionsToSkip.append(node.colon.position)
}
override func visitPost(_ node: UnresolvedTernaryExprSyntax) {
positionsToSkip.append(node.colonMark.position)
}
override func visitPost(_ node: DictionaryElementSyntax) {
dictionaryPositions.append(node.colon.position)
}

View File

@ -77,7 +77,7 @@ public struct CommaInheritanceRule: OptInRule, SubstitutionCorrectableRule, Conf
}
public func violationRanges(in file: SwiftLintFile) -> [NSRange] {
let visitor = CommaInheritanceRuleVisitor()
let visitor = CommaInheritanceRuleVisitor(viewMode: .sourceAccurate)
return visitor.walk(file: file) { visitor -> [ByteRange] in
visitor.violationRanges
}.compactMap {
@ -90,7 +90,7 @@ private final class CommaInheritanceRuleVisitor: SyntaxVisitor {
private(set) var violationRanges: [ByteRange] = []
override func visitPost(_ node: InheritedTypeSyntax) {
for type in node.children {
for type in node.children(viewMode: .sourceAccurate) {
guard let composition = type.as(CompositionTypeSyntax.self) else {
continue
}

View File

@ -51,6 +51,7 @@ private final class ComputedAccessorsOrderRuleVisitor: SyntaxVisitor {
init(expectedOrder: ComputedAccessorsOrderRuleConfiguration.Order) {
self.expectedOrder = expectedOrder
super.init(viewMode: .sourceAccurate)
}
override func visitPost(_ node: AccessorBlockSyntax) {

View File

@ -15,7 +15,7 @@ public struct ImplicitGetterRule: ConfigurationProviderRule, SourceKitFreeRule {
)
public func validate(file: SwiftLintFile) -> [StyleViolation] {
ImplicitGetterRuleVisitor()
ImplicitGetterRuleVisitor(viewMode: .sourceAccurate)
.walk(file: file, handler: \.violationPositions)
.sorted { $0.position < $1.position }
.map { violation in

View File

@ -38,7 +38,7 @@ public struct MultipleClosuresWithTrailingClosureRule: SwiftSyntaxRule, Configur
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
}

View File

@ -126,6 +126,7 @@ private class OperatorUsageWhitespaceVisitor: SyntaxVisitor {
init(allowedNoSpaceOperators: [String]) {
self.allowedNoSpaceOperators = Set(allowedNoSpaceOperators)
super.init(viewMode: .sourceAccurate)
}
override func visitPost(_ node: BinaryOperatorExprSyntax) {
@ -162,6 +163,16 @@ private class OperatorUsageWhitespaceVisitor: SyntaxVisitor {
}
}
override func visitPost(_ node: UnresolvedTernaryExprSyntax) {
if let violation = violation(operatorToken: node.colonMark) {
violationRanges.append(violation)
}
if let violation = violation(operatorToken: node.questionMark) {
violationRanges.append(violation)
}
}
private func violation(operatorToken: TokenSyntax) -> (ByteRange, String)? {
guard let previousToken = operatorToken.previousToken,
let nextToken = operatorToken.nextToken else {
@ -216,8 +227,8 @@ private extension Trivia {
switch element {
case .blockComment, .docLineComment, .docBlockComment, .lineComment:
return true
case .carriageReturnLineFeeds, .carriageReturns, .formfeeds,
.garbageText, .newlines, .spaces, .verticalTabs, .tabs:
case .carriageReturnLineFeeds, .carriageReturns, .formfeeds, .newlines,
.shebang, .spaces, .tabs, .unexpectedText, .verticalTabs:
return false
}
}

View File

@ -74,12 +74,13 @@ private final class SelfBindingRuleVisitor: SyntaxVisitor, ViolationsSyntaxVisit
init(bindIdentifier: String) {
self.bindIdentifier = bindIdentifier
super.init(viewMode: .sourceAccurate)
}
override func visitPost(_ node: OptionalBindingConditionSyntax) {
if let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self),
identifierPattern.identifier.text != bindIdentifier,
let initializerIdentifier = node.initializer.value.as(IdentifierExprSyntax.self),
let initializerIdentifier = node.initializer?.value.as(IdentifierExprSyntax.self),
initializerIdentifier.identifier.text == "self" {
violationPositions.append(identifierPattern.positionAfterSkippingLeadingTrivia)
}
@ -103,7 +104,7 @@ private final class SelfBindingRuleRewriter: SyntaxRewriter, ViolationsSyntaxRew
override func visit(_ node: OptionalBindingConditionSyntax) -> Syntax {
guard let identifierPattern = node.pattern.as(IdentifierPatternSyntax.self),
identifierPattern.identifier.text != bindIdentifier,
let initializerIdentifier = node.initializer.value.as(IdentifierExprSyntax.self),
let initializerIdentifier = node.initializer?.value.as(IdentifierExprSyntax.self),
initializerIdentifier.identifier.text == "self" else {
return super.visit(node)
}

View File

@ -76,7 +76,7 @@ public struct UnneededParenthesesInClosureArgumentRule: ConfigurationProviderRul
)
public func makeVisitor(file: SwiftLintFile) -> ViolationsSyntaxVisitor? {
Visitor()
Visitor(viewMode: .sourceAccurate)
}
public func makeRewriter(file: SwiftLintFile) -> ViolationsSyntaxRewriter? {
@ -134,15 +134,15 @@ private final class Rewriter: SyntaxRewriter, ViolationsSyntaxRewriter {
}
let isLast = idx == clause.parameterList.count - 1
return SyntaxFactory.makeClosureParam(
return ClosureParamSyntax(
name: name,
trailingComma: isLast ? nil : SyntaxFactory.makeCommaToken(trailingTrivia: .spaces(1))
trailingComma: isLast ? nil : .commaToken(trailingTrivia: Trivia(pieces: [.spaces(1)]))
)
}
correctionPositions.append(clause.positionAfterSkippingLeadingTrivia)
let paramList = SyntaxFactory.makeClosureParamList(items).withTrailingTrivia(.spaces(1))
let paramList = ClosureParamListSyntax(items).withTrailingTrivia(.spaces(1))
return super.visit(node.withInput(Syntax(paramList)))
}
}

41
bazel/SwiftSyntax.BUILD Normal file
View File

@ -0,0 +1,41 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
cc_library(
name = "_CSwiftSyntax",
srcs = glob(["Sources/_CSwiftSyntax/src/*.c"]),
hdrs = glob(["Sources/_CSwiftSyntax/include/*.h"]),
linkstatic = True,
tags = ["swift_module"],
)
swift_library(
name = "SwiftSyntax",
srcs = glob(["Sources/SwiftSyntax/**/*.swift"]),
module_name = "SwiftSyntax",
private_deps = ["_CSwiftSyntax"],
visibility = ["//visibility:public"],
)
swift_library(
name = "SwiftDiagnostics",
srcs = glob(["Sources/SwiftDiagnostics/**/*.swift"]),
module_name = "SwiftDiagnostics",
visibility = ["//visibility:public"],
deps = [":SwiftSyntax"],
)
swift_library(
name = "SwiftParser",
srcs = glob(["Sources/SwiftParser/**/*.swift"]),
module_name = "SwiftParser",
visibility = ["//visibility:public"],
deps = [":SwiftSyntax", ":SwiftDiagnostics"],
)
swift_library(
name = "SwiftSyntaxBuilder",
srcs = glob(["Sources/SwiftSyntaxBuilder/**/*.swift"]),
module_name = "SwiftSyntaxBuilder",
visibility = ["//visibility:public"],
deps = [":SwiftSyntax"],
)

View File

@ -1,5 +1,4 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@com_github_keith_swift_syntax_bazel//:deps.bzl", "swift_syntax_deps")
load("@com_github_jpsim_sourcekitten//bazel:repos.bzl", "sourcekitten_repos")
def _default_extra_swift_sources_impl(ctx):
@ -27,5 +26,4 @@ def swiftlint_deps():
if not native.existing_rule("swiftlint_extra_rules"):
_default_extra_swift_sources(name = "swiftlint_extra_rules")
swift_syntax_deps()
sourcekitten_repos()

View File

@ -18,10 +18,11 @@ def swiftlint_repos():
)
http_archive(
name = "com_github_keith_swift_syntax_bazel",
sha256 = "f83b8449f84e29d263d2b0ceb9d2ae7f88c9f2a81f4b10035e94073664507507",
strip_prefix = "swift-syntax-bazel-13.3.13E113",
url = "https://github.com/keith/swift-syntax-bazel/archive/refs/tags/13.3.13E113.tar.gz",
name = "com_github_apple_swift_syntax",
sha256 = "ccb203b1b9fb482750735bbc94eb4394fa4dfa23783e1e0ca362e8539fc3f5d7",
build_file = "@SwiftLint//bazel:SwiftSyntax.BUILD",
strip_prefix = "swift-syntax-e6fa90ca5e47803439ab478d51ee1c833619e8f8",
url = "https://github.com/apple/swift-syntax/archive/e6fa90ca5e47803439ab478d51ee1c833619e8f8.tar.gz",
)
http_archive(