Skip to content

Commit 909f628

Browse files
committed
Add linter for nolint
Linter can check that nolint statements are properly formatted and also that all nolint statements are used.
1 parent 4a3e9fd commit 909f628

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+766
-63
lines changed

.golangci.example.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,17 @@ linters-settings:
224224
simple: true
225225
range-loops: true # Report preallocation suggestions on range loops, true by default
226226
for-loops: false # Report preallocation suggestions on for loops, false by default
227+
nolintlint:
228+
# Enable to ensure that nolint directives are all used. Default is true.
229+
allow-unused: false
230+
# Disable to ensure that nolint directives don't have a leading space. Default is true.
231+
allow-leading-space: true
232+
# Exclude following linters from requiring an explanation. Default is [].
233+
allow-no-explanation: []
234+
# Enable to require an explanation after each nolint directive. Default is false.
235+
require-explanation: true
236+
# Enable to require an explanation after each nolint directive. Default is false.
237+
require-specific: true
227238
rowserrcheck:
228239
packages:
229240
- github.com/jmoiron/sqlx

.golangci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ linters-settings:
5454
suggest-new: true
5555
misspell:
5656
locale: US
57+
nolintlint:
58+
allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space)
59+
allow-unused: false # report any unused nolint directives
60+
require-explanation: false # don't require an explanation for nolint directives
61+
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
5762

