Compare commits
1 Commits
main
...
test/multi
Author | SHA1 | Date |
---|---|---|
![]() |
c36858f705 |
|
@ -103,18 +103,25 @@ extension SwiftLintFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func matchesAndTokens(matching pattern: String,
|
internal func matchesAndTokens(matching pattern: String,
|
||||||
range: NSRange? = nil) -> [(NSTextCheckingResult, [SwiftLintSyntaxToken])] {
|
range: NSRange? = nil) -> [(SwiftlintTextCheckingResult, [SwiftLintSyntaxToken])] {
|
||||||
let contents = stringView
|
let contents = stringView
|
||||||
let range = range ?? contents.range
|
// let range = range ?? contents.range
|
||||||
let syntax = syntaxMap
|
let syntax = syntaxMap
|
||||||
return regex(pattern).matches(in: contents, options: [], range: range).compactMap { match in
|
let matches = range.map { regex(pattern).matches(in: contents, options: [], range: $0).map(SwiftlintTextCheckingResult.init) } ?? fulllFileMatches(pattern: pattern)
|
||||||
|
return matches.compactMap { match in
|
||||||
let matchByteRange = contents.NSRangeToByteRange(start: match.range.location, length: match.range.length)
|
let matchByteRange = contents.NSRangeToByteRange(start: match.range.location, length: match.range.length)
|
||||||
return matchByteRange.map { (match, syntax.tokens(inByteRange: $0)) }
|
return matchByteRange.map { (match, syntax.tokens(inByteRange: $0)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal func fulllFileMatches(pattern: String) -> [SwiftlintTextCheckingResult] {
|
||||||
|
return matches2(pattern: pattern)
|
||||||
|
// print("\(self.file.path) Check on matching '\(NSRegularExpression.escapedPattern(for: pattern))'")
|
||||||
|
// return regex(pattern).matches(in: stringView, options: [], range: stringView.range)
|
||||||
|
}
|
||||||
|
|
||||||
internal func matchesAndSyntaxKinds(matching pattern: String,
|
internal func matchesAndSyntaxKinds(matching pattern: String,
|
||||||
range: NSRange? = nil) -> [(NSTextCheckingResult, [SyntaxKind])] {
|
range: NSRange? = nil) -> [(SwiftlintTextCheckingResult, [SyntaxKind])] {
|
||||||
return matchesAndTokens(matching: pattern, range: range).map { textCheckingResult, tokens in
|
return matchesAndTokens(matching: pattern, range: range).map { textCheckingResult, tokens in
|
||||||
(textCheckingResult, tokens.kinds)
|
(textCheckingResult, tokens.kinds)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,11 @@ public final class SwiftLintFile {
|
||||||
let file: File
|
let file: File
|
||||||
let id: Int
|
let id: Int
|
||||||
|
|
||||||
|
private let queue = DispatchQueue(label: "regexQueue")
|
||||||
|
private var items: [RegexRequest] = []
|
||||||
|
private var idx: Int = 0
|
||||||
|
private let regexGroup = DispatchGroup()
|
||||||
|
|
||||||
/// Creates a `SwiftLintFile` with a SourceKitten `File`.
|
/// Creates a `SwiftLintFile` with a SourceKitten `File`.
|
||||||
///
|
///
|
||||||
/// - parameter file: A file from SourceKitten.
|
/// - parameter file: A file from SourceKitten.
|
||||||
|
@ -80,3 +85,89 @@ extension SwiftLintFile: Hashable {
|
||||||
hasher.combine(id)
|
hasher.combine(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private struct RegexRequest {
|
||||||
|
let id: Int
|
||||||
|
let pattern: String
|
||||||
|
let result: ([SwiftlintTextCheckingResult]) -> ()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SwiftlintTextCheckingResult {
|
||||||
|
let offset: Int
|
||||||
|
let ranges: [NSRange]
|
||||||
|
let range: NSRange
|
||||||
|
let numberOfRanges: Int
|
||||||
|
init(original: NSTextCheckingResult) {
|
||||||
|
self.offset = 0
|
||||||
|
self.range = original.range
|
||||||
|
self.numberOfRanges = original.numberOfRanges
|
||||||
|
self.ranges = (0..<original.numberOfRanges).map { original.range(at: $0) }
|
||||||
|
}
|
||||||
|
init(original: NSTextCheckingResult, offset: Int, numberOfRanges: Int ) {
|
||||||
|
self.offset = offset
|
||||||
|
self.range = original.range
|
||||||
|
self.numberOfRanges = numberOfRanges
|
||||||
|
self.ranges = (0...numberOfRanges).map { original.range(at: $0 + offset) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func range(at group: Int) -> NSRange {
|
||||||
|
return ranges[group]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extension SwiftLintFile {
|
||||||
|
|
||||||
|
func matches2(pattern: String) -> [SwiftlintTextCheckingResult] {
|
||||||
|
|
||||||
|
var res:[SwiftlintTextCheckingResult] = []
|
||||||
|
let p: Int = queue.sync {
|
||||||
|
self.idx += 1
|
||||||
|
let id = self.idx
|
||||||
|
items.append(RegexRequest(id: id, pattern: pattern, result: { res = $0 }))
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
// Thread.sleep(forTimeInterval: 0.1)
|
||||||
|
queue.async {
|
||||||
|
let lstId = self.items.last?.id
|
||||||
|
guard lstId == p else { return }
|
||||||
|
// process
|
||||||
|
self.process(requests: self.items)
|
||||||
|
self.items.removeAll()
|
||||||
|
self.regexGroup.notify(queue: self.queue) { }
|
||||||
|
}
|
||||||
|
regexGroup.wait()
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private func process(requests:[RegexRequest]) {
|
||||||
|
// Gather requests
|
||||||
|
let regexes = requests.map { regex($0.pattern) }
|
||||||
|
let fullRegex = requests.map { "(\($0.pattern))" }.joined(separator: "|")
|
||||||
|
// print("Fill REgex \(fullRegex)")
|
||||||
|
|
||||||
|
// offsets
|
||||||
|
var ofs = 1
|
||||||
|
var offsets: [(Int, Int)] = []
|
||||||
|
regexes.forEach {
|
||||||
|
offsets.append((ofs, $0.numberOfCaptureGroups))
|
||||||
|
ofs += $0.numberOfCaptureGroups + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
let fullR = regex(fullRegex)
|
||||||
|
|
||||||
|
// print("FullR: [\(requests.count)] [\(fullR.numberOfCaptureGroups)] \(fullR) ")
|
||||||
|
|
||||||
|
assert(fullR.numberOfCaptureGroups == ofs - 1, "Total number of capture groups should be the same \(fullR.numberOfCaptureGroups) : \(requests.count) :\(ofs)")
|
||||||
|
let allMatches = fullR.matches(in: stringView)
|
||||||
|
|
||||||
|
// print("Total matches \(allMatches.count)")
|
||||||
|
|
||||||
|
requests.enumerated().forEach { item in
|
||||||
|
let r = allMatches.filter { $0.range(at: offsets[item.offset].0).length != NSNotFound }
|
||||||
|
.map { SwiftlintTextCheckingResult(original: $0, offset: offsets[item.offset].0, numberOfRanges: offsets[item.offset].1)}
|
||||||
|
item.element.result(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ public struct IdenticalOperandsRule: ConfigurationProviderRule, OptInRule, Autom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func violationRangeFrom(match: NSTextCheckingResult, in file: SwiftLintFile) -> NSRange? {
|
private func violationRangeFrom(match: SwiftlintTextCheckingResult, in file: SwiftLintFile) -> NSRange? {
|
||||||
let contents = file.stringView
|
let contents = file.stringView
|
||||||
let operatorRange = match.range(at: 1)
|
let operatorRange = match.range(at: 1)
|
||||||
guard let operatorByteRange = contents.NSRangeToByteRange(operatorRange) else {
|
guard let operatorByteRange = contents.NSRangeToByteRange(operatorRange) else {
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct LintableFilesVisitor {
|
||||||
self.useScriptInputFiles = useScriptInputFiles
|
self.useScriptInputFiles = useScriptInputFiles
|
||||||
self.forceExclude = forceExclude
|
self.forceExclude = forceExclude
|
||||||
self.cache = cache
|
self.cache = cache
|
||||||
self.parallel = true
|
self.parallel = false
|
||||||
if let compilerInvocations = compilerInvocations {
|
if let compilerInvocations = compilerInvocations {
|
||||||
self.mode = .analyze(allCompilerInvocations: compilerInvocations)
|
self.mode = .analyze(allCompilerInvocations: compilerInvocations)
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue