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

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

Merged
merged 3 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/src/docs/usage/faq.mdx
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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