Files
SwiftLint/Source/SwiftLintCore/Extensions/NSRegularExpression+SwiftLint.swift

74 lines
2.4 KiB
Swift

import Foundation
import SourceKittenFramework
private var regexCache = [RegexCacheKey: NSRegularExpression]()
private let regexCacheLock = NSLock()
public struct RegularExpression: Hashable, Comparable, ExpressibleByStringLiteral {
public let regex: NSRegularExpression
public init(pattern: String, options: NSRegularExpression.Options? = nil) throws {
regex = try .cached(pattern: pattern)
}
public init(stringLiteral value: String) {
// swiftlint:disable:next force_try
try! self.init(pattern: value)
}
var pattern: String { regex.pattern }
var numberOfCaptureGroups: Int { regex.numberOfCaptureGroups }
public static func < (lhs: Self, rhs: Self) -> Bool {
lhs.pattern < rhs.pattern
}
}
private struct RegexCacheKey: Hashable {
let pattern: String
let options: NSRegularExpression.Options
func hash(into hasher: inout Hasher) {
hasher.combine(pattern)
hasher.combine(options.rawValue)
}
}
extension NSRegularExpression: Comparable {
public static func < (lhs: NSRegularExpression, rhs: NSRegularExpression) -> Bool {
lhs.pattern < rhs.pattern
}
}
public extension NSRegularExpression {
static func cached(pattern: String, options: Options? = nil) throws -> NSRegularExpression {
let options = options ?? [.anchorsMatchLines, .dotMatchesLineSeparators]
let key = RegexCacheKey(pattern: pattern, options: options)
regexCacheLock.lock()
defer { regexCacheLock.unlock() }
if let result = regexCache[key] {
return result
}
let result = try NSRegularExpression(pattern: pattern, options: options)
regexCache[key] = result
return result
}
func matches(in stringView: StringView,
options: NSRegularExpression.MatchingOptions = []) -> [NSTextCheckingResult] {
return matches(in: stringView.string, options: options, range: stringView.range)
}
func matches(in stringView: StringView,
options: NSRegularExpression.MatchingOptions = [],
range: NSRange) -> [NSTextCheckingResult] {
return matches(in: stringView.string, options: options, range: range)
}
func matches(in file: SwiftLintFile,
options: NSRegularExpression.MatchingOptions = []) -> [NSTextCheckingResult] {
return matches(in: file.stringView.string, options: options, range: file.stringView.range)
}
}