Skip to content

Commit 4e3bd6d

Browse files
committed
clear types only after unused running
Ensure that `unused` is always the last in execution order. It can speed up packages loading a bit. Refactor enabled linters set to remove extra logging. Relates: #944
1 parent 9eb569a commit 4e3bd6d

File tree

10 files changed

+63
-67
lines changed

10 files changed

+63
-67
lines changed

go.mod

+1-5
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,8 @@ require (
5252
github.com/valyala/quicktemplate v1.2.0
5353
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e
5454
gopkg.in/yaml.v2 v2.2.8
55+
honnef.co/go/tools v0.0.1-2020.1.3
5556
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed
5657
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
5758
mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f
5859
)
59-
60-
// See https://github.com/golangci/golangci-lint/issues/995
61-
// Update only after mitigating this issue.
62-
// TODO: Enable back tests with skip "Issue955" after update.
63-
require honnef.co/go/tools v0.0.1-2020.1.3

go.sum

+1-4
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,6 @@ golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3
366366
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
367367
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
368368
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
369-
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
370369
golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
371370
golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
372371
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -378,7 +377,6 @@ golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWc
378377
golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
379378
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e h1:3Dzrrxi54Io7Aoyb0PYLsI47K2TxkRQg+cqUn+m04do=
380379
golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
381-
golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770 h1:M9Fif0OxNji8w+HvmhVQ8KJtiZOsjU9RgslJGhn95XE=
382380
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
383381
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
384382
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
@@ -387,6 +385,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
387385
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
388386
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
389387
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
388+
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
390389
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
391390
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
392391
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -413,8 +412,6 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
413412
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
414413
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
415414
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
416-
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
417-
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
418415
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
419416
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
420417
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=

pkg/commands/linters.go

+7-13
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,26 @@ func (e *Executor) initLinters() {
2020
e.initRunConfiguration(lintersCmd)
2121
}
2222

23-
func IsLinterInConfigsList(name string, linters []*linter.Config) bool {
24-
for _, lc := range linters {
25-
if lc.Name() == name {
26-
return true
27-
}
28-
}
29-
30-
return false
31-
}
32-
3323
func (e *Executor) executeLinters(_ *cobra.Command, args []string) {
3424
if len(args) != 0 {
3525
e.log.Fatalf("Usage: golangci-lint linters")
3626
}
3727

38-
enabledLCs, err := e.EnabledLintersSet.Get(false)
28+
enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap()
3929
if err != nil {
4030
log.Fatalf("Can't get enabled linters: %s", err)
4131
}
4232

4333
color.Green("Enabled by your configuration linters:\n")
44-
printLinterConfigs(enabledLCs)
34+
enabledLinters := make([]*linter.Config, 0, len(enabledLintersMap))
35+
for _, linter := range enabledLintersMap {
36+
enabledLinters = append(enabledLinters, linter)
37+
}
38+
printLinterConfigs(enabledLinters)
4539

4640
var disabledLCs []*linter.Config
4741
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
48-
if !IsLinterInConfigsList(lc.Name(), enabledLCs) {
42+
if enabledLintersMap[lc.Name()] == nil {
4943
disabledLCs = append(disabledLCs, lc)
5044
}
5145
}

pkg/commands/run.go

+6-12
Original file line numberDiff line numberDiff line change
@@ -285,40 +285,34 @@ func fixSlicesFlags(fs *pflag.FlagSet) {
285285
func (e *Executor) runAnalysis(ctx context.Context, args []string) ([]result.Issue, error) {
286286
e.cfg.Run.Args = args
287287

288-
enabledLinters, err := e.EnabledLintersSet.Get(true)
288+
lintersToRun, err := e.EnabledLintersSet.GetOptimizedLinters()
289289
if err != nil {
290290
return nil, err
291291
}
292292

293-
enabledOriginalLinters, err := e.EnabledLintersSet.Get(false)
293+
enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap()
294294
if err != nil {
295295
return nil, err
296296
}
297297

298298
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
299-
isEnabled := false
300-
for _, enabledLC := range enabledOriginalLinters {
301-
if enabledLC.Name() == lc.Name() {
302-
isEnabled = true
303-
break
304-
}
305-
}
299+
isEnabled := enabledLintersMap[lc.Name()] != nil
306300
e.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault)
307301
}
308302

309-
lintCtx, err := e.contextLoader.Load(ctx, enabledLinters)
303+
lintCtx, err := e.contextLoader.Load(ctx, lintersToRun)
310304
if err != nil {
311305
return nil, errors.Wrap(err, "context loading failed")
312306
}
313307
lintCtx.Log = e.log.Child("linters context")
314308

315309
runner, err := lint.NewRunner(e.cfg, e.log.Child("runner"),
316-
e.goenv, e.lineCache, e.DBManager, lintCtx.Packages)
310+
e.goenv, e.EnabledLintersSet, e.lineCache, e.DBManager, lintCtx.Packages)
317311
if err != nil {
318312
return nil, err
319313
}
320314

