Skip to content

Commit

Permalink
Merge pull request #520 from realm/nn-optimize-colon-rule
Browse files Browse the repository at this point in the history
Improve performance of `ColonRule`
  • Loading branch information
jpsim committed Feb 10, 2016
2 parents dc97106 + 7d0afb1 commit d95d0c4
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 22 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
* Improve performance of `FunctionParameterCountRule`.
[Norio Nomura](https://github.com/norio-nomura)

* Improve performance of `ColonRule`.
[Norio Nomura](https://github.com/norio-nomura)

##### Bug Fixes

* Fix case sensitivity of keywords for `valid_docs`.
Expand Down
26 changes: 18 additions & 8 deletions Source/SwiftLintFramework/Extensions/File+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,33 @@ extension File {
}.map { $0.0 }
}

public func matchPattern(pattern: String) -> [(NSRange, [SyntaxKind])] {
return matchPattern(regex(pattern))
internal func rangesAndTokensMatching(pattern: String) -> [(NSRange, [SyntaxToken])] {
return rangesAndTokensMatching(regex(pattern))
}

public func matchPattern(regex: NSRegularExpression) -> [(NSRange, [SyntaxKind])] {
internal func rangesAndTokensMatching(regex: NSRegularExpression) ->
[(NSRange, [SyntaxToken])] {
let contents = self.contents as NSString
let range = NSRange(location: 0, length: contents.length)
let syntax = syntaxMap
let matches = regex.matchesInString(self.contents, options: [], range: range)
return matches.map { match in
return regex.matchesInString(self.contents, options: [], range: range).map { match in
let matchByteRange = contents.NSRangeToByteRange(start: match.range.location,
length: match.range.length) ?? match.range
let kindsInRange = syntax.tokens.filter { token in
let tokensInRange = syntax.tokens.filter { token in
let tokenByteRange = NSRange(location: token.offset, length: token.length)
return NSIntersectionRange(matchByteRange, tokenByteRange).length > 0
}.map({ $0.type }).flatMap(SyntaxKind.init)
return (match.range, kindsInRange)
}.map({ $0 })
return (match.range, tokensInRange)
}
}

public func matchPattern(pattern: String) -> [(NSRange, [SyntaxKind])] {
return matchPattern(regex(pattern))
}

public func matchPattern(regex: NSRegularExpression) -> [(NSRange, [SyntaxKind])] {
return rangesAndTokensMatching(regex).map { range, tokens in
(range, tokens.map({ $0.type }).flatMap(SyntaxKind.init))
}
}

Expand Down
35 changes: 21 additions & 14 deletions Source/SwiftLintFramework/Rules/ColonRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,25 +111,32 @@ public struct ColonRule: CorrectableRule, ConfigProviderRule {
// MARK: - Private

private let pattern =
"(\\w+)" + // Capture an identifier
"(?:" + // start group
"\\s+" + // followed by whitespace
":" + // to the left of a colon
"\\s*" + // followed by any amount of whitespace.
"|" + // or
":" + // immediately followed by a colon
"(\\w)" + // Capture an identifier
"(?:" + // start group
"\\s+" + // followed by whitespace
":" + // to the left of a colon
"\\s*" + // followed by any amount of whitespace.
"|" + // or
":" + // immediately followed by a colon
"(?:\\s{0}|\\s{2,})" + // followed by 0 or 2+ whitespace characters.
")" + // end group
"(" + // Capture a type identifier
"(?:\\[|\\()*" + // which may begin with a series of nested parenthesis or brackets
"\\S+?)" // lazily to the first non-whitespace character.
")" + // end group
"(" + // Capture a type identifier
"[\\[|\\(]*" + // which may begin with a series of nested parenthesis or brackets
"\\S)" // lazily to the first non-whitespace character.

private func violationRangesInFile(file: File, withPattern pattern: String) -> [NSRange] {
return file.matchPattern(pattern).filter { range, syntaxKinds in
let nsstring = file.contents as NSString
let commentAndStringKindsSet = Set(SyntaxKind.commentAndStringKinds())
return file.rangesAndTokensMatching(pattern).filter { range, syntaxTokens in
let syntaxKinds = syntaxTokens.map({ $0.type }).flatMap(SyntaxKind.init)
if !syntaxKinds.startsWith([.Identifier, .Typeidentifier]) {
return false
}
return Set(syntaxKinds).intersect(Set(SyntaxKind.commentAndStringKinds())).isEmpty
}.flatMap { $0.0 }
return Set(syntaxKinds).intersect(commentAndStringKindsSet).isEmpty
}.flatMap { range, syntaxTokens in
let identifierRange = nsstring // swiftlint:disable:next force_unwrapping
.byteRangeToNSRange(start: syntaxTokens.first!.offset, length: 0)
return identifierRange.map { NSUnionRange($0, range) }
}
}
}

0 comments on commit d95d0c4

Please sign in to comment.