Skip to content
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

add consistent linter #2778

Closed
wants to merge 13 commits into from
Closed
49 changes: 49 additions & 0 deletions .golangci.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,53 @@ linters-settings:
first-strong-isolate: false
pop-directional-isolate: false

consistent:
# check function/method parameter type (ignore/explicit/implicit)
# Default: explicit
params: explicit
# check function/method return value types (ignore/explicit/implicit)
# Default: explicit
returns: explicit
# check function type parameter types (ignore/explicit/implicit)
# Default: explicit
type-params: explicit
# check single import declarations (ignore/bare/parens)
# Default: bare
single-imports: bare
# check allocations using new (ignore/literal/new)
# Default: literal
new-allocs: literal
# check allocations using make (ignore/literal/make)
# Default: literal
make-allocs: literal
# check upper/lowercase in hex literals (ignore/lower/upper)
# Default: lower
hex-lits: lower
# check range checks (ignore/left/center)
# Default: left
range-checks: left
# check AND-NOT expressions (ignore/and-not/and-comp)
# Default: and-not
and-nots: and-not
# check floating-point literals (ignore/explicit/implicit)
# Default: explicit
float-lits: explicit
# check len/cap checks (ignore/equal-zero/compare-zero/compare-one)
# Default: equal-zero
len-checks: equal-zero
# check switch case clauses (ignore/comma/or)
# Default: comma
switch-cases: comma
# check switch default clauses (ignore/last/first)
# Default: last
switch-defaults: last
# check empty interfaces (ignore/any/iface)
# Default: any
empty-ifaces: any
# check labels against regexp ('' to ignore)
# Default: ^[a-z][a-zA-Z0-9]*$
labels-regexp: ^[a-z][a-zA-Z0-9]*$

