feat: explain typecheck and remove it from the linter list (#3929)

This commit is contained in:
Ludovic Fernandez 2023-06-29 22:40:59 +02:00 committed by GitHub
parent a303529ad3
commit 79c78d6f6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 96 additions and 19 deletions

View File

@ -32,3 +32,22 @@ The same as the Go team (the 2 last minor versions)
Because the first run caches type information. All subsequent runs will be fast. Because the first run caches type information. All subsequent runs will be fast.
Usually this options is used during development on local machine and compilation was already performed. Usually this options is used during development on local machine and compilation was already performed.
## Why do you have `typecheck` errors?
`typecheck` is like the front-end of a Go compiler, parses and type-checks Go code, it manages compilation errors.
It cannot be disabled because of that.
Of course, this is just as good as the compiler itself and a lot of compilation issues will not properly show where in the code your error lies.
`typecheck` is not a real linter, it's just a way to parse compiling errors (produced by the `types.Checker`) and some linter errors.
If there are `typecheck` errors, golangci-lint will not able to produce other reports because that kind of error doesn't allow it to perform analysis.
How to troubleshoot:
- [ ] Ensure the version of `golangci-lint` is built with a compatible version of Go.
- [ ] Ensure dependencies are up-to-date with `go mod tidy`.
- [ ] Ensure building works with `go run ./...`/`go build ./...` - whole package.
- [ ] If using CGO, ensure all require system libraries are installed.

View File

@ -63,6 +63,10 @@ func printLinterConfigs(lcs []*linter.Config) {
func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) { func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) {
var enabledLCs, disabledLCs []*linter.Config var enabledLCs, disabledLCs []*linter.Config
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
if lc.Internal {
continue
}
if lc.EnabledByDefault { if lc.EnabledByDefault {
enabledLCs = append(enabledLCs, lc) enabledLCs = append(enabledLCs, lc)
} else { } else {
@ -78,8 +82,12 @@ func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) {
color.Green("\nLinters presets:") color.Green("\nLinters presets:")
for _, p := range e.DBManager.AllPresets() { for _, p := range e.DBManager.AllPresets() {
linters := e.DBManager.GetAllLinterConfigsForPreset(p) linters := e.DBManager.GetAllLinterConfigsForPreset(p)
linterNames := make([]string, 0, len(linters)) var linterNames []string
for _, lc := range linters { for _, lc := range linters {
if lc.Internal {
continue
}
linterNames = append(linterNames, lc.Name()) linterNames = append(linterNames, lc.Name())
} }
sort.Strings(linterNames) sort.Strings(linterNames)

View File

@ -29,14 +29,22 @@ func (e *Executor) executeLinters(_ *cobra.Command, _ []string) error {
} }
color.Green("Enabled by your configuration linters:\n") color.Green("Enabled by your configuration linters:\n")
enabledLinters := make([]*linter.Config, 0, len(enabledLintersMap)) var enabledLinters []*linter.Config
for _, linter := range enabledLintersMap { for _, lc := range enabledLintersMap {
enabledLinters = append(enabledLinters, linter) if lc.Internal {
continue
}
enabledLinters = append(enabledLinters, lc)
} }
printLinterConfigs(enabledLinters) printLinterConfigs(enabledLinters)
var disabledLCs []*linter.Config var disabledLCs []*linter.Config
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
if lc.Internal {
continue
}
if enabledLintersMap[lc.Name()] == nil { if enabledLintersMap[lc.Name()] == nil {
disabledLCs = append(disabledLCs, lc) disabledLCs = append(disabledLCs, lc)
} }

View File

@ -42,6 +42,7 @@ type Config struct {
AlternativeNames []string AlternativeNames []string
OriginalURL string // URL of original (not forked) repo, needed for autogenerated README OriginalURL string // URL of original (not forked) repo, needed for autogenerated README
Internal bool // Internal linters cannot be disabled (ex: typecheck).
CanAutoFix bool CanAutoFix bool
IsSlow bool IsSlow bool
DoesChangeTypes bool DoesChangeTypes bool
@ -55,6 +56,11 @@ func (lc *Config) WithEnabledByDefault() *Config {
return lc return lc
} }
func (lc *Config) WithInternal() *Config {
lc.Internal = true
return lc
}
func (lc *Config) ConsiderSlow() *Config { func (lc *Config) ConsiderSlow() *Config {
lc.IsSlow = true lc.IsSlow = true
return lc return lc

View File

@ -31,8 +31,10 @@ func NewEnabledSet(m *Manager, v *Validator, log logutils.Log, cfg *config.Confi
} }
} }
//nolint:gocyclo // the complexity cannot be reduced.
func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*linter.Config) map[string]*linter.Config { func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*linter.Config) map[string]*linter.Config {
es.debugf("Linters config: %#v", lcfg) es.debugf("Linters config: %#v", lcfg)
resultLintersSet := map[string]*linter.Config{} resultLintersSet := map[string]*linter.Config{}
switch { switch {
case len(lcfg.Presets) != 0: case len(lcfg.Presets) != 0:
@ -78,6 +80,14 @@ func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*lint
} }
} }
// typecheck is not a real linter and cannot be disabled.
if _, ok := resultLintersSet["typecheck"]; !ok && (es.cfg == nil || !es.cfg.InternalCmdTest) {
for _, lc := range es.m.GetLinterConfigs("typecheck") {
// it's important to use lc.Name() nor name because name can be alias
resultLintersSet[lc.Name()] = lc
}
}
return resultLintersSet return resultLintersSet
} }
@ -134,8 +144,8 @@ func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) {
func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config) { func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config) {
var goanalysisLinters []*goanalysis.Linter var goanalysisLinters []*goanalysis.Linter
goanalysisPresets := map[string]bool{} goanalysisPresets := map[string]bool{}
for _, linter := range linters { for _, lc := range linters {
lnt, ok := linter.Linter.(*goanalysis.Linter) lnt, ok := lc.Linter.(*goanalysis.Linter)
if !ok { if !ok {
continue continue
} }
@ -144,7 +154,7 @@ func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config)
continue continue
} }
goanalysisLinters = append(goanalysisLinters, lnt) goanalysisLinters = append(goanalysisLinters, lnt)
for _, p := range linter.InPresets { for _, p := range lc.InPresets {
goanalysisPresets[p] = true goanalysisPresets[p] = true
} }
} }
@ -197,6 +207,10 @@ func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config)
func (es EnabledSet) verbosePrintLintersStatus(lcs map[string]*linter.Config) { func (es EnabledSet) verbosePrintLintersStatus(lcs map[string]*linter.Config) {
var linterNames []string var linterNames []string
for _, lc := range lcs { for _, lc := range lcs {
if lc.Internal {
continue
}
linterNames = append(linterNames, lc.Name()) linterNames = append(linterNames, lc.Name())
} }
sort.StringSlice(linterNames).Sort() sort.StringSlice(linterNames).Sort()

View File

@ -16,7 +16,9 @@ func TestGetEnabledLintersSet(t *testing.T) {
def []string // enabled by default linters def []string // enabled by default linters
exp []string // alphabetically ordered enabled linter names exp []string // alphabetically ordered enabled linter names
} }
allMegacheckLinterNames := []string{"gosimple", "staticcheck", "unused"} allMegacheckLinterNames := []string{"gosimple", "staticcheck", "unused"}
cases := []cs{ cases := []cs{
{ {
cfg: config.Linters{ cfg: config.Linters{
@ -24,7 +26,7 @@ func TestGetEnabledLintersSet(t *testing.T) {
}, },
name: "disable all linters from megacheck", name: "disable all linters from megacheck",
def: allMegacheckLinterNames, def: allMegacheckLinterNames,
exp: nil, // all disabled exp: []string{"typecheck"}, // all disabled
}, },
{ {
cfg: config.Linters{ cfg: config.Linters{
@ -32,12 +34,12 @@ func TestGetEnabledLintersSet(t *testing.T) {
}, },
name: "disable only staticcheck", name: "disable only staticcheck",
def: allMegacheckLinterNames, def: allMegacheckLinterNames,
exp: []string{"gosimple", "unused"}, exp: []string{"gosimple", "typecheck", "unused"},
}, },
{ {
name: "don't merge into megacheck", name: "don't merge into megacheck",
def: allMegacheckLinterNames, def: allMegacheckLinterNames,
exp: allMegacheckLinterNames, exp: []string{"gosimple", "staticcheck", "typecheck", "unused"},
}, },
{ {
name: "expand megacheck", name: "expand megacheck",
@ -45,33 +47,33 @@ func TestGetEnabledLintersSet(t *testing.T) {
Enable: []string{"megacheck"}, Enable: []string{"megacheck"},
}, },
def: nil, def: nil,
exp: allMegacheckLinterNames, exp: []string{"gosimple", "staticcheck", "typecheck", "unused"},
}, },
{ {
name: "don't disable anything", name: "don't disable anything",
def: []string{"gofmt", "govet"}, def: []string{"gofmt", "govet", "typecheck"},
exp: []string{"gofmt", "govet"}, exp: []string{"gofmt", "govet", "typecheck"},
}, },
{ {
name: "enable gosec by gas alias", name: "enable gosec by gas alias",
cfg: config.Linters{ cfg: config.Linters{
Enable: []string{"gas"}, Enable: []string{"gas"},
}, },
exp: []string{"gosec"}, exp: []string{"gosec", "typecheck"},
}, },
{ {
name: "enable gosec by primary name", name: "enable gosec by primary name",
cfg: config.Linters{ cfg: config.Linters{
Enable: []string{"gosec"}, Enable: []string{"gosec"},
}, },
exp: []string{"gosec"}, exp: []string{"gosec", "typecheck"},
}, },
{ {
name: "enable gosec by both names", name: "enable gosec by both names",
cfg: config.Linters{ cfg: config.Linters{
Enable: []string{"gosec", "gas"}, Enable: []string{"gosec", "gas"},
}, },
exp: []string{"gosec"}, exp: []string{"gosec", "typecheck"},
}, },
{ {
name: "disable gosec by gas alias", name: "disable gosec by gas alias",
@ -79,6 +81,7 @@ func TestGetEnabledLintersSet(t *testing.T) {
Disable: []string{"gas"}, Disable: []string{"gas"},
}, },
def: []string{"gosec"}, def: []string{"gosec"},
exp: []string{"typecheck"},
}, },
{ {
name: "disable gosec by primary name", name: "disable gosec by primary name",
@ -86,11 +89,13 @@ func TestGetEnabledLintersSet(t *testing.T) {
Disable: []string{"gosec"}, Disable: []string{"gosec"},
}, },
def: []string{"gosec"}, def: []string{"gosec"},
exp: []string{"typecheck"},
}, },
} }
m := NewManager(nil, nil) m := NewManager(nil, nil)
es := NewEnabledSet(m, NewValidator(m), nil, nil) es := NewEnabledSet(m, NewValidator(m), nil, nil)
for _, c := range cases { for _, c := range cases {
c := c c := c
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {

View File

@ -804,6 +804,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithURL("https://github.com/moricho/tparallel"), WithURL("https://github.com/moricho/tparallel"),
linter.NewConfig(golinters.NewTypecheck()). linter.NewConfig(golinters.NewTypecheck()).
WithInternal().
WithEnabledByDefault(). WithEnabledByDefault().
WithSince("v1.3.0"). WithSince("v1.3.0").
WithLoadForGoAnalysis(). WithLoadForGoAnalysis().

View File

@ -279,11 +279,15 @@ func TestNolintUnused(t *testing.T) {
createProcessor := func(t *testing.T, log *logutils.MockLog, enabledLinters []string) *Nolint { createProcessor := func(t *testing.T, log *logutils.MockLog, enabledLinters []string) *Nolint {
enabledSetLog := logutils.NewMockLog() enabledSetLog := logutils.NewMockLog()
enabledSetLog.On("Infof", "Active %d linters: %s", len(enabledLinters), enabledLinters) enabledSetLog.On("Infof", "Active %d linters: %s", len(enabledLinters), enabledLinters)
cfg := &config.Config{Linters: config.Linters{DisableAll: true, Enable: enabledLinters}} cfg := &config.Config{Linters: config.Linters{DisableAll: true, Enable: enabledLinters}}
dbManager := lintersdb.NewManager(cfg, nil) dbManager := lintersdb.NewManager(cfg, nil)
enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg) enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg)
enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap() enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap()
assert.NoError(t, err) assert.NoError(t, err)
return NewNolint(log, dbManager, enabledLintersMap) return NewNolint(log, dbManager, enabledLintersMap)
} }

View File

@ -238,6 +238,10 @@ func getLintersListMarkdown(enabled bool) string {
var neededLcs []*linter.Config var neededLcs []*linter.Config
lcs := lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs() lcs := lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs()
for _, lc := range lcs { for _, lc := range lcs {
if lc.Internal {
continue
}
if lc.EnabledByDefault == enabled { if lc.EnabledByDefault == enabled {
neededLcs = append(neededLcs, lc) neededLcs = append(neededLcs, lc)
} }

View File

@ -170,6 +170,10 @@ func getEnabledByDefaultLinters() []string {
ebdl := lintersdb.NewManager(nil, nil).GetAllEnabledByDefaultLinters() ebdl := lintersdb.NewManager(nil, nil).GetAllEnabledByDefaultLinters()
var ret []string var ret []string
for _, lc := range ebdl { for _, lc := range ebdl {
if lc.Internal {
continue
}
ret = append(ret, lc.Name()) ret = append(ret, lc.Name())
} }

View File

@ -243,7 +243,7 @@ func TestLineDirective(t *testing.T) {
}, },
configPath: "testdata/linedirective/gomodguard.yml", configPath: "testdata/linedirective/gomodguard.yml",
targetPath: "linedirective", targetPath: "linedirective",
expected: "import of package `github.com/ryancurrah/gomodguard` is blocked because the module is not " + expected: "import of package `golang.org/x/tools/go/analysis` is blocked because the module is not " +
"in the allowed modules list. (gomodguard)", "in the allowed modules list. (gomodguard)",
}, },
{ {

View File

@ -2,4 +2,4 @@ linters-settings:
gomodguard: gomodguard:
allowed: allowed:
domains: domains:
- golang.org - github.com

View File

@ -3,7 +3,7 @@
package main package main
import ( import (
"github.com/ryancurrah/gomodguard" "golang.org/x/tools/go/analysis"
) )
func _() { func _() {
@ -26,6 +26,10 @@ func b() {
fmt.Println("foo") fmt.Println("foo")
} }
func c(){
_ = analysis.Analyzer{}
}
func wsl() bool { func wsl() bool {
return true return true