diff --git a/.golangci.example.yml b/.golangci.example.yml index 8e8c8ba7e486..e39ecd062f92 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -190,6 +190,14 @@ linters-settings: gocyclo: # minimal code complexity to report, 30 by default (but we recommend 10-20) min-complexity: 10 + + cyclop: + # the maximal code complexity to report + max-complexity: 10 + # the maximal average package complexity. If it's higher than 0.0 (float) the check is enabled (default 0.0) + package-average: 0.0 + # should ignore tests (default false) + skip-tests: false godot: # comments to be checked: `declarations`, `toplevel`, or `all` scope: declarations diff --git a/go.mod b/go.mod index 0e0e4ea29b14..f321a6d18856 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/alexkohler/prealloc v0.0.0-20210204145425-77a5b5dd9799 github.com/ashanbrown/forbidigo v1.1.0 github.com/ashanbrown/makezero v0.0.0-20201205152432-7b7cdbb3025a + github.com/bkielbasa/cyclop v1.2.0 github.com/bombsimon/wsl/v3 v3.1.0 github.com/charithe/durationcheck v0.0.3 github.com/daixiang0/gci v0.2.8 diff --git a/go.sum b/go.sum index 2e1d4d63be94..84c2950e8ccc 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= +github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/bombsimon/wsl/v3 v3.1.0 h1:E5SRssoBgtVFPcYWUOFJEcgaySgdtTNYzsSKDOY7ss8= github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= diff --git a/pkg/config/config.go b/pkg/config/config.go index 2a0050a2e6d1..314c81fd2db6 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -183,6 +183,11 @@ type LintersSettings struct { Gocyclo struct { MinComplexity int `mapstructure:"min-complexity"` } + Cyclop struct { + MaxComplexity int `mapstructure:"max-complexity"` + PackageAverage float64 `mapstructure:"package-average"` + SkipTests bool `mapstructure:"skip-tests"` + } Varcheck struct { CheckExportedFields bool `mapstructure:"exported-fields"` } diff --git a/pkg/golinters/cyclop.go b/pkg/golinters/cyclop.go new file mode 100644 index 000000000000..df1dd4835467 --- /dev/null +++ b/pkg/golinters/cyclop.go @@ -0,0 +1,21 @@ +package golinters + +import ( + "github.com/bkielbasa/cyclop/pkg/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +const cyclopName = "cyclop" + +func NewCyclop() *goanalysis.Linter { + return goanalysis.NewLinter( + cyclopName, + "checks function and package cyclomatic complexity", + []*analysis.Analyzer{ + analyzer.NewAnalyzer(), + }, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 0960a3d8de7f..499563d8726c 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -194,6 +194,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { linter.NewConfig(golinters.NewGocyclo()). WithPresets(linter.PresetComplexity). WithURL("https://github.com/alecthomas/gocyclo"), + linter.NewConfig(golinters.NewCyclop()). + WithLoadForGoAnalysis(). + WithPresets(linter.PresetComplexity). + WithURL("https://github.com/bkielbasa/cyclop"), linter.NewConfig(golinters.NewGocognit()). WithPresets(linter.PresetComplexity). WithURL("https://github.com/uudashr/gocognit"), diff --git a/test/testdata/cyclop.go b/test/testdata/cyclop.go new file mode 100644 index 000000000000..2551758f62d3 --- /dev/null +++ b/test/testdata/cyclop.go @@ -0,0 +1,30 @@ +// args: -Ecyclop +package testdata + +import "math" + +func cyclopComplexFunc() { // ERROR "calculated cyclomatic complexity for function cyclopComplexFunc is 11, max is 10" + i := math.MaxInt8 + if i > 2 { + if i > 2 { + } + if i > 2 { + } + if i > 2 { + } + if i > 2 { + } + } else { + if i > 2 { + } + if i > 2 { + } + if i > 2 { + } + if i > 2 { + } + } + + if i > 2 { + } +}