From 12ed5facc9ebeba6df415119efd1735b9268cef7 Mon Sep 17 00:00:00 2001 From: Ludovic Fernandez Date: Fri, 30 Apr 2021 22:28:50 +0200 Subject: [PATCH] staticcheck: configurable Go version. (#1946) --- .golangci.example.yml | 23 ++++++++++++------ pkg/config/linters_settings.go | 13 +++++++---- pkg/golinters/gosimple.go | 6 ++--- pkg/golinters/megacheck.go | 30 ------------------------ pkg/golinters/staticcheck.go | 6 ++--- pkg/golinters/staticcheck_common.go | 33 ++++++++++++++++++++++++++ pkg/golinters/stylecheck.go | 6 ++--- pkg/golinters/unused.go | 12 ++++++---- pkg/lint/lintersdb/manager.go | 36 ++++++++++++++++++----------- 9 files changed, 96 insertions(+), 69 deletions(-) delete mode 100644 pkg/golinters/megacheck.go create mode 100644 pkg/golinters/staticcheck_common.go diff --git a/.golangci.example.yml b/.golangci.example.yml index dad9449e2fa4..237b878333fa 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -358,6 +358,10 @@ linters-settings: per_char_threshold: "3.0" truncate: "32" + gosimple: + # Select the Go version to target. The default is '1.13'. + go: "1.15" + govet: # report about shadowed variables check-shadowing: true @@ -488,6 +492,14 @@ linters-settings: - name: indent-error-flow severity: warning + staticcheck: + # Select the Go version to target. The default is '1.13'. + go: "1.15" + + stylecheck: + # Select the Go version to target. The default is '1.13'. + go: "1.15" + tagliatelle: # check the struck tag name case case: @@ -531,11 +543,8 @@ linters-settings: check-exported: false unused: - # treat code as a program (not a library) and report unused exported identifiers; default is false. - # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: - # if it's called for subdir of a project it can't find funcs usages. All text editor integrations - # with golangci-lint call it on a directory with the changed file. - check-exported: false + # Select the Go version to target. The default is '1.13'. + go: "1.15" whitespace: multi-if: false # Enforces newlines (or comments) after every multi-line if statement @@ -556,8 +565,8 @@ linters-settings: force-short-decl-cuddling: false strict-append: true - # The custom section can be used to define linter plugins to be loaded at runtime. See README doc - # for more info. + # The custom section can be used to define linter plugins to be loaded at runtime. + # See README doc for more info. custom: # Each custom linter should have a unique name. example: diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 2d12c209cbcd..5f6ac45083fd 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -104,6 +104,7 @@ type LintersSettings struct { GoModDirectives GoModDirectivesSettings Gomodguard GoModGuardSettings Gosec GoSecSettings + Gosimple StaticCheckSettings Govet GovetSettings Ifshort IfshortSettings ImportAs ImportAsSettings @@ -119,12 +120,14 @@ type LintersSettings struct { Promlinter PromlinterSettings Revive ReviveSettings RowsErrCheck RowsErrCheckSettings + Staticcheck StaticCheckSettings Structcheck StructCheckSettings + Stylecheck StaticCheckSettings Tagliatelle TagliatelleSettings Testpackage TestpackageSettings Thelper ThelperSettings Unparam UnparamSettings - Unused UnusedSettings + Unused StaticCheckSettings Varcheck VarCheckSettings Whitespace WhitespaceSettings WSL WSLSettings @@ -376,6 +379,10 @@ type RowsErrCheckSettings struct { Packages []string } +type StaticCheckSettings struct { + GoVersion string `mapstructure:"go"` +} + type StructCheckSettings struct { CheckExportedFields bool `mapstructure:"exported-fields"` } @@ -414,10 +421,6 @@ type UnparamSettings struct { Algo string } -type UnusedSettings struct { - CheckExported bool `mapstructure:"check-exported"` -} - type VarCheckSettings struct { CheckExportedFields bool `mapstructure:"exported-fields"` } diff --git a/pkg/golinters/gosimple.go b/pkg/golinters/gosimple.go index 788fc8c63892..82e30b37d294 100644 --- a/pkg/golinters/gosimple.go +++ b/pkg/golinters/gosimple.go @@ -3,12 +3,12 @@ package golinters import ( "honnef.co/go/tools/simple" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -func NewGosimple() *goanalysis.Linter { - analyzers := analyzersMapToSlice(simple.Analyzers) - setAnalyzersGoVersion(analyzers) +func NewGosimple(settings *config.StaticCheckSettings) *goanalysis.Linter { + analyzers := setupStaticCheckAnalyzers(simple.Analyzers, settings) return goanalysis.NewLinter( "gosimple", diff --git a/pkg/golinters/megacheck.go b/pkg/golinters/megacheck.go deleted file mode 100644 index 85621f6fb77d..000000000000 --- a/pkg/golinters/megacheck.go +++ /dev/null @@ -1,30 +0,0 @@ -package golinters - -import ( - "fmt" - - "golang.org/x/tools/go/analysis" - - "github.com/golangci/golangci-lint/pkg/logutils" -) - -var debugf = logutils.Debug("megacheck") - -func analyzersMapToSlice(m map[string]*analysis.Analyzer) []*analysis.Analyzer { - var ret []*analysis.Analyzer - for _, v := range m { - ret = append(ret, v) - } - return ret -} - -func setAnalyzersGoVersion(analyzers []*analysis.Analyzer) { - const goVersion = 13 // TODO - for _, a := range analyzers { - if v := a.Flags.Lookup("go"); v != nil { - if err := v.Value.Set(fmt.Sprintf("1.%d", goVersion)); err != nil { - debugf("Failed to set go version: %s", err) - } - } - } -} diff --git a/pkg/golinters/staticcheck.go b/pkg/golinters/staticcheck.go index 33aa921e6b01..b0c2717bfabd 100644 --- a/pkg/golinters/staticcheck.go +++ b/pkg/golinters/staticcheck.go @@ -3,12 +3,12 @@ package golinters import ( "honnef.co/go/tools/staticcheck" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -func NewStaticcheck() *goanalysis.Linter { - analyzers := analyzersMapToSlice(staticcheck.Analyzers) - setAnalyzersGoVersion(analyzers) +func NewStaticcheck(settings *config.StaticCheckSettings) *goanalysis.Linter { + analyzers := setupStaticCheckAnalyzers(staticcheck.Analyzers, settings) return goanalysis.NewLinter( "staticcheck", diff --git a/pkg/golinters/staticcheck_common.go b/pkg/golinters/staticcheck_common.go new file mode 100644 index 000000000000..f0338032d001 --- /dev/null +++ b/pkg/golinters/staticcheck_common.go @@ -0,0 +1,33 @@ +package golinters + +import ( + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/logutils" +) + +var debugf = logutils.Debug("megacheck") + +func setupStaticCheckAnalyzers(m map[string]*analysis.Analyzer, settings *config.StaticCheckSettings) []*analysis.Analyzer { + var ret []*analysis.Analyzer + for _, v := range m { + setAnalyzerGoVersion(v, settings) + ret = append(ret, v) + } + return ret +} + +func setAnalyzerGoVersion(a *analysis.Analyzer, settings *config.StaticCheckSettings) { + // TODO: uses "1.13" for backward compatibility, but in the future (v2) must be set by using build.Default.ReleaseTags like staticcheck. + goVersion := "1.13" + if settings != nil && settings.GoVersion != "" { + goVersion = settings.GoVersion + } + + if v := a.Flags.Lookup("go"); v != nil { + if err := v.Value.Set(goVersion); err != nil { + debugf("Failed to set go version: %s", err) + } + } +} diff --git a/pkg/golinters/stylecheck.go b/pkg/golinters/stylecheck.go index 5a076951af7c..175553accc32 100644 --- a/pkg/golinters/stylecheck.go +++ b/pkg/golinters/stylecheck.go @@ -3,12 +3,12 @@ package golinters import ( "honnef.co/go/tools/stylecheck" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -func NewStylecheck() *goanalysis.Linter { - analyzers := analyzersMapToSlice(stylecheck.Analyzers) - setAnalyzersGoVersion(analyzers) +func NewStylecheck(settings *config.StaticCheckSettings) *goanalysis.Linter { + analyzers := setupStaticCheckAnalyzers(stylecheck.Analyzers, settings) return goanalysis.NewLinter( "stylecheck", diff --git a/pkg/golinters/unused.go b/pkg/golinters/unused.go index cb5613417d8b..639929ded28d 100644 --- a/pkg/golinters/unused.go +++ b/pkg/golinters/unused.go @@ -7,12 +7,17 @@ import ( "golang.org/x/tools/go/analysis" "honnef.co/go/tools/unused" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/result" ) -func NewUnused() *goanalysis.Linter { +type UnusedSettings struct { + GoVersion string +} + +func NewUnused(settings *config.StaticCheckSettings) *goanalysis.Linter { const name = "unused" var mu sync.Mutex @@ -49,13 +54,12 @@ func NewUnused() *goanalysis.Linter { }, } - analyzers := []*analysis.Analyzer{analyzer} - setAnalyzersGoVersion(analyzers) + setAnalyzerGoVersion(analyzer, settings) lnt := goanalysis.NewLinter( name, "Checks Go code for unused constants, variables, functions and types", - analyzers, + []*analysis.Analyzer{analyzer}, nil, ).WithIssuesReporter(func(lintCtx *linter.Context) []goanalysis.Issue { return resIssues diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 80101224e1f5..3f1d3a074238 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -113,6 +113,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { var goModDirectivesCfg *config.GoModDirectivesSettings var tagliatelleCfg *config.TagliatelleSettings var gosecCfg *config.GoSecSettings + var gosimpleCfg *config.StaticCheckSettings + var staticcheckCfg *config.StaticCheckSettings + var stylecheckCfg *config.StaticCheckSettings + var unusedCfg *config.StaticCheckSettings if m.cfg != nil { govetCfg = &m.cfg.LintersSettings.Govet @@ -129,6 +133,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { goModDirectivesCfg = &m.cfg.LintersSettings.GoModDirectives tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle gosecCfg = &m.cfg.LintersSettings.Gosec + gosimpleCfg = &m.cfg.LintersSettings.Gosimple + staticcheckCfg = &m.cfg.LintersSettings.Staticcheck + stylecheckCfg = &m.cfg.LintersSettings.Stylecheck + unusedCfg = &m.cfg.LintersSettings.Unused } const megacheckName = "megacheck" @@ -166,13 +174,13 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetBugs, linter.PresetSQL). WithURL("https://github.com/jingyugao/rowserrcheck"), - linter.NewConfig(golinters.NewStaticcheck()). + linter.NewConfig(golinters.NewStaticcheck(staticcheckCfg)). WithSince("v1.0.0"). WithLoadForGoAnalysis(). WithPresets(linter.PresetBugs, linter.PresetMetaLinter). WithAlternativeNames(megacheckName). WithURL("https://staticcheck.io/"), - linter.NewConfig(golinters.NewUnused()). + linter.NewConfig(golinters.NewUnused(unusedCfg)). WithSince("v1.20.0"). WithLoadForGoAnalysis(). WithPresets(linter.PresetUnused). @@ -180,14 +188,14 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { ConsiderSlow(). WithChangeTypes(). WithURL("https://github.com/dominikh/go-tools/tree/master/unused"), - linter.NewConfig(golinters.NewGosimple()). + linter.NewConfig(golinters.NewGosimple(gosimpleCfg)). WithSince("v1.20.0"). WithLoadForGoAnalysis(). WithPresets(linter.PresetStyle). WithAlternativeNames(megacheckName). WithURL("https://github.com/dominikh/go-tools/tree/master/simple"), - linter.NewConfig(golinters.NewStylecheck()). + linter.NewConfig(golinters.NewStylecheck(stylecheckCfg)). WithSince("v1.20.0"). WithLoadForGoAnalysis(). WithPresets(linter.PresetStyle). @@ -499,16 +507,16 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { } enabledByDefault := map[string]bool{ - golinters.NewGovet(nil).Name(): true, - golinters.NewErrcheck().Name(): true, - golinters.NewStaticcheck().Name(): true, - golinters.NewUnused().Name(): true, - golinters.NewGosimple().Name(): true, - golinters.NewStructcheck().Name(): true, - golinters.NewVarcheck().Name(): true, - golinters.NewIneffassign().Name(): true, - golinters.NewDeadcode().Name(): true, - golinters.NewTypecheck().Name(): true, + golinters.NewGovet(nil).Name(): true, + golinters.NewErrcheck().Name(): true, + golinters.NewStaticcheck(staticcheckCfg).Name(): true, + golinters.NewUnused(unusedCfg).Name(): true, + golinters.NewGosimple(gosimpleCfg).Name(): true, + golinters.NewStructcheck().Name(): true, + golinters.NewVarcheck().Name(): true, + golinters.NewIneffassign().Name(): true, + golinters.NewDeadcode().Name(): true, + golinters.NewTypecheck().Name(): true, } return enableLinterConfigs(lcs, func(lc *linter.Config) bool { return enabledByDefault[lc.Name()]