Add own wrappers over syntax tokens and syntax map

This commit is contained in:
Paul Taykalo 2019-11-10 21:15:58 +02:00
parent 7fa995189e
commit 73802c285d
37 changed files with 170 additions and 161 deletions

View File

@ -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 { extension Array where Element: Equatable {
var unique: [Element] { var unique: [Element] {
var uniqueValues = [Element]() var uniqueValues = [Element]()

View File

@ -24,7 +24,9 @@ private var structureDictionaryCache = Cache({ file in
return structureCache.get(file).map { SourceKittenDictionary($0.dictionary) } 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 syntaxKindsByLinesCache = Cache({ file in file.syntaxKindsByLine() })
private var syntaxTokensByLinesCache = Cache({ file in file.syntaxTokensByLine() }) private var syntaxTokensByLinesCache = Cache({ file in file.syntaxTokensByLine() })
@ -145,18 +147,18 @@ extension SwiftLintFile {
return structureDictionary return structureDictionary
} }
internal var syntaxMap: SyntaxMap { internal var syntaxMap: SwiftLintSyntaxMap {
guard let syntaxMap = syntaxMapCache.get(self) else { guard let syntaxMap = syntaxMapCache.get(self) else {
if let handler = assertHandler { if let handler = assertHandler {
handler() handler()
return SyntaxMap(data: []) return SwiftLintSyntaxMap(value: SyntaxMap(data: []))
} }
queuedFatalError("Never call this for file that sourcekitd fails.") queuedFatalError("Never call this for file that sourcekitd fails.")
} }
return syntaxMap return syntaxMap
} }
internal var syntaxTokensByLines: [[SyntaxToken]] { internal var syntaxTokensByLines: [[SwiftLintSyntaxToken]] {
guard let syntaxTokensByLines = syntaxTokensByLinesCache.get(self) else { guard let syntaxTokensByLines = syntaxTokensByLinesCache.get(self) else {
if let handler = assertHandler { if let handler = assertHandler {
handler() handler()

View File

@ -95,7 +95,7 @@ extension SwiftLintFile {
} }
internal func matchesAndTokens(matching pattern: String, internal func matchesAndTokens(matching pattern: String,
range: NSRange? = nil) -> [(NSTextCheckingResult, [SyntaxToken])] { range: NSRange? = nil) -> [(NSTextCheckingResult, [SwiftLintSyntaxToken])] {
let contents = self.contents.bridge() let contents = self.contents.bridge()
let range = range ?? NSRange(location: 0, length: contents.length) let range = range ?? NSRange(location: 0, length: contents.length)
let syntax = syntaxMap let syntax = syntaxMap
@ -115,7 +115,7 @@ extension SwiftLintFile {
} }
internal func rangesAndTokens(matching pattern: String, 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) } return matchesAndTokens(matching: pattern, range: range).map { ($0.0.range, $0.1) }
} }
@ -149,17 +149,17 @@ extension SwiftLintFile {
return results return results
} }
internal func syntaxTokensByLine() -> [[SyntaxToken]]? { internal func syntaxTokensByLine() -> [[SwiftLintSyntaxToken]]? {
if sourcekitdFailed { if sourcekitdFailed {
return nil return nil
} }
var results = [[SyntaxToken]](repeating: [], count: lines.count + 1) var results = [[SwiftLintSyntaxToken]](repeating: [], count: lines.count + 1)
var tokenGenerator = syntaxMap.tokens.makeIterator() var tokenGenerator = syntaxMap.tokens.makeIterator()
var lineGenerator = lines.makeIterator() var lineGenerator = lines.makeIterator()
var maybeLine = lineGenerator.next() var maybeLine = lineGenerator.next()
var maybeToken = tokenGenerator.next() var maybeToken = tokenGenerator.next()
while let line = maybeLine, let token = maybeToken { 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) || if NSLocationInRange(token.offset, line.byteRange) ||
NSLocationInRange(line.byteRange.location, tokenRange) { NSLocationInRange(line.byteRange.location, tokenRange) {
results[line.index].append(token) results[line.index].append(token)
@ -317,17 +317,16 @@ extension SwiftLintFile {
return corrections return corrections
} }
internal func isACL(token: SyntaxToken) -> Bool { internal func isACL(token: SwiftLintSyntaxToken) -> Bool {
guard SyntaxKind(rawValue: token.type) == .attributeBuiltin else { guard token.kind == .attributeBuiltin else {
return false return false
} }
let aclString = contents.bridge().substringWithByteRange(start: token.offset, let aclString = contents(for: token)
length: token.length)
return aclString.flatMap(AccessControlLevel.init(description:)) != nil 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, return contents.bridge().substringWithByteRange(start: token.offset,
length: token.length) length: token.length)
} }

View File

@ -1,17 +1,24 @@
import Foundation import Foundation
import SourceKittenFramework 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 /// Returns array of SyntaxTokens intersecting with byte range
/// ///
/// - Parameter byteRange: byte based NSRange /// - Parameter byteRange: byte based NSRange
internal func tokens(inByteRange byteRange: NSRange) -> [SyntaxToken] { internal func tokens(inByteRange byteRange: NSRange) -> [SwiftLintSyntaxToken] {
func intersect(_ token: SyntaxToken) -> Bool { func intersect(_ token: SwiftLintSyntaxToken) -> Bool {
return NSRange(location: token.offset, length: token.length) return token.range.intersects(byteRange)
.intersects(byteRange)
} }
func intersectsOrAfter(_ token: SyntaxToken) -> Bool { func intersectsOrAfter(_ token: SwiftLintSyntaxToken) -> Bool {
return token.offset + token.length > byteRange.location return token.offset + token.length > byteRange.location
} }
@ -29,6 +36,6 @@ extension SyntaxMap {
} }
internal func kinds(inByteRange byteRange: NSRange) -> [SyntaxKind] { internal func kinds(inByteRange byteRange: NSRange) -> [SyntaxKind] {
return tokens(inByteRange: byteRange).kinds return tokens(inByteRange: byteRange).compactMap { $0.kind }
} }
} }

View File

@ -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 }
}
}

View File

@ -49,7 +49,7 @@ public extension SwiftVersion {
if !Request.disableSourceKit, if !Request.disableSourceKit,
case let dynamicCallableFile = SwiftLintFile(contents: "@dynamicCallable"), case let dynamicCallableFile = SwiftLintFile(contents: "@dynamicCallable"),
dynamicCallableFile.syntaxMap.tokens.compactMap({ SyntaxKind(rawValue: $0.type) }) == [.attributeID] { dynamicCallableFile.syntaxMap.tokens.compactMap({ $0.kind }) == [.attributeID] {
return .five return .five
} }
@ -100,13 +100,10 @@ public extension SwiftVersion {
let version = "3.0.0" let version = "3.0.0"
#endif #endif
""") """)
func isString(token: SyntaxToken) -> Bool {
return token.type == SyntaxKind.string.rawValue
}
if !Request.disableSourceKit, if !Request.disableSourceKit,
let decl = file.structureDictionary.kinds() let decl = file.structureDictionary.kinds()
.first(where: { $0.kind == SwiftDeclarationKind.varGlobal.rawValue }), .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)) return .init(rawValue: file.contents.substring(from: token.offset + 1, length: token.length - 2))
} }

View File

@ -26,8 +26,8 @@ public struct DuplicateImportsRule: ConfigurationProviderRule, AutomaticTestable
let contents = file.contents.bridge() let contents = file.contents.bridge()
let ranges = file.syntaxMap.tokens let ranges = file.syntaxMap.tokens
.filter { SyntaxKind(rawValue: $0.type) == .buildconfigKeyword } .filter { $0.kind == .buildconfigKeyword }
.map { NSRange(location: $0.offset, length: $0.length) } .map { $0.range }
.filter { range in .filter { range in
let keyword = contents.substringWithByteRange(start: range.location, length: range.length) let keyword = contents.substringWithByteRange(start: range.location, length: range.length)
return ["#if", "#endif"].contains(keyword) return ["#if", "#endif"].contains(keyword)

View File

@ -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? { file: SwiftLintFile) -> NSRange? {
if match.numberOfRanges < 3 { return nil } 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`. // 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 tokens = syntaxMap.tokens(inByteRange: byteRange)
let nsString = file.contents.bridge()
return tokens.contains { token in return tokens.contains { token in
guard let kind = SyntaxKind(rawValue: token.type), guard let kind = token.kind,
ForceUnwrappingRule.excludingSyntaxKindsForFirstCapture.contains(kind) ForceUnwrappingRule.excludingSyntaxKindsForFirstCapture.contains(kind)
else { return false } else { return false }
// check for `self // check for `self
guard kind == .keyword, guard kind == .keyword else { return true }
let nsRange = nsString.byteRangeToNSRange(start: token.offset, length: token.length) return file.contents(for: token) != "self"
else { return true }
return nsString.substring(with: nsRange) != "self"
} }
} }

View File

@ -52,14 +52,14 @@ public struct NoFallthroughOnlyRule: ASTRule, ConfigurationProviderRule, Automat
private func isNextTokenUnknownAttribute(afterOffset offset: Int, file: SwiftLintFile) -> Bool { private func isNextTokenUnknownAttribute(afterOffset offset: Int, file: SwiftLintFile) -> Bool {
let nextNonCommentToken = file.syntaxMap.tokens let nextNonCommentToken = file.syntaxMap.tokens
.first { token in .first { token in
guard let kind = SyntaxKind(rawValue: token.type), !kind.isCommentLike else { guard let kind = token.kind, !kind.isCommentLike else {
return false return false
} }
return token.offset > offset return token.offset > offset
} }
return (nextNonCommentToken?.type).flatMap(SyntaxKind.init(rawValue:)) == .attributeID && return nextNonCommentToken?.kind == .attributeID &&
nextNonCommentToken.flatMap(file.contents(for:)) == "@unknown" nextNonCommentToken.flatMap(file.contents(for:)) == "@unknown"
} }

View File

@ -80,7 +80,7 @@ public struct PrivateOverFilePrivateRule: ConfigurationProviderRule, Substitutio
let parts = syntaxTokens.prefix { offset > $0.offset } let parts = syntaxTokens.prefix { offset > $0.offset }
guard let lastKind = parts.last, guard let lastKind = parts.last,
SyntaxKind(rawValue: lastKind.type) == .attributeBuiltin, lastKind.kind == .attributeBuiltin,
let aclName = contents.substringWithByteRange(start: lastKind.offset, length: lastKind.length), let aclName = contents.substringWithByteRange(start: lastKind.offset, length: lastKind.length),
AccessControlLevel(description: aclName) == .fileprivate, AccessControlLevel(description: aclName) == .fileprivate,
let range = contents.byteRangeToNSRange(start: lastKind.offset, length: lastKind.length) else { let range = contents.byteRangeToNSRange(start: lastKind.offset, length: lastKind.length) else {

View File

@ -47,14 +47,12 @@ public struct TypeNameRule: ASTRule, ConfigurationProviderRule {
guard tokens.count == 2, guard tokens.count == 2,
let keywordToken = tokens.first, let keywordToken = tokens.first,
let nameToken = tokens.last, let nameToken = tokens.last,
SyntaxKind(rawValue: keywordToken.type) == .keyword, keywordToken.kind == .keyword,
SyntaxKind(rawValue: nameToken.type) == .identifier else { nameToken.kind == .identifier else {
return [] return []
} }
let contents = file.contents.bridge() guard let name = file.contents(for: nameToken) else {
guard let name = contents.substringWithByteRange(start: nameToken.offset,
length: nameToken.length) else {
return [] return []
} }

View File

@ -46,7 +46,7 @@ public struct UnneededBreakInSwitchRule: ConfigurationProviderRule, AutomaticTes
let caseRange = NSRange(location: caseOffset, length: caseLength) let caseRange = NSRange(location: caseOffset, length: caseLength)
let tokens = file.syntaxMap.tokens(inByteRange: caseRange).filter { token in 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 { token.offset > lastPatternEnd else {
return false return false
} }
@ -61,7 +61,7 @@ public struct UnneededBreakInSwitchRule: ConfigurationProviderRule, AutomaticTes
// is the `break` found the last (non-comment) token inside `case`? // is the `break` found the last (non-comment) token inside `case`?
guard let lastValidToken = tokens.last, guard let lastValidToken = tokens.last,
SyntaxKind(rawValue: lastValidToken.type) == .keyword, lastValidToken.kind == .keyword,
lastValidToken.offset == byteRange.location, lastValidToken.offset == byteRange.location,
lastValidToken.length == byteRange.length else { lastValidToken.length == byteRange.length else {
return nil return nil

View File

@ -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 && return token.length == 1 &&
SyntaxKind(rawValue: token.type) == .keyword && token.kind == .keyword &&
isUnderscore(file: file, token: token) isUnderscore(file: file, token: token)
} }
@ -97,8 +97,7 @@ public struct UnusedEnumeratedRule: ASTRule, ConfigurationProviderRule, Automati
return nil return nil
} }
private func isUnderscore(file: SwiftLintFile, token: SyntaxToken) -> Bool { private func isUnderscore(file: SwiftLintFile, token: SwiftLintSyntaxToken) -> Bool {
let contents = file.contents.bridge() return file.contents(for: token) == "_"
return contents.substringWithByteRange(start: token.offset, length: token.length) == "_"
} }
} }

View File

@ -57,7 +57,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto
let range = NSRange(location: bodyOffset, length: bodyLength) let range = NSRange(location: bodyOffset, length: bodyLength)
let tokens = file.syntaxMap.tokens(inByteRange: range).filter { token in 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 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, nameEndPosition: Int,
file: SwiftLintFile) -> Bool { file: SwiftLintFile) -> Bool {
let length = firstToken.offset - nameEndPosition 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 return pattern.firstMatch(in: file.contents, options: .anchored, range: byteRange) != nil
} }
private func containsTrailingContent(lastToken: SyntaxToken, private func containsTrailingContent(lastToken: SwiftLintSyntaxToken,
bodyEndPosition: Int, bodyEndPosition: Int,
file: SwiftLintFile) -> Bool { file: SwiftLintFile) -> Bool {
let lastTokenEnd = lastToken.offset + lastToken.length let lastTokenEnd = lastToken.offset + lastToken.length
@ -106,14 +106,14 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto
return containsContent(inByteRange: remainingRange, file: file) return containsContent(inByteRange: remainingRange, file: file)
} }
private func containsLeadingContent(tokens: [SyntaxToken], private func containsLeadingContent(tokens: [SwiftLintSyntaxToken],
bodyStartPosition: Int, bodyStartPosition: Int,
file: SwiftLintFile) -> Bool { file: SwiftLintFile) -> Bool {
let inTokenPosition = tokens.firstIndex(where: { token in 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 let start: Int
if let position = inTokenPosition { if let position = inTokenPosition {
let index = tokens.index(after: position) let index = tokens.index(after: position)
@ -136,7 +136,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto
let ranges = NSMutableIndexSet(indexesIn: byteRange) let ranges = NSMutableIndexSet(indexesIn: byteRange)
for token in remainingTokens { for token in remainingTokens {
ranges.remove(in: NSRange(location: token.offset, length: token.length)) ranges.remove(in: token.range)
} }
var containsContent = false var containsContent = false
@ -158,7 +158,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto
return containsContent return containsContent
} }
private func isShortParameterStyleViolation(file: SwiftLintFile, tokens: [SyntaxToken]) -> Bool { private func isShortParameterStyleViolation(file: SwiftLintFile, tokens: [SwiftLintSyntaxToken]) -> Bool {
let kinds = tokens.kinds let kinds = tokens.kinds
switch kinds { switch kinds {
case [.identifier]: case [.identifier]:
@ -174,7 +174,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto
} }
private func isParameterStyleViolation(file: SwiftLintFile, dictionary: SourceKittenDictionary, private func isParameterStyleViolation(file: SwiftLintFile, dictionary: SourceKittenDictionary,
tokens: [SyntaxToken]) -> Bool { tokens: [SwiftLintSyntaxToken]) -> Bool {
let parameters = dictionary.enclosedVarParameters let parameters = dictionary.enclosedVarParameters
guard parameters.count == 1, guard parameters.count == 1,
let offset = parameters[0].offset, let offset = parameters[0].offset,
@ -185,7 +185,7 @@ public struct ArrayInitRule: ASTRule, ConfigurationProviderRule, OptInRule, Auto
let parameterEnd = offset + length let parameterEnd = offset + length
let tokens = Array(tokens.filter { $0.offset >= parameterEnd }.drop { token in 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" return !isKeyword || file.contents(for: token) != "in"
}) })

View File

@ -52,7 +52,7 @@ public struct DeploymentTargetRule: ConfigurationProviderRule {
return file.rangesAndTokens(matching: pattern).flatMap { range, tokens -> [StyleViolation] in return file.rangesAndTokens(matching: pattern).flatMap { range, tokens -> [StyleViolation] in
guard let availabilityToken = tokens.first, guard let availabilityToken = tokens.first,
SyntaxKind(rawValue: availabilityToken.type) == .keyword, availabilityToken.kind == .keyword,
let tokenRange = file.contents.bridge().byteRangeToNSRange(start: availabilityToken.offset, let tokenRange = file.contents.bridge().byteRangeToNSRange(start: availabilityToken.offset,
length: availabilityToken.length) else { length: availabilityToken.length) else {
return [] return []

View File

@ -62,7 +62,7 @@ public struct IdenticalOperandsRule: ConfigurationProviderRule, OptInRule, Autom
let index: Int let index: Int
// tokens in this operand // tokens in this operand
let tokens: [SyntaxToken] let tokens: [SwiftLintSyntaxToken]
} }
public func validate(file: SwiftLintFile) -> [StyleViolation] { public func validate(file: SwiftLintFile) -> [StyleViolation] {
@ -109,7 +109,7 @@ public struct IdenticalOperandsRule: ConfigurationProviderRule, OptInRule, Autom
} }
// Make sure both operands have same token types // 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 return nil
} }
@ -178,26 +178,29 @@ private extension NSString {
return NSRangeToByteRange(start: range.location, length: range.length) 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) 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, return substringWithByteRange(start: startToken.offset + startToken.length,
length: endToken.offset - 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) return isRegexBetweenTokens(startToken, #"[\?!]?\."#, endToken)
} }
func isWhiteSpaceBetweenTokens(_ startToken: SyntaxToken, _ endToken: SyntaxToken) -> Bool { func isWhiteSpaceBetweenTokens(_ startToken: SwiftLintSyntaxToken,
_ endToken: SwiftLintSyntaxToken) -> Bool {
guard let betweenTokens = subStringBetweenTokens(startToken, endToken) else { return false } guard let betweenTokens = subStringBetweenTokens(startToken, endToken) else { return false }
let range = NSRange(location: 0, length: betweenTokens.utf16.count) let range = NSRange(location: 0, length: betweenTokens.utf16.count)
return !regex(#"^[\s\(,]*$"#).matches(in: betweenTokens, options: [], range: range).isEmpty return !regex(#"^[\s\(,]*$"#).matches(in: betweenTokens, options: [], range: range).isEmpty
} }
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 } guard let betweenTokens = subStringBetweenTokens(startToken, endToken) else { return false }
let range = NSRange(location: 0, length: betweenTokens.utf16.count) let range = NSRange(location: 0, length: betweenTokens.utf16.count)

View File

@ -80,8 +80,8 @@ private func isBrace(offset: Int, element: (kind: String, byteRange: NSRange)) -
return StatementKind(rawValue: element.kind) == .brace return StatementKind(rawValue: element.kind) == .brace
} }
private func isNotComment(token: SyntaxToken) -> Bool { private func isNotComment(token: SwiftLintSyntaxToken) -> Bool {
guard let kind = SyntaxKind(rawValue: token.type) else { guard let kind = token.kind else {
return false return false
} }

View File

@ -185,7 +185,7 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule {
private func violationRanges(in file: SwiftLintFile, matching pattern: String) -> [NSRange] { private func violationRanges(in file: SwiftLintFile, matching pattern: String) -> [NSRange] {
let nsstring = file.contents.bridge() let nsstring = file.contents.bridge()
return file.rangesAndTokens(matching: pattern).filter { _, syntaxTokens in 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 false
} }
return !syntaxTokens.isEmpty && SyntaxKind.commentKinds.contains(syntaxKind) return !syntaxTokens.isEmpty && SyntaxKind.commentKinds.contains(syntaxKind)

View File

@ -64,7 +64,7 @@ public struct NotificationCenterDetachmentRule: ASTRule, ConfigurationProviderRu
return false return false
} }
let body = file.contents.bridge().substringWithByteRange(start: token.offset, length: token.length) let body = file.contents(for: token)
return body == "self" return body == "self"
} }
} }

View File

@ -132,14 +132,11 @@ public struct UnusedCaptureListRule: ASTRule, ConfigurationProviderRule, Automat
} }
private func identifierStrings(in file: SwiftLintFile, byteRange: NSRange) -> Set<String> { private func identifierStrings(in file: SwiftLintFile, byteRange: NSRange) -> Set<String> {
let contents = file.contents.bridge()
let identifiers = file.syntaxMap let identifiers = file.syntaxMap
.tokens(inByteRange: byteRange) .tokens(inByteRange: byteRange)
.compactMap { token -> String? in .compactMap { token -> String? in
guard token.type == SyntaxKind.identifier.rawValue || token.type == SyntaxKind.keyword.rawValue, guard token.kind == .identifier || token.kind == .keyword else { return nil }
let range = contents.byteRangeToNSRange(start: token.offset, length: token.length) return file.contents(for: token)
else { return nil }
return contents.substring(with: range)
} }
return Set(identifiers) return Set(identifiers)
} }

