Skip to content

Commit 327489b

Browse files
committed
ignore lines containing nolint:consistent directives
1 parent 72d335c commit 327489b

19 files changed

+117
-35
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ See below for a complete list of checks.
4646
This analyzer works similar to [go-consistent], but with explicit configuration of checks instead of
4747
auto-detection, which should make it faster.
4848

49+
The `nolint:consistent` directive can be used to ignore warnings on a particular line of code,
50+
for example:
51+
52+
```go
53+
_ = make([]int, 0) //nolint:consistent
54+
55+
_ = make([]int, 0) //nolint:consistent // human-readable explanation here
56+
```
57+
4958

5059
List of Checks
5160
--------------

andnot.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ func checkAndNotExpr(pass *analysis.Pass, expr *ast.BinaryExpr, mode string) {
2929
return
3030
}
3131

32-
pass.Reportf(expr.Pos(), "use AND-NOT operator instead of AND operator with complement expression")
32+
reportf(pass, expr.Pos(), "use AND-NOT operator instead of AND operator with complement expression")
3333

3434
case andNOTsANDComp:
3535
if expr.Op != token.AND_NOT {
3636
return
3737
}
3838

39-
pass.Reportf(expr.Pos(), "use AND operator with complement expression instead of AND-NOT operator")
39+
reportf(pass, expr.Pos(), "use AND operator with complement expression instead of AND-NOT operator")
4040
}
4141
}
4242

@@ -59,13 +59,13 @@ func checkAndNotAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, mode strin
5959
return
6060
}
6161

62-
pass.Reportf(stmt.Pos(), "use AND-NOT assignment instead of AND assignment with complement expression")
62+
reportf(pass, stmt.Pos(), "use AND-NOT assignment instead of AND assignment with complement expression")
6363

6464
case andNOTsANDComp:
6565
if stmt.Tok != token.AND_NOT_ASSIGN {
6666
return
6767
}
6868

69-
pass.Reportf(stmt.Pos(), "use AND assignment with complement expression instead of AND-NOT assignment")
69+
reportf(pass, stmt.Pos(), "use AND assignment with complement expression instead of AND-NOT assignment")
7070
}
7171
}

consistent.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,55 @@ func filesToIgnore(pass *analysis.Pass, cfg *configuration) []*ast.File {
300300
return files
301301
}
302302

