Skip to content

Commit ad660f2

Browse files
committed
Fix #237, fix #178: use go/packages
Use go/packages instead of x/tools/loader: it allows to work with go modules and speedups loading of packages with the help of build cache. A lot of linters became "fast": they are enabled by --fast now and work in 1-2 seconds. Only unparam, interfacer and megacheck are "slow" linters now. Average project is analyzed 20-40% faster than before if all linters are enabled! If we enable all linters except unparam, interfacer and megacheck analysis is 10-20x faster!
1 parent 6ecea1c commit ad660f2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+5850
-1689
lines changed

.golangci.example.yml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,6 @@ linters-settings:
6262
govet:
6363
# report about shadowed variables
6464
check-shadowing: true
65-
66-
# Obtain type information from installed (to $GOPATH/pkg) package files:
67-
# golangci-lint will execute `go install -i` and `go test -i` for analyzed packages
68-
# before analyzing them.
69-
# By default this option is disabled and govet gets type information by loader from source code.
70-
# Loading from source code is slow, but it's done only once for all linters.
71-
# Go-installing of packages first time is much slower than loading them from source code,
72-
# therefore this option is disabled by default.
73-
# But repeated installation is fast in go >= 1.10 because of build caching.
74-
# Enable this option only if all conditions are met:
75-
# 1. you use only "fast" linters (--fast e.g.): no program loading occurs
76-
# 2. you use go >= 1.10
77-
# 3. you do repeated runs (false for CI) or cache $GOPATH/pkg or `go env GOCACHE` dir in CI.
78-
use-installed-packages: false
7965
golint:
8066
# minimal confidence for issues, default is 0.8
8167
min-confidence: 0.8

.golangci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ linters-settings:
2020
- github.com/sirupsen/logrus
2121
misspell:
2222
locale: US
23+
lll:
24+
line-length: 140
2325

2426
linters:
2527
enable-all: true

Gopkg.lock

Lines changed: 13 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,16 @@ GolangCI-Lint can be used with zero configuration. By default the following lint
110110
```
111111
$ golangci-lint help linters
112112
Enabled by default linters:
113-
govet: Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false]
114-
errcheck: Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false]
113+
govet: Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: true]
114+
errcheck: Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: true]
115115
staticcheck: Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: false]
116116
unused: Checks Go code for unused constants, variables, functions and types [fast: false]
117117
gosimple: Linter for Go source code that specializes in simplifying a code [fast: false]
118-
structcheck: Finds an unused struct fields [fast: false]
119-
varcheck: Finds unused global variables and constants [fast: false]
118+
structcheck: Finds an unused struct fields [fast: true]
119+
varcheck: Finds unused global variables and constants [fast: true]
120120
ineffassign: Detects when assignments to existing variables are not used [fast: true]
121-
deadcode: Finds unused code [fast: false]
122-
typecheck: Like the front-end of a Go compiler, parses and type-checks Go code [fast: false]
121+
deadcode: Finds unused code [fast: true]
122+
typecheck: Like the front-end of a Go compiler, parses and type-checks Go code [fast: true]
123123
```
124124