View File

@ -160,8 +160,8 @@ public struct UnusedClosureParameterRule: SubstitutionCorrectableASTRule, Config
} }
let token = tokens.first(where: { token -> Bool in let token = tokens.first(where: { token -> Bool in
return (SyntaxKind(rawValue: token.type) == .identifier return (token.kind == .identifier
|| (SyntaxKind(rawValue: token.type) == .keyword && name == "self")) && || (token.kind == .keyword && name == "self")) &&
token.offset == byteRange.location && token.offset == byteRange.location &&
token.length == byteRange.length token.length == byteRange.length
}) })

View File

@ -118,7 +118,7 @@ public struct UnusedControlFlowLabelRule: SubstitutionCorrectableASTRule, Config
case let byteRange = NSRange(location: offset, length: length), case let byteRange = NSRange(location: offset, length: length),
case let tokens = file.syntaxMap.tokens(inByteRange: byteRange), case let tokens = file.syntaxMap.tokens(inByteRange: byteRange),
let firstToken = tokens.first, let firstToken = tokens.first,
SyntaxKind(rawValue: firstToken.type) == .identifier, firstToken.kind == .identifier,
let tokenContent = file.contents(for: firstToken), let tokenContent = file.contents(for: firstToken),
case let contents = file.contents.bridge(), case let contents = file.contents.bridge(),
let range = contents.byteRangeToNSRange(start: offset, length: length) else { let range = contents.byteRangeToNSRange(start: offset, length: length) else {

View File

@ -135,7 +135,7 @@ private extension SwiftLintFile {
return syntaxMap.tokens return syntaxMap.tokens
.compactMap { token in .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 return nil
} }

View File

@ -173,12 +173,10 @@ private extension SwiftLintFile {
var nextIsModuleImport = false var nextIsModuleImport = false
let tokens = syntaxMap.tokens let tokens = syntaxMap.tokens
for token in tokens { for token in tokens {
guard let tokenKind = SyntaxKind(rawValue: token.type) else { guard let tokenKind = token.kind else {
continue continue
} }
if tokenKind == .keyword, if tokenKind == .keyword, contents(for: token) == "import" {
let substring = contentsNSString.substringWithByteRange(start: token.offset, length: token.length),
substring == "import" {
nextIsModuleImport = true nextIsModuleImport = true
continue continue
} }

View File

@ -156,10 +156,10 @@ public struct UnusedSetterValueRule: ConfigurationProviderRule, AutomaticTestabl
} }
} }
private func findNamedArgument(after token: SyntaxToken, private func findNamedArgument(after token: SwiftLintSyntaxToken,
file: SwiftLintFile) -> (name: String, token: SyntaxToken)? { file: SwiftLintFile) -> (name: String, token: SwiftLintSyntaxToken)? {
guard let firstToken = file.syntaxMap.tokens.first(where: { $0.offset > token.offset }), guard let firstToken = file.syntaxMap.tokens.first(where: { $0.offset > token.offset }),
SyntaxKind(rawValue: firstToken.type) == .identifier else { firstToken.kind == .identifier else {
return nil return nil
} }
@ -174,7 +174,7 @@ public struct UnusedSetterValueRule: ConfigurationProviderRule, AutomaticTestabl
} }
private func findGetToken(in range: NSRange, file: SwiftLintFile, private func findGetToken(in range: NSRange, file: SwiftLintFile,
propertyStructure: SourceKittenDictionary) -> SyntaxToken? { propertyStructure: SourceKittenDictionary) -> SwiftLintSyntaxToken? {
let getTokens = file.rangesAndTokens(matching: "\\bget\\b", range: range).keywordTokens() let getTokens = file.rangesAndTokens(matching: "\\bget\\b", range: range).keywordTokens()
return getTokens.first(where: { token -> Bool in return getTokens.first(where: { token -> Bool in
// the last element is the deepest structure // the last element is the deepest structure
@ -223,14 +223,12 @@ public struct UnusedSetterValueRule: ConfigurationProviderRule, AutomaticTestabl
} }
} }
private extension Array where Element == (NSRange, [SyntaxToken]) { private extension Array where Element == (NSRange, [SwiftLintSyntaxToken]) {
func keywordTokens() -> [SyntaxToken] { func keywordTokens() -> [SwiftLintSyntaxToken] {
return compactMap { _, tokens in return compactMap { _, tokens in
guard let token = tokens.last, guard let token = tokens.last, token.kind == .keyword else {
SyntaxKind(rawValue: token.type) == .keyword else { return nil
return nil
} }
return token return token
} }
} }

View File

@ -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 // check if it's a line with other declaration which could have its own attributes
let nonAttributeTokens = tokens.filter { token in let nonAttributeTokens = tokens.filter { token in
guard SyntaxKind(rawValue: token.type) == .keyword, guard token.kind == .keyword,
let keyword = contents.substringWithByteRange(start: token.offset, let keyword = file.contents(for: token) else {
length: token.length) else {
return false return false
} }
@ -260,15 +259,14 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
return true return true
} }
private func attributeName(token: SyntaxToken, file: SwiftLintFile) -> (String, NSRange)? { private func attributeName(token: SwiftLintSyntaxToken, file: SwiftLintFile) -> (String, NSRange)? {
guard SyntaxKind(rawValue: token.type) == .attributeBuiltin else { guard token.kind == .attributeBuiltin else {
return nil return nil
} }
let maybeName = file.contents.bridge().substringWithByteRange(start: token.offset, let maybeName = file.contents(for: token)
length: token.length)
if let name = maybeName, isAttribute(name) { if let name = maybeName, isAttribute(name) {
return (name, NSRange(location: token.offset, length: token.length)) return (name, token.range)
} }
return nil return nil

View File

@ -73,7 +73,7 @@ public struct ClosureSpacingRule: CorrectableRule, ConfigurationProviderRule, Op
let nsstring = file.contents.bridge() let nsstring = file.contents.bridge()
let bracePattern = regex("\\{|\\}") let bracePattern = regex("\\{|\\}")
let linesTokens = file.syntaxTokensByLines 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 // find all lines and occurences of open { and closed } braces
var linesWithBraces = [[NSRange]]() var linesWithBraces = [[NSRange]]()
@ -85,7 +85,10 @@ public struct ClosureSpacingRule: CorrectableRule, ConfigurationProviderRule, Op
let braces = bracePattern.matches(in: file.contents, options: [], let braces = bracePattern.matches(in: file.contents, options: [],
range: nsrange).map { $0.range } range: nsrange).map { $0.range }
// filter out braces in comments and strings // 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 { let tokenRanges = tokens.compactMap {
file.contents.bridge().byteRangeToNSRange(start: $0.offset, length: $0.length) file.contents.bridge().byteRangeToNSRange(start: $0.offset, length: $0.length)
} }

View File

@ -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 let syntaxKinds = syntaxTokens.kinds
guard syntaxKinds.count == 2 else { guard syntaxKinds.count == 2 else {
@ -55,7 +55,7 @@ internal extension ColonRule {
validKinds = file.isTypeLike(token: syntaxTokens[1]) validKinds = file.isTypeLike(token: syntaxTokens[1])
//Exclude explicit "Self" type because of static variables //Exclude explicit "Self" type because of static variables
if syntaxKinds[0] == .identifier, if syntaxKinds[0] == .identifier,
file.getTokenText(token: syntaxTokens[1]) == "Self" { file.contents(for: syntaxTokens[1]) == "Self" {
validKinds = false validKinds = false
} }
case (.keyword, .typeidentifier): case (.keyword, .typeidentifier):
@ -73,17 +73,12 @@ internal extension ColonRule {
} }
private extension SwiftLintFile { private extension SwiftLintFile {
func isTypeLike(token: SyntaxToken) -> Bool { func isTypeLike(token: SwiftLintSyntaxToken) -> Bool {
guard let text = getTokenText(token: token), guard let text = contents(for: token),
let firstLetter = text.unicodeScalars.first else { let firstLetter = text.unicodeScalars.first else {
return false return false
} }
return CharacterSet.uppercaseLetters.contains(firstLetter) return CharacterSet.uppercaseLetters.contains(firstLetter)
} }
func getTokenText(token: SyntaxToken) -> String? {
let nsstring = contents.bridge()
return nsstring.substringWithByteRange(start: token.offset, length: token.length)
}
} }

View File

@ -34,22 +34,17 @@ public struct ConditionalReturnsOnNewlineRule: ConfigurationProviderRule, Rule,
return file.rangesAndTokens(matching: pattern).filter { _, tokens in return file.rangesAndTokens(matching: pattern).filter { _, tokens in
guard let firstToken = tokens.first, let lastToken = tokens.last, guard let firstToken = tokens.first, let lastToken = tokens.last,
SyntaxKind(rawValue: firstToken.type) == .keyword && firstToken.kind == .keyword && lastToken.kind == .keyword else {
SyntaxKind(rawValue: lastToken.type) == .keyword else { return false
return false
} }
let searchTokens = configuration.ifOnly ? ["if"] : ["if", "guard"] let searchTokens = configuration.ifOnly ? ["if"] : ["if", "guard"]
return searchTokens.contains(content(for: firstToken, file: file)) && return searchTokens.contains(file.contents(for: firstToken) ?? "") &&
content(for: lastToken, file: file) == "return" file.contents(for: lastToken) == "return"
}.map { }.map {
StyleViolation(ruleDescription: type(of: self).description, StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severityConfiguration.severity, severity: configuration.severityConfiguration.severity,
location: Location(file: file, characterOffset: $0.0.location)) 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) ?? ""
}
} }

View File

@ -34,12 +34,12 @@ public struct FileHeaderRule: ConfigurationProviderRule, OptInRule {
private static let reason = "Header comments should be consistent with project patterns." private static let reason = "Header comments should be consistent with project patterns."
public func validate(file: SwiftLintFile) -> [StyleViolation] { public func validate(file: SwiftLintFile) -> [StyleViolation] {
var firstToken: SyntaxToken? var firstToken: SwiftLintSyntaxToken?
var lastToken: SyntaxToken? var lastToken: SwiftLintSyntaxToken?
var firstNonCommentToken: SyntaxToken? var firstNonCommentToken: SwiftLintSyntaxToken?
for token in file.syntaxTokensByLines.lazy.joined() { 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 // 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 // so we can just skip the remaining tokens
firstNonCommentToken = token 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, guard let range = file.contents.bridge().byteRangeToNSRange(start: token.offset,
length: token.length) else { length: token.length) else {
return false return false

View File

@ -178,10 +178,10 @@ public struct ImplicitGetterRule: ConfigurationProviderRule, AutomaticTestableRu
public func validate(file: SwiftLintFile) -> [StyleViolation] { public func validate(file: SwiftLintFile) -> [StyleViolation] {
let pattern = "\\{[^\\{]*?\\s+get\\b" let pattern = "\\{[^\\{]*?\\s+get\\b"
let attributesKinds: Set<SyntaxKind> = [.attributeBuiltin, .attributeID] let attributesKinds: Set<SyntaxKind> = [.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 let kinds = tokens.kinds
guard let token = tokens.last, guard let token = tokens.last,
SyntaxKind(rawValue: token.type) == .keyword, token.kind == .keyword,
attributesKinds.isDisjoint(with: kinds) else { attributesKinds.isDisjoint(with: kinds) else {
return nil return nil
} }

View File

@ -185,8 +185,8 @@ public struct LetVarWhitespaceRule: ConfigurationProviderRule, OptInRule, Automa
var result = Set<Int>() var result = Set<Int>()
let syntaxMap = file.syntaxMap let syntaxMap = file.syntaxMap
for token in syntaxMap.tokens where token.type == SyntaxKind.comment.rawValue || for token in syntaxMap.tokens where token.kind == .comment ||
token.type == SyntaxKind.docComment.rawValue { token.kind == .docComment {
let startLine = file.line(byteOffset: token.offset) let startLine = file.line(byteOffset: token.offset)
let endLine = file.line(byteOffset: token.offset + token.length) let endLine = file.line(byteOffset: token.offset + token.length)
@ -209,7 +209,7 @@ public struct LetVarWhitespaceRule: ConfigurationProviderRule, OptInRule, Automa
// other than let/var // other than let/var
private func attributeLineNumbers(file: SwiftLintFile) -> Set<Int> { private func attributeLineNumbers(file: SwiftLintFile) -> Set<Int> {
return Set(file.syntaxMap.tokens.compactMap({ token in 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 file.line(byteOffset: token.offset)
} }
return nil return nil

View File

@ -29,10 +29,10 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv
} }
private func violatingRanges(in file: SwiftLintFile) -> [(NSRange, String)] { private func violatingRanges(in file: SwiftLintFile) -> [(NSRange, String)] {
let numberTokens = file.syntaxMap.tokens.filter { SyntaxKind(rawValue: $0.type) == .number } let numberTokens = file.syntaxMap.tokens.filter { $0.kind == .number }
return numberTokens.compactMap { (token: SyntaxToken) -> (NSRange, String)? in return numberTokens.compactMap { (token: SwiftLintSyntaxToken) -> (NSRange, String)? in
guard guard
let content = contentFrom(file: file, token: token), let content = file.contents(for: token),
isDecimal(number: content), isDecimal(number: content),
!isInValidRanges(number: content) !isInValidRanges(number: content)
else { else {
@ -159,9 +159,4 @@ public struct NumberSeparatorRule: OptInRule, CorrectableRule, ConfigurationProv
return Array(collection) return Array(collection)
} }
private func contentFrom(file: SwiftLintFile, token: SyntaxToken) -> String? {
return file.contents.bridge().substringWithByteRange(start: token.offset,
length: token.length)
}
} }

View File

@ -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 return { match in
let range = match.range let range = match.range
guard let matchRange = contents.bridge().NSRangeToByteRange(start: range.location, guard let matchRange = contents.bridge().NSRangeToByteRange(start: range.location,

View File

@ -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 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 return false
} }

View File

@ -84,13 +84,11 @@ public struct UnneededParenthesesInClosureArgumentRule: ConfigurationProviderRul
let parametersTokens = file.syntaxMap.tokens(inByteRange: parametersByteRange) let parametersTokens = file.syntaxMap.tokens(inByteRange: parametersByteRange)
let parametersAreValid = parametersTokens.allSatisfy { token in let parametersAreValid = parametersTokens.allSatisfy { token in
let kind = SyntaxKind(rawValue: token.type) if token.kind == .identifier {
if kind == .identifier {
return true return true
} }
return kind == .keyword && return token.kind == .keyword && file.contents(for: token) == "_"
file.contents.bridge().substringWithByteRange(start: token.offset, length: token.length) == "_"
} }
let inKinds = Set(file.syntaxMap.kinds(inByteRange: inByteRange)) let inKinds = Set(file.syntaxMap.kinds(inByteRange: inByteRange))

View File

@ -135,7 +135,6 @@
6C1D763221A4E69600DEF783 /* Request+DisableSourceKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C1D763121A4E69600DEF783 /* Request+DisableSourceKit.swift */; }; 6C1D763221A4E69600DEF783 /* Request+DisableSourceKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C1D763121A4E69600DEF783 /* Request+DisableSourceKit.swift */; };
6C7045441C6ADA450003F15A /* SourceKitCrashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */; }; 6C7045441C6ADA450003F15A /* SourceKitCrashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */; };
6CB8A80C1D11A7E10052816E /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E101B07A3EC003E02D0 /* Commandant.framework */; }; 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, ); }; }; 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, ); }; }; 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, ); }; }; 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 */; }; D93DA3D11E699E6300809827 /* NestingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93DA3CF1E699E4E00809827 /* NestingConfiguration.swift */; };
DAD3BE4A1D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD3BE491D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift */; }; DAD3BE4A1D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAD3BE491D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift */; };
E315B83C1DFA4BC500621B44 /* DynamicInlineRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E315B83B1DFA4BC500621B44 /* DynamicInlineRule.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 */; }; 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 */; }; E4EA064C23688EB5002531D7 /* SwiftLintFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */; };
E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */; }; E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */; };
E802ED001C56A56000A35AE1 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = E802ECFF1C56A56000A35AE1 /* Benchmark.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 = "<group>"; }; 6C1D763121A4E69600DEF783 /* Request+DisableSourceKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Request+DisableSourceKit.swift"; sourceTree = "<group>"; };
6C27B5FC2079D33F00353E17 /* Mac-XCTest.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Mac-XCTest.xcconfig"; sourceTree = "<group>"; }; 6C27B5FC2079D33F00353E17 /* Mac-XCTest.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Mac-XCTest.xcconfig"; sourceTree = "<group>"; };
6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceKitCrashTests.swift; sourceTree = "<group>"; }; 6C7045431C6ADA450003F15A /* SourceKitCrashTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SourceKitCrashTests.swift; sourceTree = "<group>"; };
6CC4259A1C77046200AEA885 /* SyntaxMap+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SyntaxMap+SwiftLint.swift"; sourceTree = "<group>"; };
725094881D0855760039B353 /* StatementModeConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementModeConfiguration.swift; sourceTree = "<group>"; }; 725094881D0855760039B353 /* StatementModeConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementModeConfiguration.swift; sourceTree = "<group>"; };
72EA17B51FD31F10009D5CE6 /* ExplicitACLRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplicitACLRule.swift; sourceTree = "<group>"; }; 72EA17B51FD31F10009D5CE6 /* ExplicitACLRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplicitACLRule.swift; sourceTree = "<group>"; };
740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyStringRule.swift; sourceTree = "<group>"; }; 740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyStringRule.swift; sourceTree = "<group>"; };
@ -864,8 +864,10 @@
D93DA3CF1E699E4E00809827 /* NestingConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NestingConfiguration.swift; sourceTree = "<group>"; }; D93DA3CF1E699E4E00809827 /* NestingConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NestingConfiguration.swift; sourceTree = "<group>"; };
DAD3BE491D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivateOutletRuleConfiguration.swift; sourceTree = "<group>"; }; DAD3BE491D6ECD9500660239 /* PrivateOutletRuleConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivateOutletRuleConfiguration.swift; sourceTree = "<group>"; };
E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicInlineRule.swift; sourceTree = "<group>"; }; E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicInlineRule.swift; sourceTree = "<group>"; };
E4A6CF742363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RandomAccessCollection+Swiftlint.swift"; sourceTree = "<group>"; }; E48F715C23789823003E1775 /* SwiftLintSyntaxMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLintSyntaxMap.swift; sourceTree = "<group>"; };
E48F715D23789824003E1775 /* SwiftLintSyntaxToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLintSyntaxToken.swift; sourceTree = "<group>"; };
E4A365D123653648003B4141 /* SourceKittenDictionary+Swiftlint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SourceKittenDictionary+Swiftlint.swift"; sourceTree = "<group>"; }; E4A365D123653648003B4141 /* SourceKittenDictionary+Swiftlint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SourceKittenDictionary+Swiftlint.swift"; sourceTree = "<group>"; };
E4A6CF742363CBFB00DD5B18 /* RandomAccessCollection+Swiftlint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RandomAccessCollection+Swiftlint.swift"; sourceTree = "<group>"; };
E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLintFile.swift; sourceTree = "<group>"; }; E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftLintFile.swift; sourceTree = "<group>"; };
E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReturnArrowWhitespaceRule.swift; sourceTree = "<group>"; }; E57B23C01B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReturnArrowWhitespaceRule.swift; sourceTree = "<group>"; };
E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFunctionWhitespaceRule.swift; sourceTree = "<group>"; }; E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OperatorFunctionWhitespaceRule.swift; sourceTree = "<group>"; };
@ -1628,6 +1630,8 @@
E88DEA781B098D4400A66CB0 /* RuleParameter.swift */, E88DEA781B098D4400A66CB0 /* RuleParameter.swift */,
E88DEA6A1B0983FE00A66CB0 /* StyleViolation.swift */, E88DEA6A1B0983FE00A66CB0 /* StyleViolation.swift */,
E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */, E4EA064B23688EB4002531D7 /* SwiftLintFile.swift */,
E48F715C23789823003E1775 /* SwiftLintSyntaxMap.swift */,
E48F715D23789824003E1775 /* SwiftLintSyntaxToken.swift */,
D4A893341E15824100BF954D /* SwiftVersion.swift */, D4A893341E15824100BF954D /* SwiftVersion.swift */,
D4C27BFD1E12D53F00DF713E /* Version.swift */, D4C27BFD1E12D53F00DF713E /* Version.swift */,
E88DEA701B09847500A66CB0 /* ViolationSeverity.swift */, E88DEA701B09847500A66CB0 /* ViolationSeverity.swift */,
@ -1662,7 +1666,6 @@
1894D740207D57AD00BD94CF /* SwiftDeclarationAttributeKind+Swiftlint.swift */, 1894D740207D57AD00BD94CF /* SwiftDeclarationAttributeKind+Swiftlint.swift */,
D47079AA1DFDCF7A00027086 /* SwiftExpressionKind.swift */, D47079AA1DFDCF7A00027086 /* SwiftExpressionKind.swift */,
E87E4A081BFB9CAE00FCFE46 /* SyntaxKind+SwiftLint.swift */, E87E4A081BFB9CAE00FCFE46 /* SyntaxKind+SwiftLint.swift */,
6CC4259A1C77046200AEA885 /* SyntaxMap+SwiftLint.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1941,7 +1944,6 @@
8B01E4FD20A41C8700C9233E /* FunctionParameterCountConfiguration.swift in Sources */, 8B01E4FD20A41C8700C9233E /* FunctionParameterCountConfiguration.swift in Sources */,
740DF1B1203F62BB0081F694 /* EmptyStringRule.swift in Sources */, 740DF1B1203F62BB0081F694 /* EmptyStringRule.swift in Sources */,
4DB7815E1CAD72BA00BC4723 /* LegacyCGGeometryFunctionsRule.swift in Sources */, 4DB7815E1CAD72BA00BC4723 /* LegacyCGGeometryFunctionsRule.swift in Sources */,
6CC4259B1C77046200AEA885 /* SyntaxMap+SwiftLint.swift in Sources */,
D4F10614229A2F5E00FDE319 /* NoFallthroughOnlyRuleExamples.swift in Sources */, D4F10614229A2F5E00FDE319 /* NoFallthroughOnlyRuleExamples.swift in Sources */,
3ABE19CF20B7CE32009C2EC2 /* MultilineFunctionChainsRule.swift in Sources */, 3ABE19CF20B7CE32009C2EC2 /* MultilineFunctionChainsRule.swift in Sources */,
82FE253F20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift in Sources */, 82FE253F20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift in Sources */,
@ -2067,6 +2069,7 @@
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */, E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */,
E88198591BEA95F100333A11 /* LeadingWhitespaceRule.swift in Sources */, E88198591BEA95F100333A11 /* LeadingWhitespaceRule.swift in Sources */,
D42B45D91F0AF5E30086B683 /* StrictFilePrivateRule.swift in Sources */, D42B45D91F0AF5E30086B683 /* StrictFilePrivateRule.swift in Sources */,
E48F715F23789824003E1775 /* SwiftLintSyntaxToken.swift in Sources */,
1EC163521D5992D900DD2928 /* VerticalWhitespaceRule.swift in Sources */, 1EC163521D5992D900DD2928 /* VerticalWhitespaceRule.swift in Sources */,
F90DBD7F2092E669002CC310 /* MissingDocsRuleConfiguration.swift in Sources */, F90DBD7F2092E669002CC310 /* MissingDocsRuleConfiguration.swift in Sources */,
67EB4DFA1E4CC111004E9ACD /* CyclomaticComplexityConfiguration.swift in Sources */, 67EB4DFA1E4CC111004E9ACD /* CyclomaticComplexityConfiguration.swift in Sources */,
@ -2241,6 +2244,7 @@
D48B51211F4F5DEF0068AB98 /* RuleList+Documentation.swift in Sources */, D48B51211F4F5DEF0068AB98 /* RuleList+Documentation.swift in Sources */,
8FC9F5111F4B8E48006826C1 /* IsDisjointRule.swift in Sources */, 8FC9F5111F4B8E48006826C1 /* IsDisjointRule.swift in Sources */,
8FC8523B2117BDDE0015269B /* ExplicitSelfRule.swift in Sources */, 8FC8523B2117BDDE0015269B /* ExplicitSelfRule.swift in Sources */,
E48F715E23789824003E1775 /* SwiftLintSyntaxMap.swift in Sources */,
4DCB8E7F1CBE494E0070FCF0 /* RegexHelpers.swift in Sources */, 4DCB8E7F1CBE494E0070FCF0 /* RegexHelpers.swift in Sources */,
E86396C21BADAAE5002C9E88 /* Reporter.swift in Sources */, E86396C21BADAAE5002C9E88 /* Reporter.swift in Sources */,
A1A6F3F21EE319ED00A9F9E2 /* ObjectLiteralConfiguration.swift in Sources */, A1A6F3F21EE319ED00A9F9E2 /* ObjectLiteralConfiguration.swift in Sources */,