@@ -47,7 +47,7 @@ type NotSpecific struct {
47
47
}
48
48
49
49
func (i NotSpecific ) Details () string {
50
- return fmt .Sprintf ("directive `%s` should mention specific linter such as `// %s:my-linter`" ,
50
+ return fmt .Sprintf ("directive `%s` should mention specific linter such as `%s:my-linter`" ,
51
51
i .fullDirective , i .directiveWithOptionalLeadingSpace )
52
52
}
53
53
@@ -58,7 +58,7 @@ type ParseError struct {
58
58
}
59
59
60
60
func (i ParseError ) Details () string {
61
- return fmt .Sprintf ("directive `%s` should match `// %s[:<comma-separated-linters>] [// <explanation>]`" ,
61
+ return fmt .Sprintf ("directive `%s` should match `%s[:<comma-separated-linters>] [// <explanation>]`" ,
62
62
i .fullDirective ,
63
63
i .directiveWithOptionalLeadingSpace )
64
64
}
@@ -112,8 +112,7 @@ const (
112
112
NeedsAll = NeedsMachineOnly | NeedsSpecific | NeedsExplanation
113
113
)
114
114
115
- // matches lines starting with the nolint directive
116
- var directiveOnlyPattern = regexp .MustCompile (`^\s*(nolint)(:\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*)?\b` )
115
+ var commentPattern = regexp .MustCompile (`^//\s*(nolint)(:\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*)?\b` )
117
116
118
117
// matches a complete nolint directive
119
118
var fullDirectivePattern = regexp .MustCompile (`^//\s*nolint(:\s*[\w-]+\s*(?:,\s*[\w-]+\s*)*)?\s*(//.*)?\s*\n?$` )
@@ -142,110 +141,106 @@ var trailingBlankExplanation = regexp.MustCompile(`\s*(//\s*)?$`)
142
141
143
142
func (l Linter ) Run (fset * token.FileSet , nodes ... ast.Node ) ([]Issue , error ) {
144
143
var issues []Issue
144
+
145
145
for _ , node := range nodes {
146
146
if file , ok := node .(* ast.File ); ok {
147
147
for _ , c := range file .Comments {
148
- directive := getText ( c )
149
- if directive == "" {
150
- continue
151
- }
148
+ for _ , comment := range c . List {
149
+ if ! commentPattern . MatchString ( comment . Text ) {
150
+ continue
151
+ }
152
152
153
- // check for a space between the "//" and the directive
154
- leadingSpaceMatches := leadingSpacePattern .FindStringSubmatch (c .List [0 ].Text ) // c.Text() doesn't have all leading space
155
- if len (leadingSpaceMatches ) == 0 {
156
- continue
157
- }
158
- leadingSpace := leadingSpaceMatches [1 ]
153
+ // check for a space between the "//" and the directive
154
+ leadingSpaceMatches := leadingSpacePattern .FindStringSubmatch (comment .Text )
159
155
160
- directiveWithOptionalLeadingSpace := directive
161
- if len (leadingSpace ) > 0 {
162
- directiveWithOptionalLeadingSpace = " " + directive
163
- }
156
+ var leadingSpace string
157
+ if len (leadingSpaceMatches ) > 0 {
158
+ leadingSpace = leadingSpaceMatches [ 1 ]
159
+ }
164
160
165
- base := BaseIssue {
166
- fullDirective : c .List [0 ].Text ,
167
- directiveWithOptionalLeadingSpace : directiveWithOptionalLeadingSpace ,
168
- position : fset .Position (c .Pos ()),
169
- }
161
+ directiveWithOptionalLeadingSpace := comment .Text
162
+ if len (leadingSpace ) > 0 {
163
+ split := strings .SplitN (comment .Text , ":" , 2 )
164
+ split = strings .Split (split [0 ], "//" )
170
165
171
- // check for, report and eliminate leading spaces so we can check for other issues
172
- if leadingSpace != "" && leadingSpace != " " {
173
- issues = append (issues , ExtraLeadingSpace {
174
- BaseIssue : base ,
175
- })
176
- }
166
+ directiveWithOptionalLeadingSpace = "// " + strings .TrimSpace (split [1 ])
167
+ }
177
168
178
- if (l .needs & NeedsMachineOnly ) != 0 && strings .HasPrefix (directiveWithOptionalLeadingSpace , " " ) {
179
- issues = append (issues , NotMachine {BaseIssue : base })
180
- }
169
+ base := BaseIssue {
170
+ fullDirective : comment .Text ,
171
+ directiveWithOptionalLeadingSpace : directiveWithOptionalLeadingSpace ,
172
+ position : fset .Position (c .Pos ()),
173
+ }
181
174
182
- fullMatches := fullDirectivePattern .FindStringSubmatch (c .List [0 ].Text )
183
- if len (fullMatches ) == 0 {
184
- issues = append (issues , ParseError {BaseIssue : base })
185
- continue
186
- }
187
- lintersText , explanation := fullMatches [1 ], fullMatches [2 ]
188
- var linters []string
189
- if len (lintersText ) > 0 {
190
- lls := strings .Split (lintersText [1 :], "," )
191
- linters = make ([]string , 0 , len (lls ))
192
- for _ , ll := range lls {
193
- ll = strings .TrimSpace (ll )
194
- if ll != "" {
195
- linters = append (linters , ll )
196
- }
175
+ // check for, report and eliminate leading spaces so we can check for other issues
176
+ if len (leadingSpace ) > 1 {
177
+ issues = append (issues , ExtraLeadingSpace {
178
+ BaseIssue : base ,
179
+ })
197
180
}
198
- }
199
- if (l .needs & NeedsSpecific ) != 0 {
200
- if len (linters ) == 0 {
201
- issues = append (issues , NotSpecific {BaseIssue : base })
181
+
182
+ if (l .needs & NeedsMachineOnly ) != 0 && len (leadingSpace ) > 0 {
183
+ issues = append (issues , NotMachine {BaseIssue : base })
202
184
}
203
- }
204
185
205
- // when detecting unused directives, we send all the directives through and filter them out in the nolint processor
206
- if l .needs & NeedsUnused != 0 {
207
- if len (linters ) == 0 {
208
- issues = append (issues , UnusedCandidate {BaseIssue : base })
209
- } else {
210
- for _ , linter := range linters {
211
- issues = append (issues , UnusedCandidate {BaseIssue : base , ExpectedLinter : linter })
186
+ fullMatches := fullDirectivePattern .FindStringSubmatch (comment .Text )
187
+ if len (fullMatches ) == 0 {
188
+ issues = append (issues , ParseError {BaseIssue : base })
189
+ continue
190
+ }
191
+
192
+ lintersText , explanation := fullMatches [1 ], fullMatches [2 ]
193
+ var linters []string
194
+ if len (lintersText ) > 0 {
195
+ lls := strings .Split (lintersText [1 :], "," )
196
+ linters = make ([]string , 0 , len (lls ))
197
+ for _ , ll := range lls {
198
+ ll = strings .TrimSpace (ll )
199
+ if ll != "" {
200
+ linters = append (linters , ll )
201
+ }
212
202
}
213
203
}
214
- }
215
204
216
- if (l .needs & NeedsExplanation ) != 0 && (explanation == "" || strings .TrimSpace (explanation ) == "//" ) {
217
- needsExplanation := len (linters ) == 0 // if no linters are mentioned, we must have explanation
218
- // otherwise, check if we are excluding all of the mentioned linters
219
- for _ , ll := range linters {
220
- if ! l .excludeByLinter [ll ] { // if a linter does require explanation
221
- needsExplanation = true
222
- break
205
+ if (l .needs & NeedsSpecific ) != 0 {
206
+ if len (linters ) == 0 {
207
+ issues = append (issues , NotSpecific {BaseIssue : base })
223
208
}
224
209
}
225
- if needsExplanation {
226
- fullDirectiveWithoutExplanation := trailingBlankExplanation .ReplaceAllString (c .List [0 ].Text , "" )
227
- issues = append (issues , NoExplanation {
228
- BaseIssue : base ,
229
- fullDirectiveWithoutExplanation : fullDirectiveWithoutExplanation ,
230
- })
210
+
211
+ // when detecting unused directives, we send all the directives through and filter them out in the nolint processor
212
+ if (l .needs & NeedsUnused ) != 0 {
213
+ if len (linters ) == 0 {
214
+ issues = append (issues , UnusedCandidate {BaseIssue : base })
215
+ } else {
216
+ for _ , linter := range linters {
217
+ issues = append (issues , UnusedCandidate {BaseIssue : base , ExpectedLinter : linter })
218
+ }
219
+ }
220
+ }
221
+
222
+ if (l .needs & NeedsExplanation ) != 0 && (explanation == "" || strings .TrimSpace (explanation ) == "//" ) {
223
+ needsExplanation := len (linters ) == 0 // if no linters are mentioned, we must have explanation
224
+ // otherwise, check if we are excluding all of the mentioned linters
225
+ for _ , ll := range linters {
226
+ if ! l .excludeByLinter [ll ] { // if a linter does require explanation
227
+ needsExplanation = true
228
+ break
229
+ }
230
+ }
231
+
232
+ if needsExplanation {
233
+ fullDirectiveWithoutExplanation := trailingBlankExplanation .ReplaceAllString (comment .Text , "" )
234
+ issues = append (issues , NoExplanation {
235
+ BaseIssue : base ,
236
+ fullDirectiveWithoutExplanation : fullDirectiveWithoutExplanation ,
237
+ })
238
+ }
231
239
}
232
240
}
233
241
}
234
242
}
235
243
}
236
- return issues , nil
237
- }
238
-
239
- func getText (c * ast.CommentGroup ) string {
240
- var text string
241
- for _ , comment := range c .List {
242
- if ! directiveOnlyPattern .MatchString (comment .Text ) {
243
- continue
244
- }
245
-
246
- text = strings .TrimSpace (strings .TrimPrefix (comment .Text , "//" ))
247
- break
248
- }
249
244
250
- return text
245
+ return issues , nil
251
246
}
0 commit comments