Skip to content

Commit

Permalink
feat: explain typecheck and remove it from the linter list (#3929)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Jun 29, 2023
1 parent a303529 commit 79c78d6
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 19 deletions.
19 changes: 19 additions & 0 deletions docs/src/docs/usage/faq.mdx
Expand Up @@ -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.
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.
10 changes: 9 additions & 1 deletion pkg/commands/help.go
Expand Up @@ -63,6 +63,10 @@ func printLinterConfigs(lcs []*linter.Config) {
func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) {
var enabledLCs, disabledLCs []*linter.Config
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
if lc.Internal {
continue
}

if lc.EnabledByDefault {
enabledLCs = append(enabledLCs, lc)
} else {
Expand All @@ -78,8 +82,12 @@ func (e *Executor) executeLintersHelp(_ *cobra.Command, _ []string) {
color.Green("\nLinters presets:")
for _, p := range e.DBManager.AllPresets() {
linters := e.DBManager.GetAllLinterConfigsForPreset(p)
linterNames := make([]string, 0, len(linters))
var linterNames []string
for _, lc := range linters {
if lc.Internal {
continue
}

linterNames = append(linterNames, lc.Name())
}
sort.Strings(linterNames)
Expand Down
14 changes: 11 additions & 3 deletions pkg/commands/linters.go
Expand Up @@ -29,14 +29,22 @@ func (e *Executor) executeLinters(_ *cobra.Command, _ []string) error {
}

color.Green("Enabled by your configuration linters:\n")
enabledLinters := make([]*linter.Config, 0, len(enabledLintersMap))
for _, linter := range enabledLintersMap {
enabledLinters = append(enabledLinters, linter)
var enabledLinters []*linter.Config
for _, lc := range enabledLintersMap {
if lc.Internal {
continue
}

enabledLinters = append(enabledLinters, lc)
}
printLinterConfigs(enabledLinters)

var disabledLCs []*linter.Config
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
if lc.Internal {
continue
}

if enabledLintersMap[lc.Name()] == nil {
disabledLCs = append(disabledLCs, lc)
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/lint/linter/config.go
Expand Up @@ -42,6 +42,7 @@ type Config struct {
AlternativeNames []string

OriginalURL string // URL of original (not forked) repo, needed for autogenerated README
Internal bool // Internal linters cannot be disabled (ex: typecheck).
CanAutoFix bool
IsSlow bool
DoesChangeTypes bool
Expand All @@ -55,6 +56,11 @@ func (lc *Config) WithEnabledByDefault() *Config {
return lc
}

func (lc *Config) WithInternal() *Config {
lc.Internal = true
return lc
}

func (lc *Config) ConsiderSlow() *Config {
lc.IsSlow = true
return lc
Expand Down
20 changes: 17 additions & 3 deletions pkg/lint/lintersdb/enabled_set.go
Expand Up @@ -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 {
es.debugf("Linters config: %#v", lcfg)

resultLintersSet := map[string]*linter.Config{}
switch {
case len(lcfg.Presets) != 0:
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -134,8 +144,8 @@ func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) {
func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config) {
var goanalysisLinters []*goanalysis.Linter
goanalysisPresets := map[string]bool{}
for _, linter := range linters {
lnt, ok := linter.Linter.(*goanalysis.Linter)
for _, lc := range linters {
lnt, ok := lc.Linter.(*goanalysis.Linter)
if !ok {
continue
}
Expand All @@ -144,7 +154,7 @@ func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config)
continue
}
goanalysisLinters = append(goanalysisLinters, lnt)
for _, p := range linter.InPresets {
for _, p := range lc.InPresets {
goanalysisPresets[p] = true
}
}
Expand Down Expand Up @@ -197,6 +207,10 @@ func (es EnabledSet) combineGoAnalysisLinters(linters map[string]*linter.Config)
func (es EnabledSet) verbosePrintLintersStatus(lcs map[string]*linter.Config) {
var linterNames []string
for _, lc := range lcs {
if lc.Internal {
continue
}

linterNames = append(linterNames, lc.Name())
}
sort.StringSlice(linterNames).Sort()
Expand Down
23 changes: 14 additions & 9 deletions pkg/lint/lintersdb/enabled_set_test.go
Expand Up @@ -16,81 +16,86 @@ func TestGetEnabledLintersSet(t *testing.T) {
def []string // enabled by default linters
exp []string // alphabetically ordered enabled linter names
}

allMegacheckLinterNames := []string{"gosimple", "staticcheck", "unused"}

cases := []cs{
{
cfg: config.Linters{
Disable: []string{"megacheck"},
},
name: "disable all linters from megacheck",
def: allMegacheckLinterNames,
exp: nil, // all disabled
exp: []string{"typecheck"}, // all disabled
},
{
cfg: config.Linters{
Disable: []string{"staticcheck"},
},
name: "disable only staticcheck",
def: allMegacheckLinterNames,
exp: []string{"gosimple", "unused"},
exp: []string{"gosimple", "typecheck", "unused"},
},
{
name: "don't merge into megacheck",
def: allMegacheckLinterNames,
exp: allMegacheckLinterNames,
exp: []string{"gosimple", "staticcheck", "typecheck", "unused"},
},
{
name: "expand megacheck",
cfg: config.Linters{
Enable: []string{"megacheck"},
},
def: nil,
exp: allMegacheckLinterNames,
exp: []string{"gosimple", "staticcheck", "typecheck", "unused"},
},
{
name: "don't disable anything",
def: []string{"gofmt", "govet"},
exp: []string{"gofmt", "govet"},
def: []string{"gofmt", "govet", "typecheck"},
exp: []string{"gofmt", "govet", "typecheck"},
},
{
name: "enable gosec by gas alias",
cfg: config.Linters{
Enable: []string{"gas"},
},
exp: []string{"gosec"},
exp: []string{"gosec", "typecheck"},
},
{
name: "enable gosec by primary name",
cfg: config.Linters{
Enable: []string{"gosec"},
},
exp: []string{"gosec"},
exp: []string{"gosec", "typecheck"},
},
{
name: "enable gosec by both names",
cfg: config.Linters{
Enable: []string{"gosec", "gas"},
},
exp: []string{"gosec"},
exp: []string{"gosec", "typecheck"},
},
{
name: "disable gosec by gas alias",
cfg: config.Linters{
Disable: []string{"gas"},
},
def: []string{"gosec"},
exp: []string{"typecheck"},
},
{
name: "disable gosec by primary name",
cfg: config.Linters{
Disable: []string{"gosec"},
},
def: []string{"gosec"},
exp: []string{"typecheck"},
},
}

m := NewManager(nil, nil)
es := NewEnabledSet(m, NewValidator(m), nil, nil)

for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions pkg/lint/lintersdb/manager.go
Expand Up @@ -804,6 +804,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
WithURL("https://github.com/moricho/tparallel"),

linter.NewConfig(golinters.NewTypecheck()).
WithInternal().
WithEnabledByDefault().
WithSince("v1.3.0").
WithLoadForGoAnalysis().
Expand Down
4 changes: 4 additions & 0 deletions pkg/result/processors/nolint_test.go
Expand Up @@ -279,11 +279,15 @@ func TestNolintUnused(t *testing.T) {
createProcessor := func(t *testing.T, log *logutils.MockLog, enabledLinters []string) *Nolint {
enabledSetLog := logutils.NewMockLog()
enabledSetLog.On("Infof", "Active %d linters: %s", len(enabledLinters), enabledLinters)

cfg := &config.Config{Linters: config.Linters{DisableAll: true, Enable: enabledLinters}}
dbManager := lintersdb.NewManager(cfg, nil)

enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg)

enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap()
assert.NoError(t, err)

return NewNolint(log, dbManager, enabledLintersMap)
}

Expand Down
4 changes: 4 additions & 0 deletions scripts/expand_website_templates/main.go
Expand Up @@ -238,6 +238,10 @@ func getLintersListMarkdown(enabled bool) string {
var neededLcs []*linter.Config
lcs := lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs()
for _, lc := range lcs {
if lc.Internal {
continue
}

if lc.EnabledByDefault == enabled {
neededLcs = append(neededLcs, lc)
}
Expand Down
4 changes: 4 additions & 0 deletions test/enabled_linters_test.go
Expand Up @@ -170,6 +170,10 @@ func getEnabledByDefaultLinters() []string {
ebdl := lintersdb.NewManager(nil, nil).GetAllEnabledByDefaultLinters()
var ret []string
for _, lc := range ebdl {
if lc.Internal {
continue
}

ret = append(ret, lc.Name())
}

Expand Down
2 changes: 1 addition & 1 deletion test/run_test.go
Expand Up @@ -243,7 +243,7 @@ func TestLineDirective(t *testing.T) {
},
configPath: "testdata/linedirective/gomodguard.yml",
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)",
},
{
Expand Down
2 changes: 1 addition & 1 deletion test/testdata/linedirective/gomodguard.yml
Expand Up @@ -2,4 +2,4 @@ linters-settings:
gomodguard:
allowed:
domains:
- golang.org
- github.com
6 changes: 5 additions & 1 deletion test/testdata/linedirective/hello.go
Expand Up @@ -3,7 +3,7 @@
package main

import (
"github.com/ryancurrah/gomodguard"
"golang.org/x/tools/go/analysis"
)

func _() {
Expand All @@ -26,6 +26,10 @@ func b() {
fmt.Println("foo")
}

func c(){
_ = analysis.Analyzer{}
}

func wsl() bool {

return true
Expand Down

0 comments on commit 79c78d6

Please sign in to comment.