Skip to content

Commit a24cc87

Browse files
committed
refactor lintersdb: split it into abstractions
1 parent c37ad66 commit a24cc87

File tree

8 files changed

+291
-252
lines changed

8 files changed

+291
-252
lines changed

pkg/commands/executor.go

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

33
import (
44
"github.com/golangci/golangci-lint/pkg/config"
5+
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
56
"github.com/golangci/golangci-lint/pkg/logutils"
67
"github.com/golangci/golangci-lint/pkg/report"
78
"github.com/spf13/cobra"
@@ -10,15 +11,14 @@ import (
1011
type Executor struct {
1112
rootCmd *cobra.Command
1213

13-
cfg *config.Config
14-
15-
exitCode int
16-
14+
exitCode int
1715
version, commit, date string
1816

19-
log logutils.Log
20-
21-
reportData report.Data
17+
cfg *config.Config
18+
log logutils.Log
19+
reportData report.Data
20+
DBManager *lintersdb.Manager
21+
EnabledLintersSet *lintersdb.EnabledSet
2222
}
2323

2424
func NewExecutor(version, commit, date string) *Executor {
@@ -30,6 +30,9 @@ func NewExecutor(version, commit, date string) *Executor {
3030
}
3131

3232
e.log = report.NewLogWrapper(logutils.NewStderrLog(""), &e.reportData)
33+
e.DBManager = lintersdb.NewManager()
34+
e.EnabledLintersSet = lintersdb.NewEnabledSet(e.DBManager, &lintersdb.Validator{},
35+
e.log.Child("lintersdb"), e.cfg)
3336

3437
e.initRoot()
3538
e.initRun()

pkg/commands/help.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77

88
"github.com/fatih/color"
99
"github.com/golangci/golangci-lint/pkg/lint/linter"
10-
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
1110
"github.com/golangci/golangci-lint/pkg/logutils"
1211
"github.com/spf13/cobra"
1312
)
@@ -41,7 +40,7 @@ func printLinterConfigs(lcs []linter.Config) {
4140

4241
func (e Executor) executeLintersHelp(cmd *cobra.Command, args []string) {
4342
var enabledLCs, disabledLCs []linter.Config
44-
for _, lc := range lintersdb.GetAllSupportedLinterConfigs() {
43+
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
4544
if lc.EnabledByDefault {
4645
enabledLCs = append(enabledLCs, lc)
4746
} else {
@@ -55,8 +54,8 @@ func (e Executor) executeLintersHelp(cmd *cobra.Command, args []string) {
5554
printLinterConfigs(disabledLCs)
5655

5756
color.Green("\nLinters presets:")
58-
for _, p := range lintersdb.AllPresets() {
59-
linters := lintersdb.GetAllLinterConfigsForPreset(p)
57+
for _, p := range e.DBManager.AllPresets() {
58+
linters := e.DBManager.GetAllLinterConfigsForPreset(p)
6059
linterNames := []string{}
6160
for _, lc := range linters {
6261
linterNames = append(linterNames, lc.Linter.Name())

pkg/commands/linters.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66

77
"github.com/fatih/color"
88
"github.com/golangci/golangci-lint/pkg/lint/linter"
9-
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
109
"github.com/spf13/cobra"
1110
)
1211

@@ -31,7 +30,7 @@ func IsLinterInConfigsList(name string, linters []linter.Config) bool {
3130
}
3231

3332
func (e Executor) executeLinters(cmd *cobra.Command, args []string) {
34-
enabledLCs, err := lintersdb.GetEnabledLinters(e.cfg, e.log.Child("lintersdb"))
33+
enabledLCs, err := e.EnabledLintersSet.Get()
3534
if err != nil {
3635
log.Fatalf("Can't get enabled linters: %s", err)
3736
}
@@ -40,7 +39,7 @@ func (e Executor) executeLinters(cmd *cobra.Command, args []string) {
4039
printLinterConfigs(enabledLCs)
4140

4241
var disabledLCs []linter.Config
43-
for _, lc := range lintersdb.GetAllSupportedLinterConfigs() {
42+
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
4443
if !IsLinterInConfigsList(lc.Linter.Name(), enabledLCs) {
4544
disabledLCs = append(disabledLCs, lc)
4645
}

pkg/commands/run.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func wh(text string) string {
4040
return color.GreenString(text)
4141
}
4242

43-
func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
43+
func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager) {
4444
hideFlag := func(name string) {
4545
if err := fs.MarkHidden(name); err != nil {
4646
panic(err)
@@ -137,7 +137,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
137137
fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters"))
138138
fs.StringSliceVarP(&lc.Presets, "presets", "p", nil,
139139
wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see "+
140-
"them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))))
140+
"them. This option implies option --disable-all", strings.Join(m.AllPresets(), "|"))))
141141
fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set"))
142142

143143
// Issues config
@@ -167,7 +167,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
167167
func (e *Executor) initRunConfiguration(cmd *cobra.Command) {
168168
fs := cmd.Flags()
169169
fs.SortFlags = false // sort them as they are defined here
170-
initFlagSet(fs, e.cfg)
170+
initFlagSet(fs, e.cfg, e.DBManager)
171171

172172
// init e.cfg by values from config: flags parse will see these values
173173
// like the default ones. It will overwrite them only if the same option
@@ -178,7 +178,7 @@ func (e *Executor) initRunConfiguration(cmd *cobra.Command) {
178178
// `changed` variable inside string slice vars will be shared.
179179
// Use another config variable here, not e.cfg, to not
180180
// affect main parsing by this parsing of only config option.
181-
initFlagSet(fs, cfg)
181+
initFlagSet(fs, cfg, e.DBManager)
182182

183183
// Parse max options, even force version option: don't want
184184
// to get access to Executor here: it's error-prone to use
@@ -232,12 +232,12 @@ func fixSlicesFlags(fs *pflag.FlagSet) {
232232
func (e *Executor) runAnalysis(ctx context.Context, args []string) (<-chan result.Issue, error) {
233233
e.cfg.Run.Args = args
234234

235-
linters, err := lintersdb.GetEnabledLinters(e.cfg, e.log.Child("lintersdb"))
235+
linters, err := e.EnabledLintersSet.Get()
236236
if err != nil {
237237
return nil, err
238238
}
239239

240-
for _, lc := range lintersdb.GetAllSupportedLinterConfigs() {
240+
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
241241
isEnabled := false
242242
for _, linter := range linters {
243243
if linter.Linter.Name() == lc.Linter.Name() {

pkg/lint/lintersdb/enabled_set.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package lintersdb
2+
3+
import (
4+
"sort"
5+
6+
"github.com/golangci/golangci-lint/pkg/config"
7+
"github.com/golangci/golangci-lint/pkg/golinters"
8+
"github.com/golangci/golangci-lint/pkg/lint/linter"
9+
"github.com/golangci/golangci-lint/pkg/logutils"
10+
)
11+
12+
type EnabledSet struct {
13+
m *Manager
14+
v *Validator
15+
log logutils.Log
16+
cfg *config.Config
17+
}
18+
19+
func NewEnabledSet(m *Manager, v *Validator, log logutils.Log, cfg *config.Config) *EnabledSet {
20+
return &EnabledSet{
21+
m: m,
22+
v: v,
23+
log: log,
24+
cfg: cfg,
25+
}
26+
}
27+
28+
// nolint:gocyclo
29+
func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []linter.Config) map[string]*linter.Config {
30+
resultLintersSet := map[string]*linter.Config{}
31+
switch {
32+
case len(lcfg.Presets) != 0:
33+
break // imply --disable-all
34+
case lcfg.EnableAll:
35+
resultLintersSet = linterConfigsToMap(es.m.GetAllSupportedLinterConfigs())
36+
case lcfg.DisableAll:
37+
break
38+
default:
39+
resultLintersSet = linterConfigsToMap(enabledByDefaultLinters)
40+
}
41+
42+
// --presets can only add linters to default set
43+
for _, p := range lcfg.Presets {
44+
for _, lc := range es.m.GetAllLinterConfigsForPreset(p) {
45+
lc := lc
46+
resultLintersSet[lc.Linter.Name()] = &lc
47+
}
48+
}
49+
50+
// --fast removes slow linters from current set.
51+
// It should be after --presets to be able to run only fast linters in preset.
52+
// It should be before --enable and --disable to be able to enable or disable specific linter.
53+
if lcfg.Fast {
54+
for name := range resultLintersSet {
55+
if es.m.getLinterConfig(name).DoesFullImport {
56+
delete(resultLintersSet, name)
57+
}
58+
}
59+
}
60+
61+
for _, name := range lcfg.Enable {
62+
resultLintersSet[name] = es.m.getLinterConfig(name)
63+
}
64+
65+
for _, name := range lcfg.Disable {
66+
if name == "megacheck" {
67+
for _, ln := range getAllMegacheckSubLinterNames() {
68+
delete(resultLintersSet, ln)
69+
}
70+
}
71+
delete(resultLintersSet, name)
72+
}
73+
74+
es.optimizeLintersSet(resultLintersSet)
75+
return resultLintersSet
76+
}
77+
78+
func getAllMegacheckSubLinterNames() []string {
79+
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
80+
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
81+
staticcheckName := golinters.Megacheck{StaticcheckEnabled: true}.Name()
82+
return []string{unusedName, gosimpleName, staticcheckName}
83+
}
84+
85+
func (es EnabledSet) optimizeLintersSet(linters map[string]*linter.Config) {
86+
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
87+
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
88+
staticcheckName := golinters.Megacheck{StaticcheckEnabled: true}.Name()
89+
fullName := golinters.Megacheck{GosimpleEnabled: true, UnusedEnabled: true, StaticcheckEnabled: true}.Name()
90+
allNames := []string{unusedName, gosimpleName, staticcheckName, fullName}
91+
92+
megacheckCount := 0
93+
for _, n := range allNames {
94+
if linters[n] != nil {
95+
megacheckCount++
96+
}
97+
}
98+
99+
if megacheckCount <= 1 {
100+
return
101+
}
102+
103+
isFullEnabled := linters[fullName] != nil
104+
mega := golinters.Megacheck{
105+
UnusedEnabled: isFullEnabled || linters[unusedName] != nil,
106+
GosimpleEnabled: isFullEnabled || linters[gosimpleName] != nil,
107+
StaticcheckEnabled: isFullEnabled || linters[staticcheckName] != nil,
108+
}
109+
110+
for _, n := range allNames {
111+
delete(linters, n)
112+
}
113+
114+
lc := *es.m.getLinterConfig("megacheck")
115+
lc.Linter = mega
116+
linters[mega.Name()] = &lc
117+
}
118+
119+
func (es EnabledSet) Get() ([]linter.Config, error) {
120+
if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil {
121+
return nil, err
122+
}
123+
124+
resultLintersSet := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters())
125+
126+
var resultLinters []linter.Config
127+
for _, lc := range resultLintersSet {
128+
resultLinters = append(resultLinters, *lc)
129+
}
130+
131+
es.verbosePrintLintersStatus(resultLinters)
132+
133+
return resultLinters, nil
134+
}
135+
136+
func (es EnabledSet) verbosePrintLintersStatus(lcs []linter.Config) {
137+
var linterNames []string
138+
for _, lc := range lcs {
139+
linterNames = append(linterNames, lc.Linter.Name())
140+
}
141+
sort.StringSlice(linterNames).Sort()
142+
es.log.Infof("Active %d linters: %s", len(linterNames), linterNames)
143+
144+
if len(es.cfg.Linters.Presets) != 0 {
145+
sort.StringSlice(es.cfg.Linters.Presets).Sort()
146+
es.log.Infof("Active presets: %s", es.cfg.Linters.Presets)
147+
}
148+
}

pkg/lint/lintersdb/lintersdb_test.go renamed to pkg/lint/lintersdb/enabled_set_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ func TestGetEnabledLintersSet(t *testing.T) {
4444
},
4545
}
4646

47+
m := NewManager()
48+
es := NewEnabledSet(m, &Validator{}, nil, nil)
4749
for _, c := range cases {
4850
t.Run(c.name, func(t *testing.T) {
4951
defaultLinters := []linter.Config{}
5052
for _, ln := range c.def {
51-
defaultLinters = append(defaultLinters, *getLinterConfig(ln))
53+
defaultLinters = append(defaultLinters, *m.getLinterConfig(ln))
5254
}
53-
els := getEnabledLintersSet(&c.cfg, defaultLinters)
55+
els := es.build(&c.cfg, defaultLinters)
5456
var enabledLinters []string
5557
for ln, lc := range els {
5658
assert.Equal(t, ln, lc.Linter.Name())

0 commit comments

Comments
 (0)