Skip to content

Commit f91aaa9

Browse files
authoredMar 20, 2025··
Merge pull request #968 from TTOzzi/regex-performance
Improve lint performance by optimizing Swift Regex usage

File tree

1 file changed

+9
-12
lines changed

1 file changed

+9
-12
lines changed
 

‎Sources/SwiftFormat/Core/RuleMask.swift

+9-12
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ enum IgnoreDirective: CustomStringConvertible {
120120
/// because Windows did not have full support for regex literals until Swift 5.10.
121121
fileprivate func makeRegex() -> RegexExpression {
122122
let pattern = #"^\s*\/\/\s*"# + description + #"(?:\s*:\s*(?<ruleNames>.+))?$"#
123-
return try! Regex(pattern)
123+
return try! Regex(pattern).matchingSemantics(.unicodeScalar)
124124
}
125125
}
126126

@@ -142,14 +142,14 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
142142
case subset(ruleNames: [String])
143143
}
144144

145-
/// Computes source locations and ranges for syntax nodes in a source file.
146-
private let sourceLocationConverter: SourceLocationConverter
147-
148145
/// Cached regex object for ignoring rules at the node.
149-
private let ignoreRegex: IgnoreDirective.RegexExpression
146+
private static let ignoreRegex: IgnoreDirective.RegexExpression = IgnoreDirective.node.makeRegex()
150147

151148
/// Cached regex object for ignoring rules at the file.
152-
private let ignoreFileRegex: IgnoreDirective.RegexExpression
149+
private static let ignoreFileRegex: IgnoreDirective.RegexExpression = IgnoreDirective.file.makeRegex()
150+
151+
/// Computes source locations and ranges for syntax nodes in a source file.
152+
private let sourceLocationConverter: SourceLocationConverter
153153

154154
/// Stores the source ranges in which all rules are ignored.
155155
var allRulesIgnoredRanges: [SourceRange] = []
@@ -158,9 +158,6 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
158158
var ruleMap: [String: [SourceRange]] = [:]
159159

160160
init(sourceLocationConverter: SourceLocationConverter) {
161-
ignoreRegex = IgnoreDirective.node.makeRegex()
162-
ignoreFileRegex = IgnoreDirective.file.makeRegex()
163-
164161
self.sourceLocationConverter = sourceLocationConverter
165162
super.init(viewMode: .sourceAccurate)
166163
}
@@ -176,23 +173,23 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
176173
afterLeadingTrivia: false,
177174
afterTrailingTrivia: true
178175
)
179-
return appendRuleStatus(from: firstToken, of: sourceRange, using: ignoreFileRegex)
176+
return appendRuleStatus(from: firstToken, of: sourceRange, using: Self.ignoreFileRegex)
180177
}
181178

182179
override func visit(_ node: CodeBlockItemSyntax) -> SyntaxVisitorContinueKind {
183180
guard let firstToken = node.firstToken(viewMode: .sourceAccurate) else {
184181
return .visitChildren
185182
}
186183
let sourceRange = node.sourceRange(converter: sourceLocationConverter)
187-
return appendRuleStatus(from: firstToken, of: sourceRange, using: ignoreRegex)
184+
return appendRuleStatus(from: firstToken, of: sourceRange, using: Self.ignoreRegex)
188185
}
189186

190187
override func visit(_ node: MemberBlockItemSyntax) -> SyntaxVisitorContinueKind {
191188
guard let firstToken = node.firstToken(viewMode: .sourceAccurate) else {
192189
return .visitChildren
193190
}
194191
let sourceRange = node.sourceRange(converter: sourceLocationConverter)
195-
return appendRuleStatus(from: firstToken, of: sourceRange, using: ignoreRegex)
192+
return appendRuleStatus(from: firstToken, of: sourceRange, using: Self.ignoreRegex)
196193
}
197194

198195
// MARK: - Helper Methods

0 commit comments

Comments
 (0)
Please sign in to comment.