Skip to content

Commit 0f8df04

Browse files
committed
Feature: support nolint range
f f
1 parent 625445b commit 0f8df04

File tree

1 file changed

+97
-6
lines changed

1 file changed

+97
-6
lines changed

Diff for: pkg/result/processors/nolint.go

+97-6
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func (i *ignoredRange) doesMatch(issue *result.Issue) bool {
4646

4747
// handle possible unused nolint directives
4848
// nolintlint generates potential issues for every nolint directive and they are filtered out here
49-
if issue.FromLinter == golinters.NolintlintName && issue.ExpectNoLint {
49+
if issue.FromLinter == golinters.NolintlintName && issue.ExpectNoLint {
5050
if issue.ExpectedNoLintLinter != "" {
5151
return i.matchedIssueFromLinter[issue.ExpectedNoLintLinter]
5252
}
@@ -123,7 +123,7 @@ func (p *Nolint) getOrCreateFileData(i *result.Issue) (*fileData, error) {
123123
}
124124

125125
func (p *Nolint) buildIgnoredRangesForFile(f *ast.File, fset *token.FileSet, filePath string) []ignoredRange {
126-
inlineRanges := p.extractFileCommentsInlineRanges(fset, f.Comments...)
126+
inlineRanges := p.extractFileCommentsRanges(fset, f.Comments...)
127127
nolintDebugf("file %s: inline nolint ranges are %+v", filePath, inlineRanges)
128128

129129
if len(inlineRanges) == 0 {
@@ -218,20 +218,106 @@ func (e *rangeExpander) Visit(node ast.Node) ast.Visitor {
218218
return e
219219
}
220220

221-
func (p *Nolint) extractFileCommentsInlineRanges(fset *token.FileSet, comments ...*ast.CommentGroup) []ignoredRange {
221+
func (p *Nolint) extractFileCommentsRanges(fset *token.FileSet, comments ...*ast.CommentGroup) []ignoredRange {
222222
var ret []ignoredRange
223+
ignoredRangeMap := map[string]*ignoredRange{}
223224
for _, g := range comments {
224225
for _, c := range g.List {
225-
ir := p.extractInlineRangeFromComment(c.Text, g, fset)
226+
ignoredRangeMap = p.extractRangeBeginFromComment(c.Text, g, fset, ignoredRangeMap)
227+
228+
var ir *ignoredRange
229+
ignoredRangeMap, ir = p.extractRangeEndFromComment(c.Text, g, fset, ignoredRangeMap)
230+
if ir != nil {
231+
ret = append(ret, *ir)
232+
}
233+
234+
ir = p.extractInlineRangeFromComment(c.Text, g, fset)
226235
if ir != nil {
227236
ret = append(ret, *ir)
228237
}
229238
}
230239
}
231240

241+
for _, v := range ignoredRangeMap {
242+
ret = append(ret, *v)
243+
}
244+
232245
return ret
233246
}
234247

248+
func (p *Nolint) extractRangeBeginFromComment(
249+
text string,
250+
g ast.Node,
251+
fset *token.FileSet,
252+
ignoredRangeMap map[string]*ignoredRange,
253+
) map[string]*ignoredRange {
254+
text = strings.TrimLeft(text, "/ ")
255+
if strings.HasPrefix(text, "nolint-begin:") {
256+
linterItems := strings.Split(strings.TrimPrefix(text, "nolint-begin:"), ",")
257+
for _, l := range linterItems {
258+
l = strings.TrimSpace(l)
259+
if l == "" {
260+
continue
261+
}
262+
_, ok := ignoredRangeMap[l]
263+
if ok {
264+
// If there are two consecutive nolint-begins, the first nolint-begin is valid.
265+
continue
266+
}
267+
ignoredRangeMap[l] = &ignoredRange{
268+
Range: result.Range{
269+
From: fset.Position(g.Pos()).Line,
270+
To: fset.File(g.End()).LineCount(),
271+
},
272+
linters: []string{l},
273+
matchedIssueFromLinter: make(map[string]bool),
274+
}
275+
}
276+
return ignoredRangeMap
277+
}
278+
279+
if strings.HasPrefix(text, "nolint-begin") {
280+
key := ""
281+
ignoredRangeMap[key] = &ignoredRange{
282+
Range: result.Range{
283+
From: fset.Position(g.Pos()).Line,
284+
To: fset.File(g.End()).LineCount(),
285+
},
286+
linters: nil,
287+
matchedIssueFromLinter: make(map[string]bool),
288+
}
289+
}
290+
return ignoredRangeMap
291+
}
292+
293+
func (p *Nolint) extractRangeEndFromComment(
294+
text string,
295+
g ast.Node,
296+
fset *token.FileSet,
297+
ignoredRangeMap map[string]*ignoredRange,
298+
) (map[string]*ignoredRange, *ignoredRange) {
299+
text = strings.TrimLeft(text, "/ ")
300+
if strings.HasPrefix(text, "nolint-end") {
301+
var linters []string
302+
if strings.HasPrefix(text, "nolint-end:") {
303+
linters = strings.Split(strings.TrimPrefix(text, "nolint-end:"), ",")
304+
} else {
305+
linters = []string{""}
306+
}
307+
308+
for _, linter := range linters {
309+
linter = strings.TrimSpace(linter)
310+
ir := ignoredRangeMap[linter]
311+
if ir != nil {
312+
ir.Range.To = fset.Position(g.End()).Line
313+
delete(ignoredRangeMap, linter)
314+
return ignoredRangeMap, ir
315+
}
316+
}
317+
}
318+
return ignoredRangeMap, nil
319+
}
320+
235321
func (p *Nolint) extractInlineRangeFromComment(text string, g ast.Node, fset *token.FileSet) *ignoredRange {
236322
text = strings.TrimLeft(text, "/ ")
237323
if !strings.HasPrefix(text, "nolint") {
@@ -251,13 +337,18 @@ func (p *Nolint) extractInlineRangeFromComment(text string, g ast.Node, fset *to
251337
}
252338
}
253339

254-
if !strings.HasPrefix(text, "nolint:") {
340+
text = strings.Split(text, "//")[0] // allow another comment after this comment
341+
text = strings.TrimSpace(text)
342+
if text == "nolint" {
255343
return buildRange(nil) // ignore all linters
256344
}
257345

346+
if !strings.HasPrefix(text, "nolint:") {
347+
return nil
348+
}
349+
258350
// ignore specific linters
259351
var linters []string
260-
text = strings.Split(text, "//")[0] // allow another comment after this comment
261352
linterItems := strings.Split(strings.TrimPrefix(text, "nolint:"), ",")
262353
for _, linter := range linterItems {
263354
linterName := strings.ToLower(strings.TrimSpace(linter))

0 commit comments

Comments
 (0)