@@ -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,98 +141,102 @@ 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
- text := c .Text ()
149
- matches := directiveOnlyPattern .FindStringSubmatch (text )
150
- if len (matches ) == 0 {
151
- continue
152
- }
153
- directive := matches [1 ]
148
+ for _ , comment := range c .List {
149
+ if ! commentPattern .MatchString (comment .Text ) {
150
+ continue
151
+ }
154
152
155
- // check for a space between the "//" and the directive
156
- leadingSpaceMatches := leadingSpacePattern .FindStringSubmatch (c .List [0 ].Text ) // c.Text() doesn't have all leading space
157
- if len (leadingSpaceMatches ) == 0 {
158
- continue
159
- }
160
- leadingSpace := leadingSpaceMatches [1 ]
153
+ // check for a space between the "//" and the directive
154
+ leadingSpaceMatches := leadingSpacePattern .FindStringSubmatch (comment .Text )
161
155
162
- directiveWithOptionalLeadingSpace := directive
163
- if len (leadingSpace ) > 0 {
164
- directiveWithOptionalLeadingSpace = " " + directive
165
- }
156
+ var leadingSpace string
157
+ if len (leadingSpaceMatches ) > 0 {
158
+ leadingSpace = leadingSpaceMatches [ 1 ]
159
+ }
166
160
167
- base := BaseIssue {
168
- fullDirective : c . List [ 0 ]. Text ,
169
- directiveWithOptionalLeadingSpace : directiveWithOptionalLeadingSpace ,
170
- position : fset . Position ( c . Pos ()),
171
- }
161
+ directiveWithOptionalLeadingSpace := comment . Text
162
+ if len ( leadingSpace ) > 0 {
163
+ split := strings . Split ( strings . SplitN ( comment . Text , ":" , 2 )[ 0 ], "//" )
164
+ directiveWithOptionalLeadingSpace = "// " + strings . TrimSpace ( split [ 1 ])
165
+ }
172
166
173
- // check for, report and eliminate leading spaces so we can check for other issues
174
- if leadingSpace != "" && leadingSpace != " " {
175
- issues = append (issues , ExtraLeadingSpace {
176
- BaseIssue : base ,
177
- })
178
- }
167
+ base := BaseIssue {
168
+ fullDirective : comment .Text ,
169
+ directiveWithOptionalLeadingSpace : directiveWithOptionalLeadingSpace ,
170
+ position : fset .Position (comment .Pos ()),
171
+ }
179
172
180
- if (l .needs & NeedsMachineOnly ) != 0 && strings .HasPrefix (directiveWithOptionalLeadingSpace , " " ) {
181
- issues = append (issues , NotMachine {BaseIssue : base })
182
- }
173
+ // check for, report and eliminate leading spaces so we can check for other issues
174
+ if len (leadingSpace ) > 1 {
175
+ issues = append (issues , ExtraLeadingSpace {BaseIssue : base })
176
+ }
183
177
184
- fullMatches := fullDirectivePattern .FindStringSubmatch (c .List [0 ].Text )
185
- if len (fullMatches ) == 0 {
186
- issues = append (issues , ParseError {BaseIssue : base })
187
- continue
188
- }
189
- lintersText , explanation := fullMatches [1 ], fullMatches [2 ]
190
- var linters []string
191
- if len (lintersText ) > 0 {
192
- lls := strings .Split (lintersText [1 :], "," )
193
- linters = make ([]string , 0 , len (lls ))
194
- for _ , ll := range lls {
195
- ll = strings .TrimSpace (ll )
196
- if ll != "" {
197
- linters = append (linters , ll )
198
- }
178
+ if (l .needs & NeedsMachineOnly ) != 0 && len (leadingSpace ) > 0 {
179
+ issues = append (issues , NotMachine {BaseIssue : base })
199
180
}
200
- }
201
- if (l .needs & NeedsSpecific ) != 0 {
202
- if len (linters ) == 0 {
203
- issues = append (issues , NotSpecific {BaseIssue : base })
181
+
182
+ fullMatches := fullDirectivePattern .FindStringSubmatch (comment .Text )
183
+ if len (fullMatches ) == 0 {
184
+ issues = append (issues , ParseError {BaseIssue : base })
185
+ continue
204
186
}
205
- }
206
187
207
- // when detecting unused directives, we send all the directives through and filter them out in the nolint processor
208
- if l .needs & NeedsUnused != 0 {
209
- if len (linters ) == 0 {
210
- issues = append (issues , UnusedCandidate {BaseIssue : base })
211
- } else {
212
- for _ , linter := range linters {
213
- issues = append (issues , UnusedCandidate {BaseIssue : base , ExpectedLinter : linter })
188
+ lintersText , explanation := fullMatches [1 ], fullMatches [2 ]
189
+ var linters []string
190
+ if len (lintersText ) > 0 {
191
+ lls := strings .Split (lintersText [1 :], "," )
192
+ linters = make ([]string , 0 , len (lls ))
193
+ for _ , ll := range lls {
194
+ ll = strings .TrimSpace (ll )
195
+ if ll != "" {
196
+ linters = append (linters , ll )
197
+ }
214
198
}
215
199
}
216
- }
217
200
218
- if (l .needs & NeedsExplanation ) != 0 && (explanation == "" || strings .TrimSpace (explanation ) == "//" ) {
219
- needsExplanation := len (linters ) == 0 // if no linters are mentioned, we must have explanation
220
- // otherwise, check if we are excluding all of the mentioned linters
221
- for _ , ll := range linters {
222
- if ! l .excludeByLinter [ll ] { // if a linter does require explanation
223
- needsExplanation = true
224
- break
201
+ if (l .needs & NeedsSpecific ) != 0 {
202
+ if len (linters ) == 0 {
203
+ issues = append (issues , NotSpecific {BaseIssue : base })
225
204
}
226
205
}
227
- if needsExplanation {
228
- fullDirectiveWithoutExplanation := trailingBlankExplanation .ReplaceAllString (c .List [0 ].Text , "" )
229
- issues = append (issues , NoExplanation {
230
- BaseIssue : base ,
231
- fullDirectiveWithoutExplanation : fullDirectiveWithoutExplanation ,
232
- })
206
+
207
+ // when detecting unused directives, we send all the directives through and filter them out in the nolint processor
208
+ if (l .needs & NeedsUnused ) != 0 {
209
+ if len (linters ) == 0 {
210
+ issues = append (issues , UnusedCandidate {BaseIssue : base })
211
+ } else {
212
+ for _ , linter := range linters {
213
+ issues = append (issues , UnusedCandidate {BaseIssue : base , ExpectedLinter : linter })
214
+ }
215
+ }
216
+ }
217
+
218
+ if (l .needs & NeedsExplanation ) != 0 && (explanation == "" || strings .TrimSpace (explanation ) == "//" ) {
219
+ needsExplanation := len (linters ) == 0 // if no linters are mentioned, we must have explanation
220
+ // otherwise, check if we are excluding all of the mentioned linters
221
+ for _ , ll := range linters {
222
+ if ! l .excludeByLinter [ll ] { // if a linter does require explanation
223
+ needsExplanation = true
224
+ break
225
+ }
226
+ }
227
+
228
+ if needsExplanation {
229
+ fullDirectiveWithoutExplanation := trailingBlankExplanation .ReplaceAllString (comment .Text , "" )
230
+ issues = append (issues , NoExplanation {
231
+ BaseIssue : base ,
232
+ fullDirectiveWithoutExplanation : fullDirectiveWithoutExplanation ,
233
+ })
234
+ }
233
235
}
234
236
}
235
237
}
236
238
}
237
239
}
240
+
238
241
return issues , nil
239
242
}
0 commit comments