Skip to content

Commit 0108387

Browse files
committed
Add nestif linter
1 parent 3fd6db7 commit 0108387

File tree

14 files changed

+466
-0
lines changed

14 files changed

+466
-0
lines changed

.golangci.example.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ linters-settings:
9696
gocognit:
9797
# minimal code complexity to report, 30 by default (but we recommend 10-20)
9898
min-complexity: 10
99+
nestif:
100+
# minimal complexity of if statements to report, 5 by default
101+
min-complexity: 4
99102
goconst:
100103
# minimal length of string constant, 3 by default
101104
min-len: 3

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ lll: Reports long lines [fast: true, auto-fix: false]
230230
maligned: Tool to detect Go structs that would take less memory if their fields were sorted [fast: true, auto-fix: false]
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]
233+
nestif: Reports deeply nested if statements [fast: true, auto-fix: false]
233234
prealloc: Finds slice declarations that could potentially be preallocated [fast: true, auto-fix: false]
234235
rowserrcheck: checks whether Err of rows is checked successfully [fast: true, auto-fix: false]
235236
scopelint: Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false]
@@ -490,6 +491,7 @@ golangci-lint help linters
490491
- [goprintffuncname](https://github.com/jirfag/go-printf-func-name) - Checks that printf-like functions are named with `f` at the end
491492
- [gomnd](https://github.com/tommy-muehle/go-mnd) - An analyzer to detect magic numbers.
492493
- [godot](https://github.com/tetafro/godot) - Check if comments end in a period
494+
- [nestif](https://github.com/nakabonne/nestif) - Reports deeply nested if statements
493495
494496
## Configuration
495497
@@ -708,6 +710,9 @@ linters-settings:
708710
gocognit:
709711
# minimal code complexity to report, 30 by default (but we recommend 10-20)
710712
min-complexity: 10
713+
nestif:
714+
# minimal complexity of if statements to report, 5 by default
715+
min-complexity: 4
711716
goconst:
712717
# minimal length of string constant, 3 by default
713718
min-len: 3
@@ -1267,6 +1272,7 @@ Thanks to developers and authors of used linters:
12671272
- [jirfag](https://github.com/jirfag)
12681273
- [tommy-muehle](https://github.com/tommy-muehle)
12691274
- [tetafro](https://github.com/tetafro)
1275+
- [nakabonne](https://github.com/nakabonne)
12701276
12711277
## Changelog
12721278

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ require (
2929
github.com/mattn/go-colorable v0.1.4
3030
github.com/mitchellh/go-homedir v1.1.0
3131
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b
32+
github.com/nakabonne/nestif v0.3.0
3233
github.com/pkg/errors v0.8.1
3334
github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83
3435
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada // v2.19.8

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
183183
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
184184
github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
185185
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
186+
github.com/nakabonne/nestif v0.3.0 h1:+yOViDGhg8ygGrmII72nV9B/zGxY188TYpfolntsaPw=
187+
github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c=
186188
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E=
187189
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
188190
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=

pkg/config/config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ type LintersSettings struct {
199199
Dogsled DogsledSettings
200200
Gocognit GocognitSettings
201201
Godot GodotSettings
202+
Nestif NestifSettings
202203

203204
Custom map[string]CustomLinterSettings
204205
}
@@ -280,6 +281,10 @@ type GodotSettings struct {
280281
CheckAll bool `mapstructure:"check-all"`
281282
}
282283

284+
type NestifSettings struct {
285+
MinComplexity int `mapstructure:"min-complexity"`
286+
}
287+
283288
//nolint:gomnd
284289
var defaultLintersSettings = LintersSettings{
285290
Lll: LllSettings{
@@ -319,6 +324,9 @@ var defaultLintersSettings = LintersSettings{
319324
ForceCuddleErrCheckAndAssign: false,
320325
ForceCaseTrailingWhitespaceLimit: 0,
321326
},
327+
Nestif: NestifSettings{
328+
MinComplexity: 5,
329+
},
322330
}
323331

324332
type CustomLinterSettings struct {

pkg/golinters/nestif.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package golinters
2+
3+
import (
4+
"sort"
5+
"sync"
6+
7+
"github.com/nakabonne/nestif"
8+
"golang.org/x/tools/go/analysis"
9+
10+
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
11+
"github.com/golangci/golangci-lint/pkg/lint/linter"
12+
"github.com/golangci/golangci-lint/pkg/result"
13+
)
14+
15+
const nestifName = "nestif"
16+
17+
func NewNestif() *goanalysis.Linter {
18+
var mu sync.Mutex
19+
var resIssues []goanalysis.Issue
20+
21+
analyzer := &analysis.Analyzer{
22+
Name: goanalysis.TheOnlyAnalyzerName,
23+
Doc: goanalysis.TheOnlyanalyzerDoc,
24+
}
25+
return goanalysis.NewLinter(
26+
nestifName,
27+
"Reports deeply nested if statements",
28+
[]*analysis.Analyzer{analyzer},
29+
nil,
30+
).WithContextSetter(func(lintCtx *linter.Context) {
31+
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
32+
checker := &nestif.Checker{
33+
MinComplexity: lintCtx.Settings().Nestif.MinComplexity,
34+
}
35+
var issues []nestif.Issue
36+
for _, f := range pass.Files {
37+
issues = append(issues, checker.Check(f, pass.Fset)...)
38+
}
39+
if len(issues) == 0 {
40+
return nil, nil
41+
}
42+
43+
sort.Slice(issues, func(i, j int) bool {
44+
return issues[i].Complexity > issues[j].Complexity
45+
})
46+
47+
res := make([]goanalysis.Issue, 0, len(issues))
48+
for _, i := range issues {
49+
res = append(res, goanalysis.NewIssue(&result.Issue{ //nolint:scopelint
50+
Pos: i.Pos,
51+
Text: i.Message,
52+
FromLinter: nestifName,
53+
}, pass))
54+
}
55+
56+
mu.Lock()
57+
resIssues = append(resIssues, res...)
58+
mu.Unlock()
59+
60+
return nil, nil
61+
}
62+
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
63+
return resIssues
64+
}).WithLoadMode(goanalysis.LoadModeSyntax)
65+
}

pkg/lint/lintersdb/manager.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
250250
linter.NewConfig(golinters.NewGodot()).
251251
WithPresets(linter.PresetStyle).
252252
WithURL("https://github.com/tetafro/godot"),
253+
linter.NewConfig(golinters.NewNestif()).
254+
WithPresets(linter.PresetComplexity).
255+
WithURL("https://github.com/nakabonne/nestif"),
253256
}
254257

255258
isLocalRun := os.Getenv("GOLANGCI_COM_RUN") == ""

test/testdata/nestif.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//args: -Enestif
2+
//config: linters-settings.nestif.min-complexity=1
3+
package testdata
4+
5+
func _() {
6+
var b1, b2, b3, b4 bool
7+
8+
if b1 { // ERROR "`if b1` is deeply nested \(complexity: 1\)"
9+
if b2 { // +1
10+
}
11+
}
12+
13+
if b1 { // ERROR "`if b1` is deeply nested \(complexity: 3\)"
14+
if b2 { // +1
15+
if b3 { // +2
16+
}
17+
}
18+
}
19+
20+
if b1 { // ERROR "`if b1` is deeply nested \(complexity: 5\)"
21+
if b2 { // +1
22+
} else if b3 { // +1
23+
if b4 { // +2
24+
}
25+
} else { // +1
26+
}
27+
}
28+
29+
if b1 { // ERROR "`if b1` is deeply nested \(complexity: 9\)"
30+
if b2 { // +1
31+
if b3 { // +2
32+
}
33+
}
34+
35+
if b2 { // +1
36+
if b3 { // +2
37+
if b4 { // +3
38+
}
39+
}
40+
}
41+
}
42+
43+
if b1 == b2 == b3 { // ERROR "`if b1 == b2 == b3` is deeply nested \(complexity: 1\)"
44+
if b4 { // +1
45+
}
46+
}
47+
}

vendor/github.com/nakabonne/nestif/.gitignore

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/nakabonne/nestif/LICENSE

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/nakabonne/nestif/README.md

Lines changed: 122 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/nakabonne/nestif/go.mod

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)