Files
SwiftLint/Source/SwiftLintFramework/File+SwiftLint.swift
T
2015-11-03 11:06:16 +02:00

103 lines
4.1 KiB
Swift

//
// File+SwiftLint.swift
// SwiftLint
//
// Created by JP Simard on 2015-05-16.
// Copyright (c) 2015 Realm. All rights reserved.
//
import SourceKittenFramework
import SwiftXPC
extension File {
public func regions() -> [Region] {
let nsStringContents = contents as NSString
let commands = matchPattern("swiftlint:(enable|disable)\\ [^\\s]+",
withSyntaxKinds: [.Comment]).flatMap { Command(string: nsStringContents, range: $0) }
let totalNumberOfLines = lines.count
let numberOfCharactersInLastLine = lines.last?.content.characters.count
var regions = [Region]()
var disabledRules = Set<String>()
let commandPairs = zip(commands, Array(commands.dropFirst().map({Optional($0)})) + [nil])
for (command, nextCommand) in commandPairs {
switch command.action {
case .Disable: disabledRules.insert(command.ruleIdentifier)
case .Enable: disabledRules.remove(command.ruleIdentifier)
}
regions.append(
Region(
start: Location(file: path,
line: command.line,
character: command.character),
end: Location(file: path,
line: nextCommand?.line ?? totalNumberOfLines,
character: nextCommand?.character ?? numberOfCharactersInLastLine),
disabledRuleIdentifiers: disabledRules)
)
}
return regions
}
public func matchPattern(pattern: String,
withSyntaxKinds syntaxKinds: [SyntaxKind]) -> [NSRange] {
return matchPattern(pattern).filter { _, kindsInRange in
return kindsInRange.count == syntaxKinds.count &&
zip(kindsInRange, syntaxKinds).filter({ $0.0 != $0.1 }).count == 0
}.map { $0.0 }
}
public func matchPattern(pattern: String) -> [(NSRange, [SyntaxKind])] {
let regex = try! NSRegularExpression(pattern: pattern, options: [])
let range = NSRange(location: 0, length: contents.utf16.count)
let syntax = syntaxMap
let matches = regex.matchesInString(contents, options: [], range: range)
return matches.map { match in
let tokensInRange = syntax.tokens.filter {
NSLocationInRange($0.offset, match.range) ||
NSLocationInRange(match.range.location,
NSRange(location: $0.offset, length: $0.length))
}
let kindsInRange = tokensInRange.flatMap {
SyntaxKind(rawValue: $0.type)
}
return (match.range, kindsInRange)
}
}
//Added by S2dent
/**
This function returns only matches that are not contained in a syntax kind
specified.
- parameter pattern: regex pattern to be matched inside file.
- parameter excludingSyntaxKinds: syntax kinds the matches to be filtered
when inside them.
- returns: An array of [NSRange] objects consisting of regex matches inside
file contents.
*/
public func matchPattern(pattern: String,
excludingSyntaxKinds syntaxKinds: [SyntaxKind]) -> [NSRange] {
let regex = try! NSRegularExpression(pattern: pattern, options: [])
let range = NSRange(location: 0, length: contents.utf16.count)
let syntax = syntaxMap
let matches = regex.matchesInString(contents, options: [], range: range)
return matches.filter { match in
let tokensInRange = syntax.tokens.filter {
NSLocationInRange($0.offset, match.range) ||
NSLocationInRange(match.range.location,
NSRange(location: $0.offset, length: $0.length))
}
for token in tokensInRange {
if NSIntersectionRange(NSRange(location: token.offset,
length:token.length), match.range).length > 0 &&
syntaxKinds.contains(SyntaxKind(rawValue: token.type)!) {
return false
}
}
return true
}.map { $0.range }
}
}