321-
issues, err := runner.Run(ctx, enabledLinters, lintCtx)
315+
issues, err := runner.Run(ctx, lintersToRun, lintCtx)
322316
if err != nil {
323317
return nil, err
324318
}

pkg/lint/linter/config.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ type Config struct {
2222
InPresets []string
2323
AlternativeNames []string
2424

25-
OriginalURL string // URL of original (not forked) repo, needed for autogenerated README
26-
CanAutoFix bool
27-
IsSlow bool
25+
OriginalURL string // URL of original (not forked) repo, needed for autogenerated README
26+
CanAutoFix bool
27+
IsSlow bool
28+
DoesChangeTypes bool
2829
}
2930

3031
func (lc *Config) ConsiderSlow() *Config {
@@ -67,6 +68,11 @@ func (lc *Config) WithAutoFix() *Config {
6768
return lc
6869
}
6970

71+
func (lc *Config) WithChangeTypes() *Config {
72+
lc.DoesChangeTypes = true
73+
return lc
74+
}
75+
7076
func (lc *Config) AllNames() []string {
7177
return append([]string{lc.Name()}, lc.AlternativeNames...)
7278
}

pkg/lint/lintersdb/enabled_set.go

+15-5
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,22 @@ func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*lint
7777
return resultLintersSet
7878
}
7979

80-
func (es EnabledSet) Get(optimize bool) ([]*linter.Config, error) {
80+
func (es EnabledSet) GetEnabledLintersMap() (map[string]*linter.Config, error) {
81+
if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil {
82+
return nil, err
83+
}
84+
85+
return es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters()), nil
86+
}
87+
88+
func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) {
8189
if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil {
8290
return nil, err
8391
}
8492

8593
resultLintersSet := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters())
8694
es.verbosePrintLintersStatus(resultLintersSet)
87-
if optimize {
88-
es.combineGoAnalysisLinters(resultLintersSet)
89-
}
95+
es.combineGoAnalysisLinters(resultLintersSet)
9096

9197
var resultLinters []*linter.Config
9298
for _, lc := range resultLintersSet {
@@ -95,7 +101,11 @@ func (es EnabledSet) Get(optimize bool) ([]*linter.Config, error) {
95101

96102
// Make order of execution of linters (go/analysis metalinter and unused) stable.
97103
sort.Slice(resultLinters, func(i, j int) bool {
98-
return strings.Compare(resultLinters[i].Name(), resultLinters[j].Name()) <= 0
104+
a, b := resultLinters[i], resultLinters[j]
105+
if a.DoesChangeTypes != b.DoesChangeTypes {
106+
return b.DoesChangeTypes // move type-changing linters to the end to optimize speed
107+
}
108+
return strings.Compare(a.Name(), b.Name()) < 0
99109
})
100110

101111
return resultLinters, nil

pkg/lint/lintersdb/manager.go

+1
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
125125
WithPresets(linter.PresetUnused).
126126
WithAlternativeNames(megacheckName).
127127
ConsiderSlow().
128+
WithChangeTypes().
128129
WithURL("https://github.com/dominikh/go-tools/tree/master/unused"),
129130
linter.NewConfig(golinters.NewGosimple()).
130131
WithLoadForGoAnalysis().

pkg/lint/runner.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"runtime/debug"
88
"strings"
99

10+
"github.com/pkg/errors"
11+
1012
"github.com/golangci/golangci-lint/internal/errorutil"
1113
"github.com/golangci/golangci-lint/pkg/config"
1214
"github.com/golangci/golangci-lint/pkg/fsutils"
@@ -27,7 +29,7 @@ type Runner struct {
2729
Log logutils.Log
2830
}
2931

30-
func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
32+
func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lintersdb.EnabledSet,
3133
lineCache *fsutils.LineCache, dbManager *lintersdb.Manager, pkgs []*gopackages.Package) (*Runner, error) {
3234
icfg := cfg.Issues
3335
excludePatterns := icfg.ExcludePatterns
@@ -77,11 +79,9 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
7779
excludeRulesProcessor = processors.NewExcludeRules(excludeRules, lineCache, log.Child("exclude_rules"))
7880
}
7981

80-
enabledLintersSet := lintersdb.NewEnabledSet(dbManager,
81-
lintersdb.NewValidator(dbManager), log.Child("enabledLinters"), cfg)
82-
lcs, err := enabledLintersSet.Get(false)
82+
enabledLinters, err := es.GetEnabledLintersMap()
8383
if err != nil {
84-
return nil, err
84+
return nil, errors.Wrap(err, "failed to get enabled linters")
8585
}
8686

8787
return &Runner{
@@ -103,7 +103,7 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env,
103103

104104
excludeProcessor,
105105
excludeRulesProcessor,
106-
processors.NewNolint(log.Child("nolint"), dbManager, lcs),
106+
processors.NewNolint(log.Child("nolint"), dbManager, enabledLinters),
107107

108108
processors.NewUniqByLine(cfg),
109109
processors.NewDiff(icfg.Diff, icfg.DiffFromRevision, icfg.DiffPatchFilePath),
@@ -131,14 +131,17 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context,
131131
}
132132
}()
133133