5863
linters:
5964
# please, do not use `enable-all`: it's deprecated and will be removed soon.
@@ -84,6 +89,7 @@ linters:
8489
- lll
8590
- misspell
8691
- nakedret
92+
- nolintlint
8793
- rowserrcheck
8894
- scopelint
8995
- staticcheck

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ maligned: Tool to detect Go structs that would take less memory if their fields
231231
misspell: Finds commonly misspelled English words in comments [fast: true, auto-fix: true]
232232
nakedret: Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false]
233233
nestif: Reports deeply nested if statements [fast: true, auto-fix: false]
234+
nolintlint: Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]
234235
prealloc: Finds slice declarations that could potentially be preallocated [fast: true, auto-fix: false]
235236
rowserrcheck: checks whether Err of rows is checked successfully [fast: true, auto-fix: false]
236237
scopelint: Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false]
@@ -496,6 +497,7 @@ golangci-lint help linters
496497
- [godot](https://github.com/tetafro/godot) - Check if comments end in a period
497498
- [testpackage](https://github.com/maratori/testpackage) - linter that makes you use a separate _test package
498499
- [nestif](https://github.com/nakabonne/nestif) - Reports deeply nested if statements
500+
- [nolintlint](https://github.com/golangci-lint/pkg/golinters/nolintlint) - Reports ill-formed or insufficient nolint directives
499501
500502
## Configuration
501503
@@ -843,6 +845,17 @@ linters-settings:
843845
simple: true
844846
range-loops: true # Report preallocation suggestions on range loops, true by default
845847
for-loops: false # Report preallocation suggestions on for loops, false by default
848+
nolintlint:
849+
# Enable to ensure that nolint directives are all used. Default is true.
850+
allow-unused: false
851+
# Disable to ensure that nolint directives don't have a leading space. Default is true.
852+
allow-leading-space: true
853+
# Exclude following linters from requiring an explanation. Default is [].
854+
allow-no-explanation: []
855+
# Enable to require an explanation after each nolint directive. Default is false.
856+
require-explanation: true
857+
# Enable to require an explanation after each nolint directive. Default is false.
858+
require-specific: true
846859
rowserrcheck:
847860
packages:
848861
- github.com/jmoiron/sqlx
@@ -1032,6 +1045,11 @@ linters-settings:
10321045
suggest-new: true
10331046
misspell:
10341047
locale: US
1048+
nolintlint:
1049+
allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space)
1050+
allow-unused: false # report any unused nolint directives
1051+
require-explanation: false # don't require an explanation for nolint directives
1052+
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
10351053
10361054
linters:
10371055
# please, do not use `enable-all`: it's deprecated and will be removed soon.
@@ -1062,6 +1080,7 @@ linters:
10621080
- lll
10631081
- misspell
10641082
- nakedret
1083+
- nolintlint
10651084
- rowserrcheck
10661085
- scopelint
10671086
- staticcheck
@@ -1298,6 +1317,7 @@ Thanks to developers and authors of used linters:
12981317
- [tetafro](https://github.com/tetafro)
12991318
- [maratori](https://github.com/maratori)
13001319
- [nakabonne](https://github.com/nakabonne)
1320+
- [golangci-lint](https://github.com/golangci-lint)
13011321
13021322
## Changelog
13031323

pkg/commands/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ func (e *Executor) executeRun(_ *cobra.Command, args []string) {
441441
// to be removed when deadline is finally decommissioned
442442
func (e *Executor) setTimeoutToDeadlineIfOnlyDeadlineIsSet() {
443443
//lint:ignore SA1019 We want to promoted the deprecated config value when needed
444-
deadlineValue := e.cfg.Run.Deadline // nolint: staticcheck
444+
deadlineValue := e.cfg.Run.Deadline // nolint:staticcheck
445445
if deadlineValue != 0 && e.cfg.Run.Timeout == defaultTimeout {
446446
e.cfg.Run.Timeout = deadlineValue
447447
}

pkg/config/config.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ type LintersSettings struct {
235235
Godot GodotSettings
236236
Testpackage TestpackageSettings
237237
Nestif NestifSettings
238+
NoLintLint NoLintLintSettings
238239

239240
Custom map[string]CustomLinterSettings
240241
}
@@ -316,6 +317,14 @@ type GodotSettings struct {
316317
CheckAll bool `mapstructure:"check-all"`
317318
}
318319

320+
type NoLintLintSettings struct {
321+
RequireExplanation bool `mapstructure:"require-explanation"`
322+
AllowLeadingSpace bool `mapstructure:"allow-leading-space"`
323+
RequireSpecific bool `mapstructure:"require-specific"`
324+
AllowNoExplanation []string `mapstructure:"allow-no-explanation"`
325+
AllowUnused bool `mapstructure:"allow-unused"`
326+
}
327+
319328
type TestpackageSettings struct {
320329
SkipRegexp string `mapstructure:"skip-regexp"`
321330
}
@@ -324,7 +333,6 @@ type NestifSettings struct {
324333
MinComplexity int `mapstructure:"min-complexity"`
325334
}
326335

327-
//nolint:gomnd
328336
var defaultLintersSettings = LintersSettings{
329337
Lll: LllSettings{
330338
LineLength: 120,
@@ -363,6 +371,12 @@ var defaultLintersSettings = LintersSettings{
363371
ForceCuddleErrCheckAndAssign: false,
364372
ForceCaseTrailingWhitespaceLimit: 0,
365373
},
374+
NoLintLint: NoLintLintSettings{
375+
RequireExplanation: false,
376+
AllowLeadingSpace: true,
377+
RequireSpecific: false,
378+
AllowUnused: false,
379+
},
366380
Testpackage: TestpackageSettings{
367381
SkipRegexp: `(export|internal)_test\.go`,
368382
},

pkg/golinters/deadcode.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func NewDeadcode() *goanalysis.Linter {
2828
}
2929
res := make([]goanalysis.Issue, 0, len(issues))
3030
for _, i := range issues {
31-
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
31+
res = append(res, goanalysis.NewIssue(&result.Issue{
3232
Pos: i.Pos,
3333
Text: fmt.Sprintf("%s is unused", formatCode(i.UnusedIdentName, nil)),
3434
FromLinter: linterName,

pkg/golinters/depguard.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func NewDepguard() *goanalysis.Linter {
9494
if userSuppliedMsgSuffix != "" {
9595
userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix
9696
}
97-
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
97+
res = append(res, goanalysis.NewIssue(&result.Issue{
9898
Pos: i.Position,
9999
Text: fmt.Sprintf("%s %s%s", formatCode(i.PackageName, lintCtx.Cfg), msgSuffix, userSuppliedMsgSuffix),
100100
FromLinter: linterName,

pkg/golinters/dupl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func NewDupl() *goanalysis.Linter {
5757
text := fmt.Sprintf("%d-%d lines are duplicate of %s",
5858
i.From.LineStart(), i.From.LineEnd(),
5959
formatCode(dupl, lintCtx.Cfg))
60-
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
60+
res = append(res, goanalysis.NewIssue(&result.Issue{
6161
Pos: token.Position{
6262
Filename: i.From.Filename(),
6363
Line: i.From.LineStart(),

pkg/golinters/errcheck.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func NewErrcheck() *goanalysis.Linter {
5959
} else {
6060
text = "Error return value is not checked"
6161
}
62-
issues = append(issues, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
62+
issues = append(issues, goanalysis.NewIssue(&result.Issue{
6363
FromLinter: linterName,
6464
Text: text,
6565
Pos: i.Pos,

pkg/golinters/funlen.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func NewFunlen() *goanalysis.Linter {
4242

4343
res := make([]goanalysis.Issue, len(issues))
4444
for k, i := range issues {
45-
res[k] = goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
45+
res[k] = goanalysis.NewIssue(&result.Issue{
4646
Pos: token.Position{
4747
Filename: i.Pos.Filename,
4848
Line: i.Pos.Line,

0 commit comments

Comments
 (0)