Skip to content

Add nolintlint linter as internal linter #837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .golangci.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,17 @@ linters-settings:
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: false # Report preallocation suggestions on for loops, false by default
nolintlint:
# Enable to ensure that nolint directives are all used. Default is true.
allow-unused: false
# Disable to ensure that nolint directives don't have a leading space. Default is true.
allow-leading-space: true
# Exclude following linters from requiring an explanation. Default is [].
allow-no-explanation: []
# Enable to require an explanation after each nolint directive. Default is false.
require-explanation: true
# Enable to require an explanation after each nolint directive. Default is false.
require-specific: true
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
Expand Down
6 changes: 6 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ linters-settings:
suggest-new: true
misspell:
locale: US
nolintlint:
allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space)
allow-unused: false # report any unused nolint directives
require-explanation: false # don't require an explanation for nolint directives
require-specific: false # don't require nolint directives to be specific about which linter is being skipped

linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
Expand Down Expand Up @@ -84,6 +89,7 @@ linters:
- lll
- misspell
- nakedret
- nolintlint
- rowserrcheck
- scopelint
- staticcheck
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ maligned: Tool to detect Go structs that would take less memory if their fields
misspell: Finds commonly misspelled English words in comments [fast: true, auto-fix: true]
nakedret: Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false]
nestif: Reports deeply nested if statements [fast: true, auto-fix: false]
nolintlint: Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]
prealloc: Finds slice declarations that could potentially be preallocated [fast: true, auto-fix: false]
rowserrcheck: checks whether Err of rows is checked successfully [fast: true, auto-fix: false]
scopelint: Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false]
Expand Down Expand Up @@ -496,6 +497,7 @@ golangci-lint help linters
- [godot](https://github.com/tetafro/godot) - Check if comments end in a period
- [testpackage](https://github.com/maratori/testpackage) - linter that makes you use a separate _test package
- [nestif](https://github.com/nakabonne/nestif) - Reports deeply nested if statements
- [nolintlint](https://github.com/golangci-lint/pkg/golinters/nolintlint) - Reports ill-formed or insufficient nolint directives

## Configuration

Expand Down Expand Up @@ -843,6 +845,17 @@ linters-settings:
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: false # Report preallocation suggestions on for loops, false by default
nolintlint:
# Enable to ensure that nolint directives are all used. Default is true.
allow-unused: false
# Disable to ensure that nolint directives don't have a leading space. Default is true.
allow-leading-space: true
# Exclude following linters from requiring an explanation. Default is [].
allow-no-explanation: []
# Enable to require an explanation after each nolint directive. Default is false.
require-explanation: true
# Enable to require an explanation after each nolint directive. Default is false.
require-specific: true
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
Expand Down Expand Up @@ -1032,6 +1045,11 @@ linters-settings:
suggest-new: true
misspell:
locale: US
nolintlint:
allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space)
allow-unused: false # report any unused nolint directives
require-explanation: false # don't require an explanation for nolint directives
require-specific: false # don't require nolint directives to be specific about which linter is being skipped

linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
Expand Down Expand Up @@ -1062,6 +1080,7 @@ linters:
- lll
- misspell
- nakedret
- nolintlint
- rowserrcheck
- scopelint
- staticcheck
Expand Down Expand Up @@ -1298,6 +1317,7 @@ Thanks to developers and authors of used linters:
- [tetafro](https://github.com/tetafro)
- [maratori](https://github.com/maratori)
- [nakabonne](https://github.com/nakabonne)
- [golangci-lint](https://github.com/golangci-lint)

## Changelog

Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ func (e *Executor) executeRun(_ *cobra.Command, args []string) {
// to be removed when deadline is finally decommissioned
func (e *Executor) setTimeoutToDeadlineIfOnlyDeadlineIsSet() {
//lint:ignore SA1019 We want to promoted the deprecated config value when needed
deadlineValue := e.cfg.Run.Deadline // nolint: staticcheck
deadlineValue := e.cfg.Run.Deadline // nolint:staticcheck
if deadlineValue != 0 && e.cfg.Run.Timeout == defaultTimeout {
e.cfg.Run.Timeout = deadlineValue
}
Expand Down
16 changes: 15 additions & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ type LintersSettings struct {
Godot GodotSettings
Testpackage TestpackageSettings
Nestif NestifSettings
NoLintLint NoLintLintSettings

Custom map[string]CustomLinterSettings
}
Expand Down Expand Up @@ -316,6 +317,14 @@ type GodotSettings struct {
CheckAll bool `mapstructure:"check-all"`
}

type NoLintLintSettings struct {
RequireExplanation bool `mapstructure:"require-explanation"`
AllowLeadingSpace bool `mapstructure:"allow-leading-space"`
RequireSpecific bool `mapstructure:"require-specific"`
AllowNoExplanation []string `mapstructure:"allow-no-explanation"`
AllowUnused bool `mapstructure:"allow-unused"`
}

type TestpackageSettings struct {
SkipRegexp string `mapstructure:"skip-regexp"`
}
Expand All @@ -324,7 +333,6 @@ type NestifSettings struct {
MinComplexity int `mapstructure:"min-complexity"`
}

//nolint:gomnd
var defaultLintersSettings = LintersSettings{
Lll: LllSettings{
LineLength: 120,
Expand Down Expand Up @@ -363,6 +371,12 @@ var defaultLintersSettings = LintersSettings{
ForceCuddleErrCheckAndAssign: false,
ForceCaseTrailingWhitespaceLimit: 0,
},
NoLintLint: NoLintLintSettings{
RequireExplanation: false,
AllowLeadingSpace: true,
RequireSpecific: false,
AllowUnused: false,
},
Testpackage: TestpackageSettings{
SkipRegexp: `(export|internal)_test\.go`,
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/deadcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func NewDeadcode() *goanalysis.Linter {
}
res := make([]goanalysis.Issue, 0, len(issues))
for _, i := range issues {
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: i.Pos,
Text: fmt.Sprintf("%s is unused", formatCode(i.UnusedIdentName, nil)),
FromLinter: linterName,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/depguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func NewDepguard() *goanalysis.Linter {
if userSuppliedMsgSuffix != "" {
userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix
}
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: i.Position,
Text: fmt.Sprintf("%s %s%s", formatCode(i.PackageName, lintCtx.Cfg), msgSuffix, userSuppliedMsgSuffix),
FromLinter: linterName,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/dupl.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func NewDupl() *goanalysis.Linter {
text := fmt.Sprintf("%d-%d lines are duplicate of %s",
i.From.LineStart(), i.From.LineEnd(),
formatCode(dupl, lintCtx.Cfg))
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: token.Position{
Filename: i.From.Filename(),
Line: i.From.LineStart(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/errcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func NewErrcheck() *goanalysis.Linter {
} else {
text = "Error return value is not checked"
}
issues = append(issues, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
issues = append(issues, goanalysis.NewIssue(&result.Issue{
FromLinter: linterName,
Text: text,
Pos: i.Pos,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/funlen.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func NewFunlen() *goanalysis.Linter {

res := make([]goanalysis.Issue, len(issues))
for k, i := range issues {
res[k] = goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res[k] = goanalysis.NewIssue(&result.Issue{
Pos: token.Position{
Filename: i.Pos.Filename,
Line: i.Pos.Line,
Expand Down
12 changes: 7 additions & 5 deletions pkg/golinters/goanalysis/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ func NewIssue(i *result.Issue, pass *analysis.Pass) Issue {
}

type EncodingIssue struct {
FromLinter string
Text string
Pos token.Position
LineRange *result.Range
Replacement *result.Replacement
FromLinter string
Text string
Pos token.Position
LineRange *result.Range
Replacement *result.Replacement
ExpectNoLint bool
ExpectedNoLintLinter string
}
26 changes: 15 additions & 11 deletions pkg/golinters/goanalysis/linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,13 @@ func saveIssuesToCache(allPkgs []*packages.Package, pkgsFromCache map[*packages.
for ind := range pkgIssues {
i := &pkgIssues[ind]
encodedIssues = append(encodedIssues, EncodingIssue{
FromLinter: i.FromLinter,
Text: i.Text,
Pos: i.Pos,
LineRange: i.LineRange,
Replacement: i.Replacement,
FromLinter: i.FromLinter,
Text: i.Text,
Pos: i.Pos,
LineRange: i.LineRange,
Replacement: i.Replacement,
ExpectNoLint: i.ExpectNoLint,
ExpectedNoLintLinter: i.ExpectedNoLintLinter,
})
}

Expand Down Expand Up @@ -392,12 +394,14 @@ func loadIssuesFromCache(pkgs []*packages.Package, lintCtx *linter.Context,
issues := make([]result.Issue, 0, len(pkgIssues))
for _, i := range pkgIssues {
issues = append(issues, result.Issue{
FromLinter: i.FromLinter,
Text: i.Text,
Pos: i.Pos,
LineRange: i.LineRange,
Replacement: i.Replacement,
Pkg: pkg,
FromLinter: i.FromLinter,
Text: i.Text,
Pos: i.Pos,
LineRange: i.LineRange,
Replacement: i.Replacement,
Pkg: pkg,
ExpectNoLint: i.ExpectNoLint,
ExpectedNoLintLinter: i.ExpectedNoLintLinter,
})
}
cacheRes.issues = issues
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/goanalysis/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ func (r *runner) analyze(pkgs []*packages.Package, analyzers []*analysis.Analyze
debugf("There are %d initial and %d total packages", len(initialPkgs), len(loadingPackages))
for _, lp := range loadingPackages {
if lp.isInitial {
wg.Add(1) //nolint:gomnd
wg.Add(1)
go func(lp *loadingPackage) {
lp.analyzeRecursive(r.loadMode, loadSem)
wg.Done()
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/gocognit.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func NewGocognit() *goanalysis.Linter {
break // Break as the stats is already sorted from greatest to least
}

res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: s.Pos,
Text: fmt.Sprintf("cognitive complexity %d of func %s is high (> %d)",
s.Complexity, formatCode(s.FuncName, lintCtx.Cfg), lintCtx.Settings().Gocognit.MinComplexity),
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/goconst.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func checkConstants(pass *analysis.Pass, lintCtx *linter.Context) ([]goanalysis.
} else {
textEnd = fmt.Sprintf(", but such constant %s already exists", formatCode(i.MatchingConst, lintCtx.Cfg))
}
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: i.Pos,
Text: textBegin + textEnd,
FromLinter: goconstName,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/gocyclo.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func NewGocyclo() *goanalysis.Linter {
break // Break as the stats is already sorted from greatest to least
}

res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: s.Pos,
Text: fmt.Sprintf("cyclomatic complexity %d of func %s is high (> %d)",
s.Complexity, formatCode(s.FuncName, lintCtx.Cfg), lintCtx.Settings().Gocyclo.MinComplexity),
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/godox.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func NewGodox() *goanalysis.Linter {

res := make([]goanalysis.Issue, len(issues))
for k, i := range issues {
res[k] = goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res[k] = goanalysis.NewIssue(&result.Issue{
Pos: token.Position{
Filename: i.Pos.Filename,
Line: i.Pos.Line,
Expand Down
1 change: 0 additions & 1 deletion pkg/golinters/gofmt_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ func (p *hunkChangesParser) parseDiffLines(h *diffpkg.Hunk) {

lineStr := string(line)

//nolint:gocritic
if strings.HasPrefix(lineStr, "-") {
dl.typ = diffLineDeleted
dl.data = strings.TrimPrefix(lineStr, "-")
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/gomodguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func NewGomodguard() *goanalysis.Linter {
defer mu.Unlock()

for _, err := range gomodguardErrors {
issues = append(issues, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
issues = append(issues, goanalysis.NewIssue(&result.Issue{
FromLinter: gomodguardName,
Pos: err.Position,
Text: err.Reason,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/gosec.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func NewGosec() *goanalysis.Linter {
continue
}

res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: token.Position{
Filename: i.File,
Line: line,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/ineffassign.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func NewIneffassign() *goanalysis.Linter {

res := make([]goanalysis.Issue, 0, len(issues))
for _, i := range issues {
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: i.Pos,
Text: fmt.Sprintf("ineffectual assignment to %s", formatCode(i.IdentName, lintCtx.Cfg)),
FromLinter: ineffassignName,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/interfacer.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func NewInterfacer() *goanalysis.Linter {
res := make([]goanalysis.Issue, 0, len(issues))
for _, i := range issues {
pos := pass.Fset.Position(i.Pos())
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: pos,
Text: i.Message(),
FromLinter: interfacerName,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/maligned.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewMaligned() *goanalysis.Linter {
if lintCtx.Settings().Maligned.SuggestNewOrder {
text += fmt.Sprintf(":\n%s", formatCodeBlock(i.NewStructDef, lintCtx.Cfg))
}
issues = append(issues, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
issues = append(issues, goanalysis.NewIssue(&result.Issue{
Pos: i.Pos,
Text: text,
FromLinter: linterName,
Expand Down
2 changes: 1 addition & 1 deletion pkg/golinters/nestif.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func NewNestif() *goanalysis.Linter {

res := make([]goanalysis.Issue, 0, len(issues))
for _, i := range issues {
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
res = append(res, goanalysis.NewIssue(&result.Issue{
Pos: i.Pos,
Text: i.Message,
FromLinter: nestifName,
Expand Down
Loading