134-
specificLintCtx := *lintCtx
135-
specificLintCtx.Log = r.Log.Child(lc.Name())
134+
issues, err := lc.Linter.Run(ctx, lintCtx)
135+
136+
if lc.DoesChangeTypes {
137+
// Packages in lintCtx might be dirty due to the last analysis,
138+
// which affects to the next analysis.
139+
// To avoid this issue, we clear type information from the packages.
140+
// See https://github.com/golangci/golangci-lint/pull/944.
141+
// Currently DoesChangeTypes is true only for `unused`.
142+
lintCtx.ClearTypesInPackages()
143+
}
136144

137-
// Packages in lintCtx might be dirty due to the last analysis,
138-
// which affects to the next analysis.
139-
// To avoid this issue, we clear type information from the packages.
140-
specificLintCtx.ClearTypesInPackages()
141-
issues, err := lc.Linter.Run(ctx, &specificLintCtx)
142145
if err != nil {
143146
return nil, err
144147
}

pkg/result/processors/nolint.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,13 @@ type filesCache map[string]*fileData
6060
type Nolint struct {
6161
cache filesCache
6262
dbManager *lintersdb.Manager
63-
enabledLinters map[string]bool
63+
enabledLinters map[string]*linter.Config
6464
log logutils.Log
6565

6666
unknownLintersSet map[string]bool
6767
}
6868

69-
func NewNolint(log logutils.Log, dbManager *lintersdb.Manager, enabledLCs []*linter.Config) *Nolint {
70-
enabledLinters := make(map[string]bool, len(enabledLCs))
71-
for _, lc := range enabledLCs {
72-
enabledLinters[lc.Name()] = true
73-
}
74-
69+
func NewNolint(log logutils.Log, dbManager *lintersdb.Manager, enabledLinters map[string]*linter.Config) *Nolint {
7570
return &Nolint{
7671
cache: filesCache{},
7772
dbManager: dbManager,
@@ -154,7 +149,7 @@ func (p *Nolint) shouldPassIssue(i *result.Issue) (bool, error) {
154149
if i.ExpectedNoLintLinter != "" {
155150
// don't expect disabled linters to cover their nolint statements
156151
nolintDebugf("enabled linters: %v", p.enabledLinters)
157-
if !p.enabledLinters[i.ExpectedNoLintLinter] {
152+
if p.enabledLinters[i.ExpectedNoLintLinter] == nil {
158153
return false, nil
159154
}
160155
nolintDebugf("checking that lint issue was used for %s: %v", i.ExpectedNoLintLinter, i)

pkg/result/processors/nolint_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ func TestNolintUnused(t *testing.T) {
253253
cfg := &config.Config{Linters: config.Linters{DisableAll: true, Enable: enabledLinters}}
254254
dbManager := lintersdb.NewManager(cfg, nil)
255255
enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg)
256-
lcs, err := enabledLintersSet.Get(false)
256+
enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap()
257257
assert.NoError(t, err)
258-
return NewNolint(log, dbManager, lcs)
258+
return NewNolint(log, dbManager, enabledLintersMap)
259259
}
260260

261261
// the issues below the nolintlint issues that would be generated for the test file
@@ -297,9 +297,9 @@ func TestNolintUnused(t *testing.T) {
297297
dbManager := lintersdb.NewManager(cfg, nil)
298298
enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg)
299299

300-
lcs, err := enabledLintersSet.Get(false)
300+
enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap()
301301
assert.NoError(t, err)
302-
p := NewNolint(log, dbManager, lcs)
302+
p := NewNolint(log, dbManager, enabledLintersMap)
303303
defer p.Finish()
304304

305305
processAssertEmpty(t, p, nolintlintIssueVarcheck)

0 commit comments

Comments
 (0)