303+
func reportf(pass *analysis.Pass, pos token.Pos, format string, args ...any) {
304+
if noLintDirectivePos(pass, pos) {
305+
return
306+
}
307+
308+
pass.Reportf(pos, format, args...)
309+
}
310+
311+
func noLintDirectivePos(pass *analysis.Pass, pos token.Pos) bool {
312+
line := pass.Fset.Position(pos).Line
313+
314+
for _, file := range pass.Files {
315+
if pos < file.FileStart || pos > file.FileEnd {
316+
continue
317+
}
318+
319+
for _, comment := range file.Comments {
320+
if pass.Fset.Position(comment.Pos()).Line < line {
321+
continue
322+
}
323+
324+
return noLintDirective(comment.List[0].Text)
325+
}
326+
}
327+
328+
return false
329+
}
330+
331+
func noLintDirective(comment string) bool {
332+
if !strings.HasPrefix(comment, "//nolint:") {
333+
return false
334+
}
335+
336+
comment = comment[9:]
337+
338+
secondaryCommentPos := strings.Index(comment, "//")
339+
if secondaryCommentPos >= 0 {
340+
comment = comment[:secondaryCommentPos]
341+
}
342+
343+
for _, p := range strings.Split(comment, ",") {
344+
if strings.TrimSpace(p) == "consistent" {
345+
return true
346+
}
347+
}
348+
349+
return false
350+
}
351+
303352
func isFuncDefinition(typ *ast.FuncType, decls []*ast.FuncDecl, lits []*ast.FuncLit) bool {
304353
for _, decl := range decls {
305354
if decl.Type == typ {

emptyifaces.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func checkEmptyIfaceAny(pass *analysis.Pass, node ast.Node) {
3737
return
3838
}
3939

40-
pass.Reportf(node.Pos(), "use any instead of interface{}")
40+
reportf(pass, node.Pos(), "use any instead of interface{}")
4141
}
4242

4343
func checkEmptyIfaceIface(pass *analysis.Pass, node ast.Node) {
@@ -56,5 +56,5 @@ func checkEmptyIfaceIface(pass *analysis.Pass, node ast.Node) {
5656
return
5757
}
5858

59-
pass.Reportf(typ.Pos(), "use interface{} instead of any")
59+
reportf(pass, typ.Pos(), "use interface{} instead of any")
6060
}

fieldlist.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func checkFieldList(pass *analysis.Pass, fields *ast.FieldList, fieldTypePlural
2222
case fieldListExplicit:
2323
for _, f := range fields.List {
2424
if len(f.Names) > 1 {
25-
pass.Reportf(fields.Pos(), "declare the type of %s explicitly", fieldTypePlural)
25+
reportf(pass, fields.Pos(), "declare the type of %s explicitly", fieldTypePlural)
2626
break
2727
}
2828
}
@@ -38,7 +38,7 @@ func checkFieldList(pass *analysis.Pass, fields *ast.FieldList, fieldTypePlural
3838
prevTyp := pass.TypesInfo.TypeOf(list[i].Type)
3939

4040
if typ == prevTyp {
41-
pass.Reportf(fields.Pos(), "declare the type of similar consecutive %s only once", fieldTypePlural)
41+
reportf(pass, fields.Pos(), "declare the type of similar consecutive %s only once", fieldTypePlural)
4242
break
4343
}
4444
}

floatlits.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ func checkFloatLit(pass *analysis.Pass, lit *ast.BasicLit, mode string) {
3333

3434
switch implicit := dotPos == 0; {
3535
case mode == floatLitsExplicit && implicit:
36-
pass.Reportf(lit.Pos(), "add zero before decimal point in floating-point literal")
36+
reportf(pass, lit.Pos(), "add zero before decimal point in floating-point literal")
3737
case mode == floatLitsImplicit && !implicit && strings.TrimLeft(value[:dotPos], "0") == "":
38-
pass.Reportf(lit.Pos(), "remove zero before decimal point in floating-point literal")
38+
reportf(pass, lit.Pos(), "remove zero before decimal point in floating-point literal")
3939
}
4040
}

functypeparams.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ func checkParamsFuncType(pass *analysis.Pass, typ *ast.FuncType, mode string) {
1717

1818
switch {
1919
case namedFields(typ.Params) && mode == funcTypeParamsUnnamed:
20-
pass.Reportf(typ.Pos(), "use unnamed function type parameters")
20+
reportf(pass, typ.Pos(), "use unnamed function type parameters")
2121
return
2222

2323
case unnamedFields(typ.Params) && mode != flagIgnore && mode != funcTypeParamsUnnamed:
24-
pass.Reportf(typ.Pos(), "use named function type parameters")
24+
reportf(pass, typ.Pos(), "use named function type parameters")
2525
return
2626
}
2727

hexlits.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ func checkHexLit(pass *analysis.Pass, lit *ast.BasicLit, mode string) {
2828

2929
switch {
3030
case mode == hexLitsLower && strings.ToLower(val) != val:
31-
pass.Reportf(lit.Pos(), "use lowercase digits in hex literal")
31+
reportf(pass, lit.Pos(), "use lowercase digits in hex literal")
3232
case mode == hexLitsUpper && strings.ToUpper(val) != val:
33-
pass.Reportf(lit.Pos(), "use uppercase digits in hex literal")
33+
reportf(pass, lit.Pos(), "use uppercase digits in hex literal")
3434
}
3535
}
3636

labelsregexp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ func checkLabel(pass *analysis.Pass, stmt *ast.LabeledStmt, regexp regexpValue)
1515
return
1616
}
1717

18-
pass.Reportf(stmt.Label.Pos(), "change label to match regular expression: %s", regexp.s)
18+
reportf(pass, stmt.Label.Pos(), "change label to match regular expression: %s", regexp.s)
1919
}

lenchecks.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,28 @@ func checkLenCheck(pass *analysis.Pass, expr *ast.BinaryExpr, mode string) { //n
3939
case lenChecksEqualZero:
4040
if (oper == token.LEQ && litInt == 0) ||
4141
(oper == token.LSS && litInt == 1) {
42-
pass.Reportf(expr.Pos(), "check if %s is 0 instead", fun)
42+
reportf(pass, expr.Pos(), "check if %s is 0 instead", fun)
4343
}
4444

4545
if (oper == token.GTR && litInt == 0) ||
4646
(oper == token.GEQ && litInt == 1) {
47-
pass.Reportf(expr.Pos(), "check if %s is not 0 instead", fun)
47+
reportf(pass, expr.Pos(), "check if %s is not 0 instead", fun)
4848
}
4949

5050
case lenChecksCompareZero:
5151
if (oper == token.NEQ && litInt == 0) ||
5252
(oper == token.GEQ && litInt == 1) ||
5353
(oper == token.EQL && litInt == 0) ||
5454
(oper == token.LSS && litInt == 1) {
55-
pass.Reportf(expr.Pos(), "compare %s to 0 instead", fun)
55+
reportf(pass, expr.Pos(), "compare %s to 0 instead", fun)
5656
}
5757

5858
case lenChecksCompareOne:
5959
if (oper == token.NEQ && litInt == 0) ||
6060
(oper == token.GTR && litInt == 0) ||
6161
(oper == token.EQL && litInt == 0) ||
6262
(oper == token.LEQ && litInt == 0) {
63-
pass.Reportf(expr.Pos(), "compare %s to 1 instead", fun)
63+
reportf(pass, expr.Pos(), "compare %s to 1 instead", fun)
6464
}
6565
}
6666
}

0 commit comments

Comments
 (0)