cyclop:
# The maximal code complexity to report.
# Default: 10
Expand Down Expand Up @@ -1881,6 +1928,7 @@ linters:
- asciicheck
- bidichk
- bodyclose
- consistent
- containedctx
- contextcheck
- cyclop
Expand Down Expand Up @@ -1984,6 +2032,7 @@ linters:
- asciicheck
- bidichk
- bodyclose
- consistent
- containedctx
- contextcheck
- cyclop
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/ashanbrown/forbidigo v1.3.0
github.com/ashanbrown/makezero v1.1.1
github.com/bkielbasa/cyclop v1.2.0
github.com/blizzy78/consistent v0.2.2
github.com/blizzy78/varnamelen v0.8.0
github.com/bombsimon/wsl/v3 v3.3.0
github.com/breml/bidichk v0.2.3
Expand Down Expand Up @@ -172,7 +173,7 @@ require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.17.0 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d // indirect
golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
Expand Down
7 changes: 5 additions & 2 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions pkg/config/linters_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ var defaultLintersSettings = LintersSettings{
type LintersSettings struct {
Asasalint AsasalintSettings
BiDiChk BiDiChkSettings
Consistent ConsistentSettings
Cyclop Cyclop
Decorder DecorderSettings
Depguard DepGuardSettings
Expand Down Expand Up @@ -207,6 +208,24 @@ type BiDiChkSettings struct {
PopDirectionalIsolate bool `mapstructure:"pop-directional-isolate"`
}

type ConsistentSettings struct {
Params string `mapstructure:"params"`
Returns string `mapstructure:"returns"`
TypeParams string `mapstructure:"type-params"`
SingleImports string `mapstructure:"single-imports"`
NewAllocs string `mapstructure:"new-allocs"`
MakeAllocs string `mapstructure:"make-allocs"`
HexLits string `mapstructure:"hex-lits"`
RangeChecks string `mapstructure:"range-checks"`
AndNOTs string `mapstructure:"and-nots"`
FloatLits string `mapstructure:"float-lits"`
LenChecks string `mapstructure:"len-checks"`
SwitchCases string `mapstructure:"switch-cases"`
SwitchDefaults string `mapstructure:"switch-defaults"`
EmptyIfaces string `mapstructure:"empty-ifaces"`
LabelsRegexp string `mapstructure:"labels-regexp"`
}

type Cyclop struct {
MaxComplexity int `mapstructure:"max-complexity"`
PackageAverage float64 `mapstructure:"package-average"`
Expand Down
64 changes: 64 additions & 0 deletions pkg/golinters/consistent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package golinters

import (
"github.com/blizzy78/consistent"
"golang.org/x/tools/go/analysis"

"github.com/golangci/golangci-lint/pkg/config"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)

func NewConsistent(settings *config.ConsistentSettings) *goanalysis.Linter {
cfg := map[string]map[string]interface{}{}

analyzer := consistent.NewAnalyzer()

if settings != nil {
valueMapping := map[string]string{
"and-comp": "andComp",
"and-not": "andNot",
"compare-one": "compareOne",
"compare-zero": "compareZero",
"equal-zero": "equalZero",
}

analyzerCfg := map[string]interface{}{}

set := func(key string, value string) {
if v, ok := valueMapping[value]; ok {
value = v
}

if value == "" {
return
}

analyzerCfg[key] = value
}

set("params", settings.Params)
set("returns", settings.Returns)
set("typeParams", settings.TypeParams)
set("singleImports", settings.SingleImports)
set("newAllocs", settings.NewAllocs)
set("makeAllocs", settings.MakeAllocs)
set("hexLits", settings.HexLits)
set("rangeChecks", settings.RangeChecks)
set("andNOTs", settings.AndNOTs)
set("floatLits", settings.FloatLits)
set("lenChecks", settings.LenChecks)
set("switchCases", settings.SwitchCases)
set("switchDefaults", settings.SwitchDefaults)
set("emptyIfaces", settings.EmptyIfaces)
set("labelsRegexp", settings.LabelsRegexp)

cfg[analyzer.Name] = analyzerCfg
}

return goanalysis.NewLinter(
analyzer.Name,
"checks that common constructs are used consistently",
[]*analysis.Analyzer{analyzer},
cfg,
).WithLoadMode(goanalysis.LoadModeTypesInfo)
}
8 changes: 8 additions & 0 deletions pkg/lint/lintersdb/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
var (
asasalintCfg *config.AsasalintSettings
bidichkCfg *config.BiDiChkSettings
consistentCfg *config.ConsistentSettings
cyclopCfg *config.Cyclop
decorderCfg *config.DecorderSettings
depGuardCfg *config.DepGuardSettings
Expand Down Expand Up @@ -176,6 +177,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
if m.cfg != nil {
asasalintCfg = &m.cfg.LintersSettings.Asasalint
bidichkCfg = &m.cfg.LintersSettings.BiDiChk
consistentCfg = &m.cfg.LintersSettings.Consistent
cyclopCfg = &m.cfg.LintersSettings.Cyclop
decorderCfg = &m.cfg.LintersSettings.Decorder
depGuardCfg = &m.cfg.LintersSettings.Depguard
Expand Down Expand Up @@ -293,6 +295,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithPresets(linter.PresetPerformance, linter.PresetBugs).
WithURL("https://github.com/timakin/bodyclose"),

linter.NewConfig(golinters.NewConsistent(consistentCfg)).
WithSince("v1.46.0").
WithPresets(linter.PresetStyle).
WithLoadForGoAnalysis().
WithURL("https://github.com/blizzy78/consistent"),

linter.NewConfig(golinters.NewContainedCtx()).
WithSince("1.44.0").
WithPresets(linter.PresetStyle).
Expand Down
43 changes: 43 additions & 0 deletions test/testdata/consistent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//golangcitest:args -Econsistent
package testdata

import ( // want "remove parens around single import declaration"
"strings"
)

func consistent() {
_ = func(a, b int) {} // want "declare the type of function arguments explicitly"

_ = func() (a, b int) { return 1, 2 } // want "declare the type of function return values explicitly"

_ = new(strings.Builder) // want "use zero-value literal instead of calling new"

_ = make([]int, 0) // want "use slice literal instead of calling make"

_ = 0xABCDE // want "use lowercase digits in hex literal"

x := 5
_ = 1 < x && x < 10 // want "write common term in range expression on the left"

_ = 1 & ^2 // want "use AND-NOT operator instead of AND operator with complement expression"

_ = .5 // want "add zero before decimal point in floating-point literal"

_ = len([]int{}) > 0 // want `check if len is \(not\) 0 instead`

switch {
case 1 < 2 || 3 < 4: // want "separate cases with comma instead of using logical OR"
}

switch {
default: // want "move switch default clause to the end"
case 1 < 2:
}

type empty interface{} // want "use any instead of interface{}"

test_loop: // want `change label to match regular expression: .*`
for {
break test_loop
}
}