125125
and the following linters are disabled by default:
@@ -128,17 +128,17 @@ $ golangci-lint help linters
128128
...
129129
Disabled by default linters:
130130
golint: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true]
131-
gosec (gas): Inspects source code for security problems [fast: false]
131+
gosec (gas): Inspects source code for security problems [fast: true]
132132
interfacer: Linter that suggests narrower interface types [fast: false]
133-
unconvert: Remove unnecessary type conversions [fast: false]
133+
unconvert: Remove unnecessary type conversions [fast: true]
134134
dupl: Tool for code clone detection [fast: true]
135135
goconst: Finds repeated strings that could be replaced by a constant [fast: true]
136136
gocyclo: Computes and checks the cyclomatic complexity of functions [fast: true]
137137
gofmt: Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true]
138138
goimports: Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true]
139-
maligned: Tool to detect Go structs that would take less memory if their fields were sorted [fast: false]
139+
maligned: Tool to detect Go structs that would take less memory if their fields were sorted [fast: true]
140140
megacheck: 3 sub-linters in one: unused, gosimple and staticcheck [fast: false]
141-
depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: false]
141+
depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: true]
142142
misspell: Finds commonly misspelled English words in comments [fast: true]
143143
lll: Reports long lines [fast: true]
144144
unparam: Reports unused function parameters [fast: false]
@@ -369,7 +369,7 @@ Flags:
369369
--enable-all Enable all linters
370370
--disable-all Disable all linters
371371
-p, --presets strings Enable presets (bugs|unused|format|style|complexity|performance) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all
372-
--fast Run only fast linters from enabled linters set
372+
--fast Run only fast linters from enabled linters set (first run won't be fast)
373373
-e, --exclude strings Exclude issue by regexp
374374
--exclude-use-default Use or not use default excludes:
375375
# errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
@@ -499,20 +499,6 @@ linters-settings:
499499
govet:
500500
# report about shadowed variables
501501
check-shadowing: true
502-
503-
# Obtain type information from installed (to $GOPATH/pkg) package files:
504-
# golangci-lint will execute `go install -i` and `go test -i` for analyzed packages
505-
# before analyzing them.
506-
# By default this option is disabled and govet gets type information by loader from source code.
507-
# Loading from source code is slow, but it's done only once for all linters.
508-
# Go-installing of packages first time is much slower than loading them from source code,
509-
# therefore this option is disabled by default.
510-
# But repeated installation is fast in go >= 1.10 because of build caching.
511-
# Enable this option only if all conditions are met:
512-
# 1. you use only "fast" linters (--fast e.g.): no program loading occurs
513-
# 2. you use go >= 1.10
514-
# 3. you do repeated runs (false for CI) or cache $GOPATH/pkg or `go env GOCACHE` dir in CI.
515-
use-installed-packages: false
516502
golint:
517503
# minimal confidence for issues, default is 0.8
518504
min-confidence: 0.8
@@ -654,6 +640,8 @@ linters-settings:
654640
- github.com/sirupsen/logrus
655641
misspell:
656642
locale: US
643+
lll:
644+
line-length: 140
657645

658646
linters:
659647
enable-all: true
@@ -698,17 +686,20 @@ We don't recommend vendoring `golangci-lint` in your repo: you will get troubles
698686

699687
**Does I need to run `go install`?**
700688

701-
No, you don't need to do it anymore. We will run `go install -i` and `go test -i`
702-
for analyzed packages ourselves. We will run them only
703-
if option `govet.use-installed-packages` is `true`.
689+
No, you don't need to do it anymore.
704690

705691
**`golangci-lint` doesn't work**
706692

707693
1. Update it: `go get -u github.com/golangci/golangci-lint/cmd/golangci-lint`
708694
2. Run it with `-v` option and check the output.
709695
3. If it doesn't help create a [GitHub issue](https://github.com/golangci/golangci-lint/issues/new) with the output from the error and #2 above.
710696

697+
**Why running with `--fast` is slow on the first run?**
698+
Because the first run caches type information. All subsequent runs will be fast.
699+
Usually this options is used during development on local machine and compilation was already performed.
700+
711701
# Thanks
702+
712703
Thanks to [alecthomas/gometalinter](https://github.com/alecthomas/gometalinter) for inspiration and amazing work.
713704
Thanks to [bradleyfalzon/revgrep](https://github.com/bradleyfalzon/revgrep) for cool diff tool.
714705

README.tmpl.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,17 +358,20 @@ We don't recommend vendoring `golangci-lint` in your repo: you will get troubles
358358

359359
**Does I need to run `go install`?**
360360

361-
No, you don't need to do it anymore. We will run `go install -i` and `go test -i`
362-
for analyzed packages ourselves. We will run them only
363-
if option `govet.use-installed-packages` is `true`.
361+
No, you don't need to do it anymore.
364362

365363
**`golangci-lint` doesn't work**
366364

367365
1. Update it: `go get -u github.com/golangci/golangci-lint/cmd/golangci-lint`
368366
2. Run it with `-v` option and check the output.
369367
3. If it doesn't help create a [GitHub issue](https://github.com/golangci/golangci-lint/issues/new) with the output from the error and #2 above.
370368

369+
**Why running with `--fast` is slow on the first run?**
370+
Because the first run caches type information. All subsequent runs will be fast.
371+
Usually this options is used during development on local machine and compilation was already performed.
372+
371373
# Thanks
374+
372375
Thanks to [alecthomas/gometalinter](https://github.com/alecthomas/gometalinter) for inspiration and amazing work.
373376
Thanks to [bradleyfalzon/revgrep](https://github.com/bradleyfalzon/revgrep) for cool diff tool.
374377

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770
2929
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21
3030
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0
31-
github.com/golangci/tools v0.0.0-20180902102414-98e75f53b4b9
31+
github.com/golangci/tools v0.0.0-20180902102414-01dd7756e01d
3232
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4
3333
github.com/golangci/unparam v0.0.0-20180902112548-7ad9dbcccc16
3434
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce // indirect
@@ -56,7 +56,7 @@ require (
5656
github.com/spf13/viper v1.0.2
5757
github.com/stretchr/testify v1.2.1
5858
golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab // indirect
59-
golang.org/x/tools v0.0.0-20180831211245-5d4988d199e2
59+
golang.org/x/tools v0.0.0-20180831211245-3e7aa9e59977
6060
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
6161
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
6262
sourcegraph.com/sourcegraph/go-diff v0.0.0-20171119081133-3f415a150aec

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSS
5959
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
6060
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg=
6161
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
62+
github.com/golangci/tools v0.0.0-20180902102414-01dd7756e01d/go.mod h1:zgj6NOYXOC1cexsdtDceI4/mj3aXK4JOVg9AV3C5LWI=
6263
github.com/golangci/tools v0.0.0-20180902102414-98e75f53b4b9 h1:JGHGJqnbD9OMyjgQqyja7DZd0/to1LKFpN31Fq8byxc=
6364
github.com/golangci/tools v0.0.0-20180902102414-98e75f53b4b9/go.mod h1:zgj6NOYXOC1cexsdtDceI4/mj3aXK4JOVg9AV3C5LWI=
6465
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys=
@@ -131,6 +132,7 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
131132
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
132133
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
133134
golang.org/x/tools v0.0.0-20180826000951-f6ba57429505/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
135+
golang.org/x/tools v0.0.0-20180831211245-3e7aa9e59977/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
134136
golang.org/x/tools v0.0.0-20180831211245-5d4988d199e2/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
135137
golang.org/x/tools v0.0.0-20180831211245-7ca132754999 h1:mf2VYfMpSMTlp0I/UXrX13w5LejDx34QeUUHH4TrUA8=
136138
golang.org/x/tools v0.0.0-20180831211245-7ca132754999/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

pkg/commands/executor.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package commands
22

33
import (
44
"github.com/golangci/golangci-lint/pkg/config"
5+
"github.com/golangci/golangci-lint/pkg/goutil"
6+
"github.com/golangci/golangci-lint/pkg/lint"
57
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
68
"github.com/golangci/golangci-lint/pkg/logutils"
79
"github.com/golangci/golangci-lint/pkg/report"
@@ -21,6 +23,8 @@ type Executor struct {
2123
reportData report.Data
2224
DBManager *lintersdb.Manager
2325
EnabledLintersSet *lintersdb.EnabledSet
26+
contextLoader *lint.ContextLoader
27+
goenv *goutil.Env
2428
}
2529

2630
func NewExecutor(version, commit, date string) *Executor {
@@ -65,6 +69,8 @@ func NewExecutor(version, commit, date string) *Executor {
6569

6670
e.EnabledLintersSet = lintersdb.NewEnabledSet(e.DBManager,
6771
lintersdb.NewValidator(e.DBManager), e.log.Child("lintersdb"), e.cfg)
72+
e.goenv = goutil.NewEnv(e.log.Child("goenv"))
73+
e.contextLoader = lint.NewContextLoader(e.cfg, e.log.Child("loader"), e.goenv)
6874

6975
return e
7076
}

pkg/commands/help.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func printLinterConfigs(lcs []linter.Config) {
3838
altNamesStr = fmt.Sprintf(" (%s)", strings.Join(lc.AlternativeNames, ", "))
3939
}
4040
fmt.Fprintf(logutils.StdOut, "%s%s: %s [fast: %t]\n", color.YellowString(lc.Name()),
41-
altNamesStr, lc.Linter.Desc(), !lc.DoesFullImport)
41+
altNamesStr, lc.Linter.Desc(), !lc.NeedsSSARepr)
4242
}
4343
}
4444

pkg/commands/run.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager) {
141141
fs.StringSliceVarP(&lc.Presets, "presets", "p", nil,
142142
wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see "+
143143
"them. This option implies option --disable-all", strings.Join(m.AllPresets(), "|"))))
144-
fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set"))
144+
fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set (first run won't be fast)"))
145145

146146
// Issues config
147147
ic := &cfg.Issues
@@ -257,12 +257,13 @@ func (e *Executor) runAnalysis(ctx context.Context, args []string) (<-chan resul
257257
e.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault)
258258
}
259259

260-
lintCtx, err := lint.LoadContext(enabledLinters, e.cfg, e.log.Child("load"))
260+
lintCtx, err := e.contextLoader.Load(ctx, enabledLinters)
261261
if err != nil {
262262
return nil, errors.Wrap(err, "context loading failed")
263263
}
264+
lintCtx.Log = e.log.Child("linters context")
264265

265-
runner, err := lint.NewRunner(lintCtx.ASTCache, e.cfg, e.log.Child("runner"))
266+
runner, err := lint.NewRunner(lintCtx.ASTCache, e.cfg, e.log.Child("runner"), e.goenv)
266267
if err != nil {
267268
return nil, err
268269
}
@@ -303,6 +304,10 @@ func (e *Executor) setExitCodeIfIssuesFound(issues <-chan result.Issue) <-chan r
303304
}
304305

305306
func (e *Executor) runAndPrint(ctx context.Context, args []string) error {
307+
if err := e.goenv.Discover(ctx); err != nil {
308+
e.log.Warnf("Failed to discover go env: %s", err)
309+
}
310+
306311
if !logutils.HaveDebugTag("linters_output") {
307312
// Don't allow linters and loader to print anything
308313
log.SetOutput(ioutil.Discard)
@@ -379,8 +384,20 @@ func (e *Executor) executeRun(cmd *cobra.Command, args []string) {
379384
}
380385
}
381386

382-
if e.exitCode == exitcodes.Success && ctx.Err() != nil {
387+
e.setupExitCode(ctx)
388+
}
389+
390+
func (e *Executor) setupExitCode(ctx context.Context) {
391+
if ctx.Err() != nil {
383392
e.exitCode = exitcodes.Timeout
393+
e.log.Errorf("Deadline exceeded: try increase it by passing --deadline option")
394+
}
395+
396+
if e.exitCode == exitcodes.Success &&
397+
os.Getenv("GL_TEST_RUN") == "1" &&
398+
len(e.reportData.Warnings) != 0 {
399+
400+
e.exitCode = exitcodes.WarningInTest
384401
}
385402
}
386403

pkg/config/config.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ type Run struct {
119119

120120
type LintersSettings struct {
121121
Govet struct {
122-
CheckShadowing bool `mapstructure:"check-shadowing"`
123-
UseInstalledPackages bool `mapstructure:"use-installed-packages"`
122+
CheckShadowing bool `mapstructure:"check-shadowing"`
124123
}
125124
Golint struct {
126125
MinConfidence float64 `mapstructure:"min-confidence"`

0 commit comments

Comments
 (0)