feat: explain typecheck and remove it from the linter list (#3929)
This commit is contained in:
parent
a303529ad3
commit
79c78d6f6f
@ -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.
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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) {
|
||||||
|
@ -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().
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
2
test/testdata/linedirective/gomodguard.yml
vendored
2
test/testdata/linedirective/gomodguard.yml
vendored
@ -2,4 +2,4 @@ linters-settings:
|
|||||||
gomodguard:
|
gomodguard:
|
||||||
allowed:
|
allowed:
|
||||||
domains:
|
domains:
|
||||||
- golang.org
|
- github.com
|
||||||
|
6
test/testdata/linedirective/hello.go
vendored
6
test/testdata/linedirective/hello.go
vendored
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user