From dd320400b2b24d7b3c2af3d5181c29a55f64461f Mon Sep 17 00:00:00 2001 From: Paul Taykalo Date: Sun, 10 Nov 2019 21:15:58 +0200 Subject: [PATCH] Add own wrappers over syntax tokens and syntax map --- .../Extensions/Array+SwiftLint.swift | 6 ---- .../Extensions/SwiftLintFile+Cache.swift | 10 ++++--- .../Extensions/SwiftLintFile+Regex.swift | 19 ++++++------ .../SwiftLintSyntaxMap.swift} | 21 ++++++++----- .../Models/SwiftLintSyntaxToken.swift | 30 +++++++++++++++++++ .../Models/SwiftVersion.swift | 7 ++--- .../Idiomatic/DuplicateImportsRule.swift | 4 +-- .../Rules/Idiomatic/ForceUnwrappingRule.swift | 14 ++++----- .../Idiomatic/NoFallthroughOnlyRule.swift | 4 +-- .../PrivateOverFilePrivateRule.swift | 2 +- .../Rules/Idiomatic/TypeNameRule.swift | 8 ++--- .../Idiomatic/UnneededBreakInSwitchRule.swift | 4 +-- .../Idiomatic/UnusedEnumeratedRule.swift | 9 +++--- .../Rules/Lint/ArrayInitRule.swift | 20 ++++++------- .../Rules/Lint/DeploymentTargetRule.swift | 2 +- .../Rules/Lint/IdenticalOperandsRule.swift | 17 ++++++----- .../Rules/Lint/InertDeferRule.swift | 4 +-- .../Rules/Lint/MarkRule.swift | 2 +- .../NotificationCenterDetachmentRule.swift | 2 +- .../Rules/Lint/UnusedCaptureListRule.swift | 7 ++--- .../Lint/UnusedClosureParameterRule.swift | 4 +-- .../Lint/UnusedControlFlowLabelRule.swift | 2 +- .../Rules/Lint/UnusedDeclarationRule.swift | 2 +- .../Rules/Lint/UnusedImportRule.swift | 6 ++-- .../Rules/Lint/UnusedSetterValueRule.swift | 18 +++++------ .../Rules/Style/AttributesRule.swift | 14 ++++----- .../Rules/Style/ClosureSpacingRule.swift | 7 +++-- .../Rules/Style/ColonRule+Type.swift | 13 +++----- .../ConditionalReturnsOnNewlineRule.swift | 13 +++----- .../Rules/Style/FileHeaderRule.swift | 10 +++---- .../Rules/Style/ImplicitGetterRule.swift | 4 +-- .../Rules/Style/LetVarWhitespaceRule.swift | 6 ++-- .../Rules/Style/NumberSeparatorRule.swift | 11 ++----- .../Rules/Style/StatementPositionRule.swift | 3 +- .../Rules/Style/SwitchCaseOnNewlineRule.swift | 4 +-- ...ededParenthesesInClosureArgumentRule.swift | 6 ++-- SwiftLint.xcodeproj/project.pbxproj | 16 ++++++---- 37 files changed, 170 insertions(+), 161 deletions(-) rename Source/SwiftLintFramework/{Extensions/SyntaxMap+SwiftLint.swift => Models/SwiftLintSyntaxMap.swift} (55%) create mode 100644 Source/SwiftLintFramework/Models/SwiftLintSyntaxToken.swift diff --git a/Source/SwiftLintFramework/Extensions/Array+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/Array+SwiftLint.swift index 9a67bca5fe9..725e87e3b6a 100644 --- a/Source/SwiftLintFramework/Extensions/Array+SwiftLint.swift +++ b/Source/SwiftLintFramework/Extensions/Array+SwiftLint.swift @@ -8,12 +8,6 @@ extension Array where Element: NSTextCheckingResult { } } -extension Array where Element == SyntaxToken { - var kinds: [SyntaxKind] { - return compactMap { SyntaxKind(rawValue: $0.type) } - } -} - extension Array where Element: Equatable { var unique: [Element] { var uniqueValues = [Element]() diff --git a/Source/SwiftLintFramework/Extensions/SwiftLintFile+Cache.swift b/Source/SwiftLintFramework/Extensions/SwiftLintFile+Cache.swift index 140839bb508..e0c428eb3f2 100644 --- a/Source/SwiftLintFramework/Extensions/SwiftLintFile+Cache.swift +++ b/Source/SwiftLintFramework/Extensions/SwiftLintFile+Cache.swift @@ -24,7 +24,9 @@ private var structureDictionaryCache = Cache({ file in return structureCache.get(file).map { SourceKittenDictionary($0.dictionary) } }) -private var syntaxMapCache = Cache({ file in responseCache.get(file).map(SyntaxMap.init) }) +private var syntaxMapCache = Cache({ file in + responseCache.get(file).map { SwiftLintSyntaxMap(value: SyntaxMap(sourceKitResponse: $0)) } +}) private var syntaxKindsByLinesCache = Cache({ file in file.syntaxKindsByLine() }) private var syntaxTokensByLinesCache = Cache({ file in file.syntaxTokensByLine() }) @@ -145,18 +147,18 @@ extension SwiftLintFile { return structureDictionary } - internal var syntaxMap: SyntaxMap { + internal var syntaxMap: SwiftLintSyntaxMap { guard let syntaxMap = syntaxMapCache.get(self) else { if let handler = assertHandler { handler() - return SyntaxMap(data: []) + return SwiftLintSyntaxMap(value: SyntaxMap(data: [])) } queuedFatalError("Never call this for file that sourcekitd fails.") } return syntaxMap } - internal var syntaxTokensByLines: [[SyntaxToken]] { + internal var syntaxTokensByLines: [[SwiftLintSyntaxToken]] { guard let syntaxTokensByLines = syntaxTokensByLinesCache.get(self) else { if let handler = assertHandler { handler() diff --git a/Source/SwiftLintFramework/Extensions/SwiftLintFile+Regex.swift b/Source/SwiftLintFramework/Extensions/SwiftLintFile+Regex.swift index 47efcceac96..aeabf1ae150 100644 --- a/Source/SwiftLintFramework/Extensions/SwiftLintFile+Regex.swift +++ b/Source/SwiftLintFramework/Extensions/SwiftLintFile+Regex.swift @@ -95,7 +95,7 @@ extension SwiftLintFile { } internal func matchesAndTokens(matching pattern: String, - range: NSRange? = nil) -> [(NSTextCheckingResult, [SyntaxToken])] { + range: NSRange? = nil) -> [(NSTextCheckingResult, [SwiftLintSyntaxToken])] { let contents = self.contents.bridge() let range = range ?? NSRange(location: 0, length: contents.length) let syntax = syntaxMap @@ -115,7 +115,7 @@ extension SwiftLintFile { } internal func rangesAndTokens(matching pattern: String, - range: NSRange? = nil) -> [(NSRange, [SyntaxToken])] { + range: NSRange? = nil) -> [(NSRange, [SwiftLintSyntaxToken])] { return matchesAndTokens(matching: pattern, range: range).map { ($0.0.range, $0.1) } } @@ -149,17 +149,17 @@ extension SwiftLintFile { return results } - internal func syntaxTokensByLine() -> [[SyntaxToken]]? { + internal func syntaxTokensByLine() -> [[SwiftLintSyntaxToken]]? { if sourcekitdFailed { return nil } - var results = [[SyntaxToken]](repeating: [], count: lines.count + 1) + var results = [[SwiftLintSyntaxToken]](repeating: [], count: lines.count + 1) var tokenGenerator = syntaxMap.tokens.makeIterator() var lineGenerator = lines.makeIterator() var maybeLine = lineGenerator.next() var maybeToken = tokenGenerator.next() while let line = maybeLine, let token = maybeToken { - let tokenRange = NSRange(location: token.offset, length: token.length) + let tokenRange = token.range if NSLocationInRange(token.offset, line.byteRange) || NSLocationInRange(line.byteRange.location, tokenRange) { results[line.index].append(token) @@ -317,17 +317,16 @@ extension SwiftLintFile { return corrections } - internal func isACL(token: SyntaxToken) -> Bool { - guard SyntaxKind(rawValue: token.type) == .attributeBuiltin else { + internal func isACL(token: SwiftLintSyntaxToken) -> Bool { + guard token.kind == .attributeBuiltin else { return false } - let aclString = contents.bridge().substringWithByteRange(start: token.offset, - length: token.length) + let aclString = contents(for: token) return aclString.flatMap(AccessControlLevel.init(description:)) != nil } - internal func contents(for token: SyntaxToken) -> String? { + internal func contents(for token: SwiftLintSyntaxToken) -> String? { return contents.bridge().substringWithByteRange(start: token.offset, length: token.length) } diff --git a/Source/SwiftLintFramework/Extensions/SyntaxMap+SwiftLint.swift b/Source/SwiftLintFramework/Models/SwiftLintSyntaxMap.swift similarity index 55% rename from Source/SwiftLintFramework/Extensions/SyntaxMap+SwiftLint.swift rename to Source/SwiftLintFramework/Models/SwiftLintSyntaxMap.swift index 4f39409443d..e26653b510e 100644 --- a/Source/SwiftLintFramework/Extensions/SyntaxMap+SwiftLint.swift +++ b/Source/SwiftLintFramework/Models/SwiftLintSyntaxMap.swift @@ -1,17 +1,24 @@ import Foundation import SourceKittenFramework -extension SyntaxMap { +public struct SwiftLintSyntaxMap { + public let value: SyntaxMap + public let tokens: [SwiftLintSyntaxToken] + + public init(value: SyntaxMap) { + self.value = value + self.tokens = value.tokens.map(SwiftLintSyntaxToken.init) + } + /// Returns array of SyntaxTokens intersecting with byte range /// /// - Parameter byteRange: byte based NSRange - internal func tokens(inByteRange byteRange: NSRange) -> [SyntaxToken] { - func intersect(_ token: SyntaxToken) -> Bool { - return NSRange(location: token.offset, length: token.length) - .intersects(byteRange) + internal func tokens(inByteRange byteRange: NSRange) -> [SwiftLintSyntaxToken] { + func intersect(_ token: SwiftLintSyntaxToken) -> Bool { + return token.range.intersects(byteRange) } - func intersectsOrAfter(_ token: SyntaxToken) -> Bool { + func intersectsOrAfter(_ token: SwiftLintSyntaxToken) -> Bool { return token.offset + token.length > byteRange.location } @@ -29,6 +36,6 @@ extension SyntaxMap { } internal func kinds(inByteRange byteRange: NSRange) -> [SyntaxKind] { - return tokens(inByteRange: byteRange).kinds + return tokens(inByteRange: byteRange).compactMap { $0.kind } } } diff --git a/Source/SwiftLintFramework/Models/SwiftLintSyntaxToken.swift b/Source/SwiftLintFramework/Models/SwiftLintSyntaxToken.swift new file mode 100644 index 00000000000..a25eb84e9a2 --- /dev/null +++ b/Source/SwiftLintFramework/Models/SwiftLintSyntaxToken.swift @@ -0,0 +1,30 @@ +import Foundation +import SourceKittenFramework + +public struct SwiftLintSyntaxToken { + public let value: SyntaxToken + public let kind: SyntaxKind? + + public init(value: SyntaxToken) { + self.value = value + kind = SyntaxKind(rawValue: value.type) + } + + public var range: NSRange { + return NSRange(location: value.offset, length: value.length) + } + + public var offset: Int { + return value.offset + } + + public var length: Int { + return value.length + } +} + +extension Array where Element == SwiftLintSyntaxToken { + var kinds: [SyntaxKind] { + return compactMap { $0.kind } + } +} diff --git a/Source/SwiftLintFramework/Models/SwiftVersion.swift b/Source/SwiftLintFramework/Models/SwiftVersion.swift index 33fa85214db..8f2865da5d4 100644 --- a/Source/SwiftLintFramework/Models/SwiftVersion.swift +++ b/Source/SwiftLintFramework/Models/SwiftVersion.swift @@ -49,7 +49,7 @@ public extension SwiftVersion { if !Request.disableSourceKit, case let dynamicCallableFile = SwiftLintFile(contents: "@dynamicCallable"), - dynamicCallableFile.syntaxMap.tokens.compactMap({ SyntaxKind(rawValue: $0.type) }) == [.attributeID] { + dynamicCallableFile.syntaxMap.tokens.compactMap({ $0.kind }) == [.attributeID] { return .five } @@ -100,13 +100,10 @@ public extension SwiftVersion { let version = "3.0.0" #endif """) - func isString(token: SyntaxToken) -> Bool { - return token.type == SyntaxKind.string.rawValue - } if !Request.disableSourceKit, let decl = file.structureDictionary.kinds() .first(where: { $0.kind == SwiftDeclarationKind.varGlobal.rawValue }), - let token = file.syntaxMap.tokens(inByteRange: decl.byteRange).first(where: isString ) { + let token = file.syntaxMap.tokens(inByteRange: decl.byteRange).first(where: { $0.kind == .string }) { return .init(rawValue: file.contents.substring(from: token.offset + 1, length: token.length - 2)) } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/DuplicateImportsRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/DuplicateImportsRule.swift index a5bc4f7c311..ce62184ed60 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/DuplicateImportsRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/DuplicateImportsRule.swift @@ -26,8 +26,8 @@ public struct DuplicateImportsRule: ConfigurationProviderRule, AutomaticTestable let contents = file.contents.bridge() let ranges = file.syntaxMap.tokens - .filter { SyntaxKind(rawValue: $0.type) == .buildconfigKeyword } - .map { NSRange(location: $0.offset, length: $0.length) } + .filter { $0.kind == .buildconfigKeyword } + .map { $0.range } .filter { range in let keyword = contents.substringWithByteRange(start: range.location, length: range.length) return ["#if", "#endif"].contains(keyword) diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/ForceUnwrappingRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/ForceUnwrappingRule.swift index 180460dba29..3168535b1b7 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/ForceUnwrappingRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/ForceUnwrappingRule.swift @@ -108,7 +108,7 @@ public struct ForceUnwrappingRule: OptInRule, ConfigurationProviderRule, Automat } } - private func violationRange(match: NSTextCheckingResult, nsstring: NSString, syntaxMap: SyntaxMap, + private func violationRange(match: NSTextCheckingResult, nsstring: NSString, syntaxMap: SwiftLintSyntaxMap, file: SwiftLintFile) -> NSRange? { if match.numberOfRanges < 3 { return nil } @@ -155,18 +155,16 @@ public struct ForceUnwrappingRule: OptInRule, ConfigurationProviderRule, Automat } // check if first captured range is comment, string, typeidentifier, or a keyword that is not `self`. - private func isFirstRangeExcludedToken(byteRange: NSRange, syntaxMap: SyntaxMap, file: SwiftLintFile) -> Bool { + private func isFirstRangeExcludedToken(byteRange: NSRange, syntaxMap: SwiftLintSyntaxMap, + file: SwiftLintFile) -> Bool { let tokens = syntaxMap.tokens(inByteRange: byteRange) - let nsString = file.contents.bridge() return tokens.contains { token in - guard let kind = SyntaxKind(rawValue: token.type), + guard let kind = token.kind, ForceUnwrappingRule.excludingSyntaxKindsForFirstCapture.contains(kind) else { return false } // check for `self - guard kind == .keyword, - let nsRange = nsString.byteRangeToNSRange(start: token.offset, length: token.length) - else { return true } - return nsString.substring(with: nsRange) != "self" + guard kind == .keyword else { return true } + return file.contents(for: token) != "self" } } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/NoFallthroughOnlyRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/NoFallthroughOnlyRule.swift index ea2d0bdf088..e6fd0ca04b7 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/NoFallthroughOnlyRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/NoFallthroughOnlyRule.swift @@ -52,14 +52,14 @@ public struct NoFallthroughOnlyRule: ASTRule, ConfigurationProviderRule, Automat private func isNextTokenUnknownAttribute(afterOffset offset: Int, file: SwiftLintFile) -> Bool { let nextNonCommentToken = file.syntaxMap.tokens .first { token in - guard let kind = SyntaxKind(rawValue: token.type), !kind.isCommentLike else { + guard let kind = token.kind, !kind.isCommentLike else { return false } return token.offset > offset } - return (nextNonCommentToken?.type).flatMap(SyntaxKind.init(rawValue:)) == .attributeID && + return nextNonCommentToken?.kind == .attributeID && nextNonCommentToken.flatMap(file.contents(for:)) == "@unknown" } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift index 5b4c517bb4c..0082401afc0 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/PrivateOverFilePrivateRule.swift @@ -80,7 +80,7 @@ public struct PrivateOverFilePrivateRule: ConfigurationProviderRule, Substitutio let parts = syntaxTokens.prefix { offset > $0.offset } guard let lastKind = parts.last, - SyntaxKind(rawValue: lastKind.type) == .attributeBuiltin, + lastKind.kind == .attributeBuiltin, let aclName = contents.substringWithByteRange(start: lastKind.offset, length: lastKind.length), AccessControlLevel(description: aclName) == .fileprivate, let range = contents.byteRangeToNSRange(start: lastKind.offset, length: lastKind.length) else { diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/TypeNameRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/TypeNameRule.swift index 1828303db46..fb90052fe83 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/TypeNameRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/TypeNameRule.swift @@ -47,14 +47,12 @@ public struct TypeNameRule: ASTRule, ConfigurationProviderRule { guard tokens.count == 2, let keywordToken = tokens.first, let nameToken = tokens.last, - SyntaxKind(rawValue: keywordToken.type) == .keyword, - SyntaxKind(rawValue: nameToken.type) == .identifier else { + keywordToken.kind == .keyword, + nameToken.kind == .identifier else { return [] } - let contents = file.contents.bridge() - guard let name = contents.substringWithByteRange(start: nameToken.offset, - length: nameToken.length) else { + guard let name = file.contents(for: nameToken) else { return [] } diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/UnneededBreakInSwitchRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/UnneededBreakInSwitchRule.swift index 90ddef00bfe..3c9c06aa4cb 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/UnneededBreakInSwitchRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/UnneededBreakInSwitchRule.swift @@ -46,7 +46,7 @@ public struct UnneededBreakInSwitchRule: ConfigurationProviderRule, AutomaticTes let caseRange = NSRange(location: caseOffset, length: caseLength) let tokens = file.syntaxMap.tokens(inByteRange: caseRange).filter { token in - guard let kind = SyntaxKind(rawValue: token.type), + guard let kind = token.kind, token.offset > lastPatternEnd else { return false } @@ -61,7 +61,7 @@ public struct UnneededBreakInSwitchRule: ConfigurationProviderRule, AutomaticTes // is the `break` found the last (non-comment) token inside `case`? guard let lastValidToken = tokens.last, - SyntaxKind(rawValue: lastValidToken.type) == .keyword, + lastValidToken.kind == .keyword, lastValidToken.offset == byteRange.location, lastValidToken.length == byteRange.length else { return nil diff --git a/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift b/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift index efc361bef26..f08bae866c0 100644 --- a/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift +++ b/Source/SwiftLintFramework/Rules/Idiomatic/UnusedEnumeratedRule.swift @@ -62,9 +62,9 @@ public struct UnusedEnumeratedRule: ASTRule, ConfigurationProviderRule, Automati ] } - private func isTokenUnderscore(_ token: SyntaxToken, file: SwiftLintFile) -> Bool { + private func isTokenUnderscore(_ token: SwiftLintSyntaxToken, file: SwiftLintFile) -> Bool { return token.length == 1 && - SyntaxKind(rawValue: token.type) == .keyword && + token.kind == .keyword && isUnderscore(file: file, token: token) } @@ -97,8 +97,7 @@ public struct UnusedEnumeratedRule: ASTRule, ConfigurationProviderRule, Automati return nil } - private func isUnderscore(file: SwiftLintFile, token: SyntaxToken) -> Bool { - let contents = file.contents.bridge() - return contents.substringWithByteRange(start: token.offset, length: token.length) == "_" + private func isUnderscore(file: SwiftLintFile, token: SwiftLintSyntaxToken) -> Bool { + return file.contents(for: token) == "_" } } diff --git a/Source/SwiftLintFramework/Rules/Lint/ArrayInitRule.swift b/Source/SwiftLintFramework/Rules/Lint/ArrayInitRule.swift index 991c0f3f43f..7230ee161ac 100644 --- a/Source/SwiftLintFramework/Rules/Lint/ArrayInitRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/ArrayInitRule.swift @@ -57,7 +57,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto let range = NSRange(location: bodyOffset, length: bodyLength) let tokens = file.syntaxMap.tokens(inByteRange: range).filter { token in - guard let kind = SyntaxKind(rawValue: token.type) else { + guard let kind = token.kind else { return false } @@ -83,7 +83,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto ] } - private func isClosureParameter(firstToken: SyntaxToken, + private func isClosureParameter(firstToken: SwiftLintSyntaxToken, nameEndPosition: Int, file: SwiftLintFile) -> Bool { let length = firstToken.offset - nameEndPosition @@ -97,7 +97,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto return pattern.firstMatch(in: file.contents, options: .anchored, range: byteRange) != nil } - private func containsTrailingContent(lastToken: SyntaxToken, + private func containsTrailingContent(lastToken: SwiftLintSyntaxToken, bodyEndPosition: Int, file: SwiftLintFile) -> Bool { let lastTokenEnd = lastToken.offset + lastToken.length @@ -106,14 +106,14 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto return containsContent(inByteRange: remainingRange, file: file) } - private func containsLeadingContent(tokens: [SyntaxToken], + private func containsLeadingContent(tokens: [SwiftLintSyntaxToken], bodyStartPosition: Int, file: SwiftLintFile) -> Bool { let inTokenPosition = tokens.firstIndex(where: { token in - SyntaxKind(rawValue: token.type) == .keyword && file.contents(for: token) == "in" + token.kind == .keyword && file.contents(for: token) == "in" }) - let firstToken: SyntaxToken + let firstToken: SwiftLintSyntaxToken let start: Int if let position = inTokenPosition { let index = tokens.index(after: position) @@ -136,7 +136,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto let ranges = NSMutableIndexSet(indexesIn: byteRange) for token in remainingTokens { - ranges.remove(in: NSRange(location: token.offset, length: token.length)) + ranges.remove(in: token.range) } var containsContent = false @@ -158,7 +158,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto return containsContent } - private func isShortParameterStyleViolation(file: SwiftLintFile, tokens: [SyntaxToken]) -> Bool { + private func isShortParameterStyleViolation(file: SwiftLintFile, tokens: [SwiftLintSyntaxToken]) -> Bool { let kinds = tokens.kinds switch kinds { case [.identifier]: @@ -174,7 +174,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto } private func isParameterStyleViolation(file: SwiftLintFile, dictionary: SourceKittenDictionary, - tokens: [SyntaxToken]) -> Bool { + tokens: [SwiftLintSyntaxToken]) -> Bool { let parameters = dictionary.enclosedVarParameters guard parameters.count == 1, let offset = parameters[0].offset, @@ -185,7 +185,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto let parameterEnd = offset + length let tokens = Array(tokens.filter { $0.offset >= parameterEnd }.drop { token in - let isKeyword = SyntaxKind(rawValue: token.type) == .keyword + let isKeyword = token.kind == .keyword return !isKeyword || file.contents(for: token) != "in" }) diff --git a/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift b/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift index 4d49b43548b..1f5afed1569 100644 --- a/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/DeploymentTargetRule.swift @@ -52,7 +52,7 @@ public struct DeploymentTargetRule: ConfigurationProviderRule { return file.rangesAndTokens(matching: pattern).flatMap { range, tokens -> [StyleViolation] in guard let availabilityToken = tokens.first, - SyntaxKind(rawValue: availabilityToken.type) == .keyword, + availabilityToken.kind == .keyword, let tokenRange = file.contents.bridge().byteRangeToNSRange(start: availabilityToken.offset, length: availabilityToken.length) else { return [] diff --git a/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift b/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift index 9568dabee4c..177304bc567 100644 --- a/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/IdenticalOperandsRule.swift @@ -57,7 +57,7 @@ public struct IdenticalOperandsRule: ConfigurationProviderRule, OptInRule, Autom let index: Int // tokens in this operand - let tokens: [SyntaxToken] + let tokens: [SwiftLintSyntaxToken] } public func validate(file: SwiftLintFile) -> [StyleViolation] { @@ -104,7 +104,7 @@ public struct IdenticalOperandsRule: ConfigurationProviderRule, OptInRule, Autom } // Make sure both operands have same token types - guard leftOperand.tokens.map({ $0.type }) == rightOperand.tokens.map({ $0.type }) else { + guard leftOperand.tokens.map({ $0.value.type }) == rightOperand.tokens.map({ $0.value.type }) else { return nil } @@ -173,24 +173,27 @@ private extension NSString { return NSRangeToByteRange(start: range.location, length: range.length) } - func subStringWithSyntaxToken(_ syntaxToken: SyntaxToken) -> String? { + func subStringWithSyntaxToken(_ syntaxToken: SwiftLintSyntaxToken) -> String? { return substringWithByteRange(start: syntaxToken.offset, length: syntaxToken.length) } - func subStringBetweenTokens(_ startToken: SyntaxToken, _ endToken: SyntaxToken) -> String? { + func subStringBetweenTokens(_ startToken: SwiftLintSyntaxToken, _ endToken: SwiftLintSyntaxToken) -> String? { return substringWithByteRange(start: startToken.offset + startToken.length, length: endToken.offset - startToken.offset - startToken.length) } - func isDotOrOptionalChainingBetweenTokens(_ startToken: SyntaxToken, _ endToken: SyntaxToken) -> Bool { + func isDotOrOptionalChainingBetweenTokens(_ startToken: SwiftLintSyntaxToken, + _ endToken: SwiftLintSyntaxToken) -> Bool { return isRegexBetweenTokens(startToken, "[\\?!]?\\.", endToken) } - func isNilCoalecingOperatorBetweenTokens(_ startToken: SyntaxToken, _ endToken: SyntaxToken) -> Bool { + func isNilCoalecingOperatorBetweenTokens(_ startToken: SwiftLintSyntaxToken, + _ endToken: SwiftLintSyntaxToken) -> Bool { return isRegexBetweenTokens(startToken, "\\?\\?", endToken) } - func isRegexBetweenTokens(_ startToken: SyntaxToken, _ regexString: String, _ endToken: SyntaxToken) -> Bool { + func isRegexBetweenTokens(_ startToken: SwiftLintSyntaxToken, _ regexString: String, + _ endToken: SwiftLintSyntaxToken) -> Bool { guard let betweenTokens = subStringBetweenTokens(startToken, endToken) else { return false } let range = NSRange(location: 0, length: betweenTokens.utf16.count) diff --git a/Source/SwiftLintFramework/Rules/Lint/InertDeferRule.swift b/Source/SwiftLintFramework/Rules/Lint/InertDeferRule.swift index 51f85ea0182..b7555e69448 100644 --- a/Source/SwiftLintFramework/Rules/Lint/InertDeferRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/InertDeferRule.swift @@ -80,8 +80,8 @@ private func isBrace(offset: Int, element: (kind: String, byteRange: NSRange)) - return StatementKind(rawValue: element.kind) == .brace } -private func isNotComment(token: SyntaxToken) -> Bool { - guard let kind = SyntaxKind(rawValue: token.type) else { +private func isNotComment(token: SwiftLintSyntaxToken) -> Bool { + guard let kind = token.kind else { return false } diff --git a/Source/SwiftLintFramework/Rules/Lint/MarkRule.swift b/Source/SwiftLintFramework/Rules/Lint/MarkRule.swift index cdf881e26e5..b3fe0e844a0 100644 --- a/Source/SwiftLintFramework/Rules/Lint/MarkRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/MarkRule.swift @@ -185,7 +185,7 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule { private func violationRanges(in file: SwiftLintFile, matching pattern: String) -> [NSRange] { let nsstring = file.contents.bridge() return file.rangesAndTokens(matching: pattern).filter { _, syntaxTokens in - guard let syntaxKind = SyntaxKind(rawValue: syntaxTokens[0].type) else { + guard let syntaxKind = syntaxTokens.first?.kind else { return false } return !syntaxTokens.isEmpty && SyntaxKind.commentKinds.contains(syntaxKind) diff --git a/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift b/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift index cccbdae999d..50080ef260f 100644 --- a/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/NotificationCenterDetachmentRule.swift @@ -64,7 +64,7 @@ public struct NotificationCenterDetachmentRule: ASTRule, ConfigurationProviderRu return false } - let body = file.contents.bridge().substringWithByteRange(start: token.offset, length: token.length) + let body = file.contents(for: token) return body == "self" } } diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift index 05d2f217776..42b42671faf 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift @@ -132,14 +132,11 @@ public struct UnusedCaptureListRule: ASTRule, ConfigurationProviderRule, Automat } private func identifierStrings(in file: SwiftLintFile, byteRange: NSRange) -> Set { - let contents = file.contents.bridge() let identifiers = file.syntaxMap .tokens(inByteRange: byteRange) .compactMap { token -> String? in - guard token.type == SyntaxKind.identifier.rawValue || token.type == SyntaxKind.keyword.rawValue, - let range = contents.byteRangeToNSRange(start: token.offset, length: token.length) - else { return nil } - return contents.substring(with: range) + guard token.kind == .identifier || token.kind == .keyword else { return nil } + return file.contents(for: token) } return Set(identifiers) } diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift index cffe7bd548a..be68bdbaead 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedClosureParameterRule.swift @@ -160,8 +160,8 @@ public struct UnusedClosureParameterRule: SubstitutionCorrectableASTRule, Config } let token = tokens.first(where: { token -> Bool in - return (SyntaxKind(rawValue: token.type) == .identifier - || (SyntaxKind(rawValue: token.type) == .keyword && name == "self")) && + return (token.kind == .identifier + || (token.kind == .keyword && name == "self")) && token.offset == byteRange.location && token.length == byteRange.length }) diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift index d59b564cdbe..87f0ccc3c96 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedControlFlowLabelRule.swift @@ -118,7 +118,7 @@ public struct UnusedControlFlowLabelRule: SubstitutionCorrectableASTRule, Config case let byteRange = NSRange(location: offset, length: length), case let tokens = file.syntaxMap.tokens(inByteRange: byteRange), let firstToken = tokens.first, - SyntaxKind(rawValue: firstToken.type) == .identifier, + firstToken.kind == .identifier, let tokenContent = file.contents(for: firstToken), case let contents = file.contents.bridge(), let range = contents.byteRangeToNSRange(start: offset, length: length) else { diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift index 81ac5fcbe00..ee50faa9453 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift @@ -135,7 +135,7 @@ private extension SwiftLintFile { return syntaxMap.tokens .compactMap { token in - guard let kind = SyntaxKind(rawValue: token.type), !syntaxKindsToSkip.contains(kind) else { + guard let kind = token.kind, !syntaxKindsToSkip.contains(kind) else { return nil } diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedImportRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedImportRule.swift index c0504efc1f3..49583cd36a5 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedImportRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedImportRule.swift @@ -173,12 +173,10 @@ private extension SwiftLintFile { var nextIsModuleImport = false let tokens = syntaxMap.tokens for token in tokens { - guard let tokenKind = SyntaxKind(rawValue: token.type) else { + guard let tokenKind = token.kind else { continue } - if tokenKind == .keyword, - let substring = contentsNSString.substringWithByteRange(start: token.offset, length: token.length), - substring == "import" { + if tokenKind == .keyword, contents(for: token) == "import" { nextIsModuleImport = true continue } diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift index 7bd5d4512de..a6882f9f8b2 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedSetterValueRule.swift @@ -156,10 +156,10 @@ public struct UnusedSetterValueRule: ConfigurationProviderRule, AutomaticTestabl } } - private func findNamedArgument(after token: SyntaxToken, - file: SwiftLintFile) -> (name: String, token: SyntaxToken)? { + private func findNamedArgument(after token: SwiftLintSyntaxToken, + file: SwiftLintFile) -> (name: String, token: SwiftLintSyntaxToken)? { guard let firstToken = file.syntaxMap.tokens.first(where: { $0.offset > token.offset }), - SyntaxKind(rawValue: firstToken.type) == .identifier else { + firstToken.kind == .identifier else { return nil } @@ -174,7 +174,7 @@ public struct UnusedSetterValueRule: ConfigurationProviderRule, AutomaticTestabl } private func findGetToken(in range: NSRange, file: SwiftLintFile, - propertyStructure: SourceKittenDictionary) -> SyntaxToken? { + propertyStructure: SourceKittenDictionary) -> SwiftLintSyntaxToken? { let getTokens = file.rangesAndTokens(matching: "\\bget\\b", range: range).keywordTokens() return getTokens.first(where: { token -> Bool in // the last element is the deepest structure @@ -223,14 +223,12 @@ public struct UnusedSetterValueRule: ConfigurationProviderRule, AutomaticTestabl } } -private extension Array where Element == (NSRange, [SyntaxToken]) { - func keywordTokens() -> [SyntaxToken] { +private extension Array where Element == (NSRange, [SwiftLintSyntaxToken]) { + func keywordTokens() -> [SwiftLintSyntaxToken] { return compactMap { _, tokens in - guard let token = tokens.last, - SyntaxKind(rawValue: token.type) == .keyword else { - return nil + guard let token = tokens.last, token.kind == .keyword else { + return nil } - return token } } diff --git a/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift b/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift index 0a0b3ed6768..ff5e3fa1c9e 100644 --- a/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/AttributesRule.swift @@ -202,9 +202,8 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule { // check if it's a line with other declaration which could have its own attributes let nonAttributeTokens = tokens.filter { token in - guard SyntaxKind(rawValue: token.type) == .keyword, - let keyword = contents.substringWithByteRange(start: token.offset, - length: token.length) else { + guard token.kind == .keyword, + let keyword = file.contents(for: token) else { return false } @@ -260,15 +259,14 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule { return true } - private func attributeName(token: SyntaxToken, file: SwiftLintFile) -> (String, NSRange)? { - guard SyntaxKind(rawValue: token.type) == .attributeBuiltin else { + private func attributeName(token: SwiftLintSyntaxToken, file: SwiftLintFile) -> (String, NSRange)? { + guard token.kind == .attributeBuiltin else { return nil } - let maybeName = file.contents.bridge().substringWithByteRange(start: token.offset, - length: token.length) + let maybeName = file.contents(for: token) if let name = maybeName, isAttribute(name) { - return (name, NSRange(location: token.offset, length: token.length)) + return (name, token.range) } return nil diff --git a/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift b/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift index 35e318be031..af47f14ba4d 100644 --- a/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ClosureSpacingRule.swift @@ -73,7 +73,7 @@ public struct ClosureSpacingRule: CorrectableRule, ConfigurationProviderRule, Op let nsstring = file.contents.bridge() let bracePattern = regex("\\{|\\}") let linesTokens = file.syntaxTokensByLines - let kindsToExclude = SyntaxKind.commentAndStringKinds.map { $0.rawValue } + let kindsToExclude = SyntaxKind.commentAndStringKinds // find all lines and occurences of open { and closed } braces var linesWithBraces = [[NSRange]]() @@ -85,7 +85,10 @@ public struct ClosureSpacingRule: CorrectableRule, ConfigurationProviderRule, Op let braces = bracePattern.matches(in: file.contents, options: [], range: nsrange).map { $0.range } // filter out braces in comments and strings - let tokens = linesTokens[eachLine.index].filter { kindsToExclude.contains($0.type) } + let tokens = linesTokens[eachLine.index].filter { + guard let tokenKind = $0.kind else { return false } + return kindsToExclude.contains(tokenKind) + } let tokenRanges = tokens.compactMap { file.contents.bridge().byteRangeToNSRange(start: $0.offset, length: $0.length) } diff --git a/Source/SwiftLintFramework/Rules/Style/ColonRule+Type.swift b/Source/SwiftLintFramework/Rules/Style/ColonRule+Type.swift index 39e08e3acf4..00cd000dfd4 100644 --- a/Source/SwiftLintFramework/Rules/Style/ColonRule+Type.swift +++ b/Source/SwiftLintFramework/Rules/Style/ColonRule+Type.swift @@ -38,7 +38,7 @@ internal extension ColonRule { } } - private func isValidMatch(syntaxTokens: [SyntaxToken], file: SwiftLintFile) -> Bool { + private func isValidMatch(syntaxTokens: [SwiftLintSyntaxToken], file: SwiftLintFile) -> Bool { let syntaxKinds = syntaxTokens.kinds guard syntaxKinds.count == 2 else { @@ -55,7 +55,7 @@ internal extension ColonRule { validKinds = file.isTypeLike(token: syntaxTokens[1]) //Exclude explicit "Self" type because of static variables if syntaxKinds[0] == .identifier, - file.getTokenText(token: syntaxTokens[1]) == "Self" { + file.contents(for: syntaxTokens[1]) == "Self" { validKinds = false } case (.keyword, .typeidentifier): @@ -73,17 +73,12 @@ internal extension ColonRule { } private extension SwiftLintFile { - func isTypeLike(token: SyntaxToken) -> Bool { - guard let text = getTokenText(token: token), + func isTypeLike(token: SwiftLintSyntaxToken) -> Bool { + guard let text = contents(for: token), let firstLetter = text.unicodeScalars.first else { return false } return CharacterSet.uppercaseLetters.contains(firstLetter) } - - func getTokenText(token: SyntaxToken) -> String? { - let nsstring = contents.bridge() - return nsstring.substringWithByteRange(start: token.offset, length: token.length) - } } diff --git a/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift b/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift index 627ae062337..5f8965858c1 100644 --- a/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ConditionalReturnsOnNewlineRule.swift @@ -34,22 +34,17 @@ public struct ConditionalReturnsOnNewlineRule: ConfigurationProviderRule, Rule, return file.rangesAndTokens(matching: pattern).filter { _, tokens in guard let firstToken = tokens.first, let lastToken = tokens.last, - SyntaxKind(rawValue: firstToken.type) == .keyword && - SyntaxKind(rawValue: lastToken.type) == .keyword else { - return false + firstToken.kind == .keyword && lastToken.kind == .keyword else { + return false } let searchTokens = configuration.ifOnly ? ["if"] : ["if", "guard"] - return searchTokens.contains(content(for: firstToken, file: file)) && - content(for: lastToken, file: file) == "return" + return searchTokens.contains(file.contents(for: firstToken) ?? "") && + file.contents(for: lastToken) == "return" }.map { StyleViolation(ruleDescription: type(of: self).description, severity: configuration.severityConfiguration.severity, location: Location(file: file, characterOffset: $0.0.location)) } } - - private func content(for token: SyntaxToken, file: SwiftLintFile) -> String { - return file.contents.bridge().substringWithByteRange(start: token.offset, length: token.length) ?? "" - } } diff --git a/Source/SwiftLintFramework/Rules/Style/FileHeaderRule.swift b/Source/SwiftLintFramework/Rules/Style/FileHeaderRule.swift index 253e8d986ba..63f6188a125 100644 --- a/Source/SwiftLintFramework/Rules/Style/FileHeaderRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/FileHeaderRule.swift @@ -34,12 +34,12 @@ public struct FileHeaderRule: ConfigurationProviderRule, OptInRule { private static let reason = "Header comments should be consistent with project patterns." public func validate(file: SwiftLintFile) -> [StyleViolation] { - var firstToken: SyntaxToken? - var lastToken: SyntaxToken? - var firstNonCommentToken: SyntaxToken? + var firstToken: SwiftLintSyntaxToken? + var lastToken: SwiftLintSyntaxToken? + var firstNonCommentToken: SwiftLintSyntaxToken? for token in file.syntaxTokensByLines.lazy.joined() { - guard let kind = SyntaxKind(rawValue: token.type), kind.isFileHeaderKind else { + guard let kind = token.kind, kind.isFileHeaderKind else { // found a token that is not a comment, which means it's not the top of the file // so we can just skip the remaining tokens firstNonCommentToken = token @@ -97,7 +97,7 @@ public struct FileHeaderRule: ConfigurationProviderRule, OptInRule { } } - private func isSwiftLintCommand(token: SyntaxToken, file: SwiftLintFile) -> Bool { + private func isSwiftLintCommand(token: SwiftLintSyntaxToken, file: SwiftLintFile) -> Bool { guard let range = file.contents.bridge().byteRangeToNSRange(start: token.offset, length: token.length) else { return false diff --git a/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift b/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift index ccbd30473b6..7647eb792af 100644 --- a/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/ImplicitGetterRule.swift @@ -178,10 +178,10 @@ public struct ImplicitGetterRule: ConfigurationProviderRule, AutomaticTestableRu public func validate(file: SwiftLintFile) -> [StyleViolation] { let pattern = "\\{[^\\{]*?\\s+get\\b" let attributesKinds: Set = [.attributeBuiltin, .attributeID] - let getTokens: [SyntaxToken] = file.rangesAndTokens(matching: pattern).compactMap { _, tokens in + let getTokens: [SwiftLintSyntaxToken] = file.rangesAndTokens(matching: pattern).compactMap { _, tokens in let kinds = tokens.kinds guard let token = tokens.last, - SyntaxKind(rawValue: token.type) == .keyword, + token.kind == .keyword, attributesKinds.isDisjoint(with: kinds) else { return nil } diff --git a/Source/SwiftLintFramework/Rules/Style/LetVarWhitespaceRule.swift b/Source/SwiftLintFramework/Rules/Style/LetVarWhitespaceRule.swift index 81e46380c48..ac9532f5c5f 100644 --- a/Source/SwiftLintFramework/Rules/Style/LetVarWhitespaceRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/LetVarWhitespaceRule.swift @@ -185,8 +185,8 @@ public struct LetVarWhitespaceRule: ConfigurationProviderRule, OptInRule, Automa var result = Set() let syntaxMap = file.syntaxMap - for token in syntaxMap.tokens where token.type == SyntaxKind.comment.rawValue || - token.type == SyntaxKind.docComment.rawValue { + for token in syntaxMap.tokens where token.kind == .comment || + token.kind == .docComment { let startLine = file.line(byteOffset: token.offset) let endLine = file.line(byteOffset: token.offset + token.length) @@ -209,7 +209,7 @@ public struct LetVarWhitespaceRule: ConfigurationProviderRule, OptInRule, Automa // other than let/var private func attributeLineNumbers(file: SwiftLintFile) -> Set { return Set(file.syntaxMap.tokens.compactMap({ token in - if token.type == SyntaxKind.attributeBuiltin.rawValue { + if token.kind == .attributeBuiltin { return file.line(byteOffset: token.offset) } return nil diff --git a/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift b/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift index 46ed1045911..f5719043041 100644 --- a/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/NumberSeparatorRule.swift @@ -29,10 +29,10 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv } private func violatingRanges(in file: SwiftLintFile) -> [(NSRange, String)] { - let numberTokens = file.syntaxMap.tokens.filter { SyntaxKind(rawValue: $0.type) == .number } - return numberTokens.compactMap { (token: SyntaxToken) -> (NSRange, String)? in + let numberTokens = file.syntaxMap.tokens.filter { $0.kind == .number } + return numberTokens.compactMap { (token: SwiftLintSyntaxToken) -> (NSRange, String)? in guard - let content = contentFrom(file: file, token: token), + let content = file.contents(for: token), isDecimal(number: content), !isInValidRanges(number: content) else { @@ -159,9 +159,4 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv return Array(collection) } - - private func contentFrom(file: SwiftLintFile, token: SyntaxToken) -> String? { - return file.contents.bridge().substringWithByteRange(start: token.offset, - length: token.length) - } } diff --git a/Source/SwiftLintFramework/Rules/Style/StatementPositionRule.swift b/Source/SwiftLintFramework/Rules/Style/StatementPositionRule.swift index 1119a6b639e..b90a228fe89 100644 --- a/Source/SwiftLintFramework/Rules/Style/StatementPositionRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/StatementPositionRule.swift @@ -160,7 +160,8 @@ private extension StatementPositionRule { } } - static func uncuddledMatchFilter(contents: String, syntaxMap: SyntaxMap) -> ((NSTextCheckingResult) -> Bool) { + static func uncuddledMatchFilter(contents: String, + syntaxMap: SwiftLintSyntaxMap) -> ((NSTextCheckingResult) -> Bool) { return { match in let range = match.range guard let matchRange = contents.bridge().NSRangeToByteRange(start: range.location, diff --git a/Source/SwiftLintFramework/Rules/Style/SwitchCaseOnNewlineRule.swift b/Source/SwiftLintFramework/Rules/Style/SwitchCaseOnNewlineRule.swift index e006143ebee..bea2c6d268b 100644 --- a/Source/SwiftLintFramework/Rules/Style/SwitchCaseOnNewlineRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/SwitchCaseOnNewlineRule.swift @@ -74,9 +74,9 @@ public struct SwitchCaseOnNewlineRule: ASTRule, ConfigurationProviderRule, OptIn ] } - private func firstNonCommentToken(inByteRange byteRange: NSRange, file: SwiftLintFile) -> SyntaxToken? { + private func firstNonCommentToken(inByteRange byteRange: NSRange, file: SwiftLintFile) -> SwiftLintSyntaxToken? { return file.syntaxMap.tokens(inByteRange: byteRange).first { token -> Bool in - guard let kind = SyntaxKind(rawValue: token.type) else { + guard let kind = token.kind else { return false } diff --git a/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift b/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift index e32bc5f116c..639ceb0fcfb 100644 --- a/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift +++ b/Source/SwiftLintFramework/Rules/Style/UnneededParenthesesInClosureArgumentRule.swift @@ -84,13 +84,11 @@ public struct UnneededParenthesesInClosureArgumentRule: ConfigurationProviderRul let parametersTokens = file.syntaxMap.tokens(inByteRange: parametersByteRange) let parametersAreValid = parametersTokens.allSatisfy { token in - let kind = SyntaxKind(rawValue: token.type) - if kind == .identifier { + if token.kind == .identifier { return true } - return kind == .keyword && - file.contents.bridge().substringWithByteRange(start: token.offset, length: token.length) == "_" + return token.kind == .keyword && file.contents(for: token) == "_" } let inKinds = Set(file.syntaxMap.kinds(inByteRange: inByteRange)) diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj index 3b9ae6be164..edf52e8d215 100644 --- a/SwiftLint.xcodeproj/project.pbxproj +++ b/SwiftLint.xcodeproj/project.pbxproj @@ -135,7 +135,6 @@ 6C1D763221A4E69600DEF783 /* Request+DisableSourceKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C1D763121A4E69600DEF783 /* Request+DisableSourceKit.swift */; }; 6C7045441C6ADA450003F15A /* SourceKitCrashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */; }; 6CB8A80C1D11A7E10052816E /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E101B07A3EC003E02D0 /* Commandant.framework */; }; - 6CC4259B1C77046200AEA885 /* SyntaxMap+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC4259A1C77046200AEA885 /* SyntaxMap+SwiftLint.swift */; }; 6CCFCF2A1CFEF729003239EB /* Commandant.framework in Embed Frameworks into SwiftLintFramework.framework */ = {isa = PBXBuildFile; fileRef = E8BA7E101B07A3EC003E02D0 /* Commandant.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 6CCFCF2D1CFEF731003239EB /* SourceKittenFramework.framework in Embed Frameworks into SwiftLintFramework.framework */ = {isa = PBXBuildFile; fileRef = E876BFBD1B07828500114ED5 /* SourceKittenFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 6CCFCF2E1CFEF73A003239EB /* SWXMLHash.framework in Embed Frameworks into SwiftLintFramework.framework */ = {isa = PBXBuildFile; fileRef = E8C0DFCC1AD349DB007EE3D4 /* SWXMLHash.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -361,8 +360,10 @@ D93DA3D11E699E6300809827 /* NestingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93DA3CF1E699E4E00809827 /* NestingConfiguration.swift */; }; DAD3BE4A1D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD3BE491D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift */; }; E315B83C1DFA4BC500621B44 /* DynamicInlineRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */; }; - E4A6CF752363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A6CF742363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift */; }; + E48F715E23789824003E1775 /* SwiftLintSyntaxMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E48F715C23789823003E1775 /* SwiftLintSyntaxMap.swift */; }; + E48F715F23789824003E1775 /* SwiftLintSyntaxToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = E48F715D23789824003E1775 /* SwiftLintSyntaxToken.swift */; }; E4A365D223653649003B4141 /* SourceKittenDictionary+Swiftlint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A365D123653648003B4141 /* SourceKittenDictionary+Swiftlint.swift */; }; + E4A6CF752363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A6CF742363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift */; }; E4EA064C23688EB5002531D7 /* SwiftLintFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */; }; E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */; }; E802ED001C56A56000A35AE1 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = E802ECFF1C56A56000A35AE1 /* Benchmark.swift */; }; @@ -622,7 +623,6 @@ 6C1D763121A4E69600DEF783 /* Request+DisableSourceKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Request+DisableSourceKit.swift"; sourceTree = ""; }; 6C27B5FC2079D33F00353E17 /* Mac-XCTest.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Mac-XCTest.xcconfig"; sourceTree = ""; }; 6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceKitCrashTests.swift; sourceTree = ""; }; - 6CC4259A1C77046200AEA885 /* SyntaxMap+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SyntaxMap+SwiftLint.swift"; sourceTree = ""; }; 725094881D0855760039B353 /* StatementModeConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementModeConfiguration.swift; sourceTree = ""; }; 72EA17B51FD31F10009D5CE6 /* ExplicitACLRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplicitACLRule.swift; sourceTree = ""; }; 740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyStringRule.swift; sourceTree = ""; }; @@ -864,8 +864,10 @@ D93DA3CF1E699E4E00809827 /* NestingConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NestingConfiguration.swift; sourceTree = ""; }; DAD3BE491D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivateOutletRuleConfiguration.swift; sourceTree = ""; }; E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicInlineRule.swift; sourceTree = ""; }; - E4A6CF742363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RandomAccessCollection+Swiftlint.swift"; sourceTree = ""; }; + E48F715C23789823003E1775 /* SwiftLintSyntaxMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLintSyntaxMap.swift; sourceTree = ""; }; + E48F715D23789824003E1775 /* SwiftLintSyntaxToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLintSyntaxToken.swift; sourceTree = ""; }; E4A365D123653648003B4141 /* SourceKittenDictionary+Swiftlint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SourceKittenDictionary+Swiftlint.swift"; sourceTree = ""; }; + E4A6CF742363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RandomAccessCollection+Swiftlint.swift"; sourceTree = ""; }; E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLintFile.swift; sourceTree = ""; }; E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReturnArrowWhitespaceRule.swift; sourceTree = ""; }; E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFunctionWhitespaceRule.swift; sourceTree = ""; }; @@ -1628,6 +1630,8 @@ E88DEA781B098D4400A66CB0 /* RuleParameter.swift */, E88DEA6A1B0983FE00A66CB0 /* StyleViolation.swift */, E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */, + E48F715C23789823003E1775 /* SwiftLintSyntaxMap.swift */, + E48F715D23789824003E1775 /* SwiftLintSyntaxToken.swift */, D4A893341E15824100BF954D /* SwiftVersion.swift */, D4C27BFD1E12D53F00DF713E /* Version.swift */, E88DEA701B09847500A66CB0 /* ViolationSeverity.swift */, @@ -1662,7 +1666,6 @@ 1894D740207D57AD00BD94CF /* SwiftDeclarationAttributeKind+Swiftlint.swift */, D47079AA1DFDCF7A00027086 /* SwiftExpressionKind.swift */, E87E4A081BFB9CAE00FCFE46 /* SyntaxKind+SwiftLint.swift */, - 6CC4259A1C77046200AEA885 /* SyntaxMap+SwiftLint.swift */, ); path = Extensions; sourceTree = ""; @@ -1941,7 +1944,6 @@ 8B01E4FD20A41C8700C9233E /* FunctionParameterCountConfiguration.swift in Sources */, 740DF1B1203F62BB0081F694 /* EmptyStringRule.swift in Sources */, 4DB7815E1CAD72BA00BC4723 /* LegacyCGGeometryFunctionsRule.swift in Sources */, - 6CC4259B1C77046200AEA885 /* SyntaxMap+SwiftLint.swift in Sources */, D4F10614229A2F5E00FDE319 /* NoFallthroughOnlyRuleExamples.swift in Sources */, 3ABE19CF20B7CE32009C2EC2 /* MultilineFunctionChainsRule.swift in Sources */, 82FE253F20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift in Sources */, @@ -2067,6 +2069,7 @@ E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */, E88198591BEA95F100333A11 /* LeadingWhitespaceRule.swift in Sources */, D42B45D91F0AF5E30086B683 /* StrictFilePrivateRule.swift in Sources */, + E48F715F23789824003E1775 /* SwiftLintSyntaxToken.swift in Sources */, 1EC163521D5992D900DD2928 /* VerticalWhitespaceRule.swift in Sources */, F90DBD7F2092E669002CC310 /* MissingDocsRuleConfiguration.swift in Sources */, 67EB4DFA1E4CC111004E9ACD /* CyclomaticComplexityConfiguration.swift in Sources */, @@ -2241,6 +2244,7 @@ D48B51211F4F5DEF0068AB98 /* RuleList+Documentation.swift in Sources */, 8FC9F5111F4B8E48006826C1 /* IsDisjointRule.swift in Sources */, 8FC8523B2117BDDE0015269B /* ExplicitSelfRule.swift in Sources */, + E48F715E23789824003E1775 /* SwiftLintSyntaxMap.swift in Sources */, 4DCB8E7F1CBE494E0070FCF0 /* RegexHelpers.swift in Sources */, E86396C21BADAAE5002C9E88 /* Reporter.swift in Sources */, A1A6F3F21EE319ED00A9F9E2 /* ObjectLiteralConfiguration.swift in Sources */,