@@ -95,6 +95,34 @@ extension SourceRange {
95
95
}
96
96
}
97
97
98
+ /// Represents the kind of ignore directive encountered in the source.
99
+ enum IgnoreDirective : CustomStringConvertible {
100
+ /// A node-level directive that disables rules for the following node and its children.
101
+ case node
102
+ /// A file-level directive that disables rules for the entire file.
103
+ case file
104
+
105
+ var description : String {
106
+ switch self {
107
+ case . node:
108
+ return " swift-format-ignore "
109
+ case . file:
110
+ return " swift-format-ignore-file "
111
+ }
112
+ }
113
+
114
+ /// Regex pattern to match an ignore comment. This pattern supports 0 or more comma delimited rule
115
+ /// names. The rule name(s), when present, are in capture group #3.
116
+ private var pattern : String {
117
+ return #"^\s*\/\/\s*"# + description + #"((:\s+(([A-z0-9]+[,\s]*)+))?$|\s+$)"#
118
+ }
119
+
120
+ /// Rule ignore regex object.
121
+ fileprivate var regex : NSRegularExpression {
122
+ return try ! NSRegularExpression ( pattern: pattern, options: [ ] )
123
+ }
124
+ }
125
+
98
126
/// A syntax visitor that finds `SourceRange`s of nodes that have rule status modifying comment
99
127
/// directives. The changes requested in each comment is parsed and collected into a map to support
100
128
/// status lookup per rule name.
@@ -116,30 +144,13 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
116
144
/// Computes source locations and ranges for syntax nodes in a source file.
117
145
private let sourceLocationConverter : SourceLocationConverter
118
146
119
- /// Regex pattern to match an ignore comment. This pattern supports 0 or more comma delimited rule
120
- /// names. The rule name(s), when present, are in capture group #3.
121
- private let ignorePattern =
122
- #"^\s*\/\/\s*swift-format-ignore((:\s+(([A-z0-9]+[,\s]*)+))?$|\s+$)"#
123
-
124
- /// Rule ignore regex object.
125
- private let ignoreRegex : NSRegularExpression
126
-
127
- /// Regex pattern to match an ignore comment that applies to an entire file.
128
- private let ignoreFilePattern = #"^\s*\/\/\s*swift-format-ignore-file((:\s+(([A-z0-9]+[,\s]*)+))?$|\s+$)"#
129
-
130
- /// Rule ignore regex object.
131
- private let ignoreFileRegex : NSRegularExpression
132
-
133
147
/// Stores the source ranges in which all rules are ignored.
134
148
var allRulesIgnoredRanges : [ SourceRange ] = [ ]
135
149
136
150
/// Map of rule names to list ranges in the source where the rule is ignored.
137
151
var ruleMap : [ String : [ SourceRange ] ] = [ : ]
138
152
139
153
init ( sourceLocationConverter: SourceLocationConverter ) {
140
- ignoreRegex = try ! NSRegularExpression ( pattern: ignorePattern, options: [ ] )
141
- ignoreFileRegex = try ! NSRegularExpression ( pattern: ignoreFilePattern, options: [ ] )
142
-
143
154
self . sourceLocationConverter = sourceLocationConverter
144
155
super. init ( viewMode: . sourceAccurate)
145
156
}
@@ -155,23 +166,23 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
155
166
afterLeadingTrivia: false ,
156
167
afterTrailingTrivia: true
157
168
)
158
- return appendRuleStatusDirectives ( from: firstToken, of: sourceRange, using : ignoreFileRegex )
169
+ return appendRuleStatus ( from: firstToken, of: sourceRange, for : . file )
159
170
}
160
171
161
172
override func visit( _ node: CodeBlockItemSyntax ) -> SyntaxVisitorContinueKind {
162
173
guard let firstToken = node. firstToken ( viewMode: . sourceAccurate) else {
163
174
return . visitChildren
164
175
}
165
176
let sourceRange = node. sourceRange ( converter: sourceLocationConverter)
166
- return appendRuleStatusDirectives ( from: firstToken, of: sourceRange, using : ignoreRegex )
177
+ return appendRuleStatus ( from: firstToken, of: sourceRange, for : . node )
167
178
}
168
179
169
180
override func visit( _ node: MemberBlockItemSyntax ) -> SyntaxVisitorContinueKind {
170
181
guard let firstToken = node. firstToken ( viewMode: . sourceAccurate) else {
171
182
return . visitChildren
172
183
}
173
184
let sourceRange = node. sourceRange ( converter: sourceLocationConverter)
174
- return appendRuleStatusDirectives ( from: firstToken, of: sourceRange, using : ignoreRegex )
185
+ return appendRuleStatus ( from: firstToken, of: sourceRange, for : . node )
175
186
}
176
187
177
188
// MARK: - Helper Methods
@@ -183,16 +194,16 @@ fileprivate class RuleStatusCollectionVisitor: SyntaxVisitor {
183
194
/// - token: A token that may have comments that modify the status of rules.
184
195
/// - sourceRange: The range covering the node to which `token` belongs. If an ignore directive
185
196
/// is found among the comments, this entire range is used to ignore the specified rules.
186
- /// - regex : The regular expression used to detect ignore directives .
187
- private func appendRuleStatusDirectives (
197
+ /// - directive : The type of ignore directive to look for .
198
+ private func appendRuleStatus (
188
199
from token: TokenSyntax ,
189
200
of sourceRange: SourceRange ,
190
- using regex : NSRegularExpression
201
+ for directive : IgnoreDirective
191
202
) -> SyntaxVisitorContinueKind {
192
203
let isFirstInFile = token. previousToken ( viewMode: . sourceAccurate) == nil
193
204
let comments = loneLineComments ( in: token. leadingTrivia, isFirstToken: isFirstInFile)
194
205
for comment in comments {
195
- guard let matchResult = ruleStatusDirectiveMatch ( in: comment, using: regex) else { continue }
206
+ guard let matchResult = ruleStatusDirectiveMatch ( in: comment, using: directive . regex) else { continue }
196
207
switch matchResult {
197
208
case . all:
198
209
allRulesIgnoredRanges. append ( sourceRange)
0 commit comments