Add maintidx linter (#2435)

This commit is contained in:
Hiroyuki Yagihashi 2022-01-18 21:50:52 +09:00 committed by GitHub
parent b2eef6e165
commit e3d0247ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 452 additions and 0 deletions

View File

@ -590,6 +590,12 @@ linters-settings:
# tab width in spaces. Default to 1.
tab-width: 1
maintidx:
# Show functions with maintainability index lower than N.
# A high index indicates better maintainability (it's kind of the opposite of complexity).
# default: 20
under: 100
makezero:
# Allow only slices initialized with a length of zero. Default is false.
always: false

1
go.mod
View File

@ -91,6 +91,7 @@ require (
github.com/ultraware/whitespace v0.0.4
github.com/uudashr/gocognit v1.0.5
github.com/valyala/quicktemplate v1.7.0
github.com/yagipy/maintidx v1.0.0
github.com/yeya24/promlinter v0.1.0
gitlab.com/bosi/decorder v0.2.1
golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da

2
go.sum generated
View File

@ -799,6 +799,8 @@ github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM=
github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk=
github.com/yeya24/promlinter v0.1.0 h1:goWULN0jH5Yajmu/K+v1xCqIREeB+48OiJ2uu2ssc7U=
github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=

View File

@ -51,6 +51,9 @@ var defaultLintersSettings = LintersSettings{
LineLength: 120,
TabWidth: 1,
},
MaintIdx: MaintIdxSettings{
Under: 20,
},
Nakedret: NakedretSettings{
MaxFuncLines: 30,
},
@ -128,6 +131,7 @@ type LintersSettings struct {
ImportAs ImportAsSettings
Ireturn IreturnSettings
Lll LllSettings
MaintIdx MaintIdxSettings
Makezero MakezeroSettings
Maligned MalignedSettings
Misspell MisspellSettings
@ -389,6 +393,10 @@ type LllSettings struct {
TabWidth int `mapstructure:"tab-width"`
}
type MaintIdxSettings struct {
Under int `mapstructure:"under"`
}
type MakezeroSettings struct {
Always bool
}

32
pkg/golinters/maintidx.go Normal file
View File

@ -0,0 +1,32 @@
package golinters
import (
"github.com/yagipy/maintidx"
"golang.org/x/tools/go/analysis"
"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)
func NewMaintIdx(cfg *config.MaintIdxSettings) *goanalysis.Linter {
analyzer := maintidx.Analyzer
cfgMap := map[string]map[string]interface{}{
analyzer.Name: {"under": 20},
}
if cfg != nil {
cfgMap[analyzer.Name] = map[string]interface{}{
"under": cfg.Under,
}
}
return goanalysis.NewLinter(
analyzer.Name,
analyzer.Doc,
[]*analysis.Analyzer{
analyzer,
},
cfgMap,
).WithLoadMode(goanalysis.LoadModeSyntax)
}

View File

@ -114,6 +114,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
var ifshortCfg *config.IfshortSettings
var importAsCfg *config.ImportAsSettings
var ireturnCfg *config.IreturnSettings
var maintIdxCfg *config.MaintIdxSettings
var nilNilCfg *config.NilNilSettings
var nlreturnCfg *config.NlreturnSettings
var predeclaredCfg *config.PredeclaredSettings
@ -143,6 +144,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
ifshortCfg = &m.cfg.LintersSettings.Ifshort
importAsCfg = &m.cfg.LintersSettings.ImportAs
ireturnCfg = &m.cfg.LintersSettings.Ireturn
maintIdxCfg = &m.cfg.LintersSettings.MaintIdx
nilNilCfg = &m.cfg.LintersSettings.NilNil
nlreturnCfg = &m.cfg.LintersSettings.Nlreturn
predeclaredCfg = &m.cfg.LintersSettings.Predeclared
@ -439,6 +441,11 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithSince("v1.8.0").
WithPresets(linter.PresetStyle),
linter.NewConfig(golinters.NewMaintIdx(maintIdxCfg)).
WithSince("v1.44.0").
WithPresets(linter.PresetComplexity).
WithURL("https://github.com/yagipy/maintidx"),
linter.NewConfig(golinters.NewMakezero()).
WithSince("v1.34.0").
WithPresets(linter.PresetStyle, linter.PresetBugs).

View File

@ -0,0 +1,3 @@
linters-settings:
maintidx:
under: 100

196
test/testdata/maintidx.go vendored Normal file
View File

@ -0,0 +1,196 @@
//args: -Emaintidx
package testdata
func over20() {
}
func under20() { // ERROR "Function name: under20, Cyclomatic Complexity: 76, Halstead Volume: 1636.00, Maintainability Index: 17"
for true {
if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
}
}
}

197
test/testdata/maintidx_under_100.go vendored Normal file
View File

@ -0,0 +1,197 @@
// args: -Emaintidx
// config_path: testdata/configs/maintidx_under_100.yml
package testdata
func over20() { // ERROR "Function name: over20, Cyclomatic Complexity: 1, Halstead Volume: 8.00, Maintainability Index: 86"
}
func under20() { // ERROR "Function name: under20, Cyclomatic Complexity: 76, Halstead Volume: 1636.00, Maintainability Index: 17"
for true {
if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else if false {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
} else {
if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else if false {
n := 0
switch n {
case 0:
case 1:
default:
}
} else {
n := 0
switch n {
case 0:
case 1:
default:
}
}
}
}
}