refactor lintersdb: split it into abstractions
This commit is contained in:
parent
c37ad6652e
commit
a24cc87a06
@ -2,6 +2,7 @@ package commands
|
||||
|
||||
import (
|
||||
"github.com/golangci/golangci-lint/pkg/config"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
|
||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
||||
"github.com/golangci/golangci-lint/pkg/report"
|
||||
"github.com/spf13/cobra"
|
||||
@ -10,15 +11,14 @@ import (
|
||||
type Executor struct {
|
||||
rootCmd *cobra.Command
|
||||
|
||||
cfg *config.Config
|
||||
|
||||
exitCode int
|
||||
|
||||
version, commit, date string
|
||||
|
||||
cfg *config.Config
|
||||
log logutils.Log
|
||||
|
||||
reportData report.Data
|
||||
DBManager *lintersdb.Manager
|
||||
EnabledLintersSet *lintersdb.EnabledSet
|
||||
}
|
||||
|
||||
func NewExecutor(version, commit, date string) *Executor {
|
||||
@ -30,6 +30,9 @@ func NewExecutor(version, commit, date string) *Executor {
|
||||
}
|
||||
|
||||
e.log = report.NewLogWrapper(logutils.NewStderrLog(""), &e.reportData)
|
||||
e.DBManager = lintersdb.NewManager()
|
||||
e.EnabledLintersSet = lintersdb.NewEnabledSet(e.DBManager, &lintersdb.Validator{},
|
||||
e.log.Child("lintersdb"), e.cfg)
|
||||
|
||||
e.initRoot()
|
||||
e.initRun()
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
|
||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -41,7 +40,7 @@ func printLinterConfigs(lcs []linter.Config) {
|
||||
|
||||
func (e Executor) executeLintersHelp(cmd *cobra.Command, args []string) {
|
||||
var enabledLCs, disabledLCs []linter.Config
|
||||
for _, lc := range lintersdb.GetAllSupportedLinterConfigs() {
|
||||
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
|
||||
if lc.EnabledByDefault {
|
||||
enabledLCs = append(enabledLCs, lc)
|
||||
} else {
|
||||
@ -55,8 +54,8 @@ func (e Executor) executeLintersHelp(cmd *cobra.Command, args []string) {
|
||||
printLinterConfigs(disabledLCs)
|
||||
|
||||
color.Green("\nLinters presets:")
|
||||
for _, p := range lintersdb.AllPresets() {
|
||||
linters := lintersdb.GetAllLinterConfigsForPreset(p)
|
||||
for _, p := range e.DBManager.AllPresets() {
|
||||
linters := e.DBManager.GetAllLinterConfigsForPreset(p)
|
||||
linterNames := []string{}
|
||||
for _, lc := range linters {
|
||||
linterNames = append(linterNames, lc.Linter.Name())
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/lintersdb"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -31,7 +30,7 @@ func IsLinterInConfigsList(name string, linters []linter.Config) bool {
|
||||
}
|
||||
|
||||
func (e Executor) executeLinters(cmd *cobra.Command, args []string) {
|
||||
enabledLCs, err := lintersdb.GetEnabledLinters(e.cfg, e.log.Child("lintersdb"))
|
||||
enabledLCs, err := e.EnabledLintersSet.Get()
|
||||
if err != nil {
|
||||
log.Fatalf("Can't get enabled linters: %s", err)
|
||||
}
|
||||
@ -40,7 +39,7 @@ func (e Executor) executeLinters(cmd *cobra.Command, args []string) {
|
||||
printLinterConfigs(enabledLCs)
|
||||
|
||||
var disabledLCs []linter.Config
|
||||
for _, lc := range lintersdb.GetAllSupportedLinterConfigs() {
|
||||
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
|
||||
if !IsLinterInConfigsList(lc.Linter.Name(), enabledLCs) {
|
||||
disabledLCs = append(disabledLCs, lc)
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ func wh(text string) string {
|
||||
return color.GreenString(text)
|
||||
}
|
||||
|
||||
func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
||||
func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager) {
|
||||
hideFlag := func(name string) {
|
||||
if err := fs.MarkHidden(name); err != nil {
|
||||
panic(err)
|
||||
@ -137,7 +137,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
||||
fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters"))
|
||||
fs.StringSliceVarP(&lc.Presets, "presets", "p", nil,
|
||||
wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see "+
|
||||
"them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))))
|
||||
"them. This option implies option --disable-all", strings.Join(m.AllPresets(), "|"))))
|
||||
fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set"))
|
||||
|
||||
// Issues config
|
||||
@ -167,7 +167,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) {
|
||||
func (e *Executor) initRunConfiguration(cmd *cobra.Command) {
|
||||
fs := cmd.Flags()
|
||||
fs.SortFlags = false // sort them as they are defined here
|
||||
initFlagSet(fs, e.cfg)
|
||||
initFlagSet(fs, e.cfg, e.DBManager)
|
||||
|
||||
// init e.cfg by values from config: flags parse will see these values
|
||||
// like the default ones. It will overwrite them only if the same option
|
||||
@ -178,7 +178,7 @@ func (e *Executor) initRunConfiguration(cmd *cobra.Command) {
|
||||
// `changed` variable inside string slice vars will be shared.
|
||||
// Use another config variable here, not e.cfg, to not
|
||||
// affect main parsing by this parsing of only config option.
|
||||
initFlagSet(fs, cfg)
|
||||
initFlagSet(fs, cfg, e.DBManager)
|
||||
|
||||
// Parse max options, even force version option: don't want
|
||||
// to get access to Executor here: it's error-prone to use
|
||||
@ -232,12 +232,12 @@ func fixSlicesFlags(fs *pflag.FlagSet) {
|
||||
func (e *Executor) runAnalysis(ctx context.Context, args []string) (<-chan result.Issue, error) {
|
||||
e.cfg.Run.Args = args
|
||||
|
||||
linters, err := lintersdb.GetEnabledLinters(e.cfg, e.log.Child("lintersdb"))
|
||||
linters, err := e.EnabledLintersSet.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, lc := range lintersdb.GetAllSupportedLinterConfigs() {
|
||||
for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() {
|
||||
isEnabled := false
|
||||
for _, linter := range linters {
|
||||
if linter.Linter.Name() == lc.Linter.Name() {
|
||||
|
148
pkg/lint/lintersdb/enabled_set.go
Normal file
148
pkg/lint/lintersdb/enabled_set.go
Normal file
@ -0,0 +1,148 @@
|
||||
package lintersdb
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/golangci/golangci-lint/pkg/config"
|
||||
"github.com/golangci/golangci-lint/pkg/golinters"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
||||
)
|
||||
|
||||
type EnabledSet struct {
|
||||
m *Manager
|
||||
v *Validator
|
||||
log logutils.Log
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func NewEnabledSet(m *Manager, v *Validator, log logutils.Log, cfg *config.Config) *EnabledSet {
|
||||
return &EnabledSet{
|
||||
m: m,
|
||||
v: v,
|
||||
log: log,
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []linter.Config) map[string]*linter.Config {
|
||||
resultLintersSet := map[string]*linter.Config{}
|
||||
switch {
|
||||
case len(lcfg.Presets) != 0:
|
||||
break // imply --disable-all
|
||||
case lcfg.EnableAll:
|
||||
resultLintersSet = linterConfigsToMap(es.m.GetAllSupportedLinterConfigs())
|
||||
case lcfg.DisableAll:
|
||||
break
|
||||
default:
|
||||
resultLintersSet = linterConfigsToMap(enabledByDefaultLinters)
|
||||
}
|
||||
|
||||
// --presets can only add linters to default set
|
||||
for _, p := range lcfg.Presets {
|
||||
for _, lc := range es.m.GetAllLinterConfigsForPreset(p) {
|
||||
lc := lc
|
||||
resultLintersSet[lc.Linter.Name()] = &lc
|
||||
}
|
||||
}
|
||||
|
||||
// --fast removes slow linters from current set.
|
||||
// It should be after --presets to be able to run only fast linters in preset.
|
||||
// It should be before --enable and --disable to be able to enable or disable specific linter.
|
||||
if lcfg.Fast {
|
||||
for name := range resultLintersSet {
|
||||
if es.m.getLinterConfig(name).DoesFullImport {
|
||||
delete(resultLintersSet, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range lcfg.Enable {
|
||||
resultLintersSet[name] = es.m.getLinterConfig(name)
|
||||
}
|
||||
|
||||
for _, name := range lcfg.Disable {
|
||||
if name == "megacheck" {
|
||||
for _, ln := range getAllMegacheckSubLinterNames() {
|
||||
delete(resultLintersSet, ln)
|
||||
}
|
||||
}
|
||||
delete(resultLintersSet, name)
|
||||
}
|
||||
|
||||
es.optimizeLintersSet(resultLintersSet)
|
||||
return resultLintersSet
|
||||
}
|
||||
|
||||
func getAllMegacheckSubLinterNames() []string {
|
||||
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
|
||||
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
|
||||
staticcheckName := golinters.Megacheck{StaticcheckEnabled: true}.Name()
|
||||
return []string{unusedName, gosimpleName, staticcheckName}
|
||||
}
|
||||
|
||||
func (es EnabledSet) optimizeLintersSet(linters map[string]*linter.Config) {
|
||||
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
|
||||
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
|
||||
staticcheckName := golinters.Megacheck{StaticcheckEnabled: true}.Name()
|
||||
fullName := golinters.Megacheck{GosimpleEnabled: true, UnusedEnabled: true, StaticcheckEnabled: true}.Name()
|
||||
allNames := []string{unusedName, gosimpleName, staticcheckName, fullName}
|
||||
|
||||
megacheckCount := 0
|
||||
for _, n := range allNames {
|
||||
if linters[n] != nil {
|
||||
megacheckCount++
|
||||
}
|
||||
}
|
||||
|
||||
if megacheckCount <= 1 {
|
||||
return
|
||||
}
|
||||
|
||||
isFullEnabled := linters[fullName] != nil
|
||||
mega := golinters.Megacheck{
|
||||
UnusedEnabled: isFullEnabled || linters[unusedName] != nil,
|
||||
GosimpleEnabled: isFullEnabled || linters[gosimpleName] != nil,
|
||||
StaticcheckEnabled: isFullEnabled || linters[staticcheckName] != nil,
|
||||
}
|
||||
|
||||
for _, n := range allNames {
|
||||
delete(linters, n)
|
||||
}
|
||||
|
||||
lc := *es.m.getLinterConfig("megacheck")
|
||||
lc.Linter = mega
|
||||
linters[mega.Name()] = &lc
|
||||
}
|
||||
|
||||
func (es EnabledSet) Get() ([]linter.Config, error) {
|
||||
if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultLintersSet := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters())
|
||||
|
||||
var resultLinters []linter.Config
|
||||
for _, lc := range resultLintersSet {
|
||||
resultLinters = append(resultLinters, *lc)
|
||||
}
|
||||
|
||||
es.verbosePrintLintersStatus(resultLinters)
|
||||
|
||||
return resultLinters, nil
|
||||
}
|
||||
|
||||
func (es EnabledSet) verbosePrintLintersStatus(lcs []linter.Config) {
|
||||
var linterNames []string
|
||||
for _, lc := range lcs {
|
||||
linterNames = append(linterNames, lc.Linter.Name())
|
||||
}
|
||||
sort.StringSlice(linterNames).Sort()
|
||||
es.log.Infof("Active %d linters: %s", len(linterNames), linterNames)
|
||||
|
||||
if len(es.cfg.Linters.Presets) != 0 {
|
||||
sort.StringSlice(es.cfg.Linters.Presets).Sort()
|
||||
es.log.Infof("Active presets: %s", es.cfg.Linters.Presets)
|
||||
}
|
||||
}
|
@ -44,13 +44,15 @@ func TestGetEnabledLintersSet(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
m := NewManager()
|
||||
es := NewEnabledSet(m, &Validator{}, nil, nil)
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
defaultLinters := []linter.Config{}
|
||||
for _, ln := range c.def {
|
||||
defaultLinters = append(defaultLinters, *getLinterConfig(ln))
|
||||
defaultLinters = append(defaultLinters, *m.getLinterConfig(ln))
|
||||
}
|
||||
els := getEnabledLintersSet(&c.cfg, defaultLinters)
|
||||
els := es.build(&c.cfg, defaultLinters)
|
||||
var enabledLinters []string
|
||||
for ln, lc := range els {
|
||||
assert.Equal(t, ln, lc.Linter.Name())
|
@ -1,43 +1,42 @@
|
||||
package lintersdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/golangci/golangci-lint/pkg/config"
|
||||
"github.com/golangci/golangci-lint/pkg/golinters"
|
||||
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
||||
)
|
||||
|
||||
func AllPresets() []string {
|
||||
type Manager struct {
|
||||
nameToLC map[string]linter.Config
|
||||
}
|
||||
|
||||
func NewManager() *Manager {
|
||||
m := &Manager{}
|
||||
nameToLC := make(map[string]linter.Config)
|
||||
for _, lc := range m.GetAllSupportedLinterConfigs() {
|
||||
nameToLC[lc.Linter.Name()] = lc
|
||||
}
|
||||
|
||||
m.nameToLC = nameToLC
|
||||
return m
|
||||
}
|
||||
|
||||
func (Manager) AllPresets() []string {
|
||||
return []string{linter.PresetBugs, linter.PresetUnused, linter.PresetFormatting,
|
||||
linter.PresetStyle, linter.PresetComplexity, linter.PresetPerformance}
|
||||
}
|
||||
|
||||
func allPresetsSet() map[string]bool {
|
||||
func (m Manager) allPresetsSet() map[string]bool {
|
||||
ret := map[string]bool{}
|
||||
for _, p := range AllPresets() {
|
||||
for _, p := range m.AllPresets() {
|
||||
ret[p] = true
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var nameToLC map[string]linter.Config
|
||||
var nameToLCOnce sync.Once
|
||||
|
||||
func getLinterConfig(name string) *linter.Config {
|
||||
nameToLCOnce.Do(func() {
|
||||
nameToLC = make(map[string]linter.Config)
|
||||
for _, lc := range GetAllSupportedLinterConfigs() {
|
||||
nameToLC[lc.Linter.Name()] = lc
|
||||
}
|
||||
})
|
||||
|
||||
lc, ok := nameToLC[name]
|
||||
func (m Manager) getLinterConfig(name string) *linter.Config {
|
||||
lc, ok := m.nameToLC[name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
@ -55,7 +54,7 @@ func enableLinterConfigs(lcs []linter.Config, isEnabled func(lc *linter.Config)
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetAllSupportedLinterConfigs() []linter.Config {
|
||||
func (Manager) GetAllSupportedLinterConfigs() []linter.Config {
|
||||
lcs := []linter.Config{
|
||||
linter.NewConfig(golinters.Govet{}).
|
||||
WithFullImport(). // TODO: depend on it's configuration here
|
||||
@ -207,9 +206,9 @@ func GetAllSupportedLinterConfigs() []linter.Config {
|
||||
})
|
||||
}
|
||||
|
||||
func GetAllEnabledByDefaultLinters() []linter.Config {
|
||||
func (m Manager) GetAllEnabledByDefaultLinters() []linter.Config {
|
||||
var ret []linter.Config
|
||||
for _, lc := range GetAllSupportedLinterConfigs() {
|
||||
for _, lc := range m.GetAllSupportedLinterConfigs() {
|
||||
if lc.EnabledByDefault {
|
||||
ret = append(ret, lc)
|
||||
}
|
||||
@ -228,89 +227,9 @@ func linterConfigsToMap(lcs []linter.Config) map[string]*linter.Config {
|
||||
return ret
|
||||
}
|
||||
|
||||
func validateLintersNames(cfg *config.Linters) error {
|
||||
allNames := append([]string{}, cfg.Enable...)
|
||||
allNames = append(allNames, cfg.Disable...)
|
||||
for _, name := range allNames {
|
||||
if getLinterConfig(name) == nil {
|
||||
return fmt.Errorf("no such linter %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validatePresets(cfg *config.Linters) error {
|
||||
allPresets := allPresetsSet()
|
||||
for _, p := range cfg.Presets {
|
||||
if !allPresets[p] {
|
||||
return fmt.Errorf("no such preset %q: only next presets exist: (%s)", p, strings.Join(AllPresets(), "|"))
|
||||
}
|
||||
}
|
||||
|
||||
if len(cfg.Presets) != 0 && cfg.EnableAll {
|
||||
return fmt.Errorf("--presets is incompatible with --enable-all")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAllDisableEnableOptions(cfg *config.Linters) error {
|
||||
if cfg.EnableAll && cfg.DisableAll {
|
||||
return fmt.Errorf("--enable-all and --disable-all options must not be combined")
|
||||
}
|
||||
|
||||
if cfg.DisableAll {
|
||||
if len(cfg.Enable) == 0 && len(cfg.Presets) == 0 {
|
||||
return fmt.Errorf("all linters were disabled, but no one linter was enabled: must enable at least one")
|
||||
}
|
||||
|
||||
if len(cfg.Disable) != 0 {
|
||||
return fmt.Errorf("can't combine options --disable-all and --disable %s", cfg.Disable[0])
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.EnableAll && len(cfg.Enable) != 0 && !cfg.Fast {
|
||||
return fmt.Errorf("can't combine options --enable-all and --enable %s", cfg.Enable[0])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateDisabledAndEnabledAtOneMoment(cfg *config.Linters) error {
|
||||
enabledLintersSet := map[string]bool{}
|
||||
for _, name := range cfg.Enable {
|
||||
enabledLintersSet[name] = true
|
||||
}
|
||||
|
||||
for _, name := range cfg.Disable {
|
||||
if enabledLintersSet[name] {
|
||||
return fmt.Errorf("linter %q can't be disabled and enabled at one moment", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateEnabledDisabledLintersConfig(cfg *config.Linters) error {
|
||||
validators := []func(cfg *config.Linters) error{
|
||||
validateLintersNames,
|
||||
validatePresets,
|
||||
validateAllDisableEnableOptions,
|
||||
validateDisabledAndEnabledAtOneMoment,
|
||||
}
|
||||
for _, v := range validators {
|
||||
if err := v(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAllLinterConfigsForPreset(p string) []linter.Config {
|
||||
func (m Manager) GetAllLinterConfigsForPreset(p string) []linter.Config {
|
||||
ret := []linter.Config{}
|
||||
for _, lc := range GetAllSupportedLinterConfigs() {
|
||||
for _, lc := range m.GetAllSupportedLinterConfigs() {
|
||||
for _, ip := range lc.InPresets {
|
||||
if p == ip {
|
||||
ret = append(ret, lc)
|
||||
@ -321,127 +240,3 @@ func GetAllLinterConfigsForPreset(p string) []linter.Config {
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
func getEnabledLintersSet(lcfg *config.Linters,
|
||||
enabledByDefaultLinters []linter.Config) map[string]*linter.Config {
|
||||
|
||||
resultLintersSet := map[string]*linter.Config{}
|
||||
switch {
|
||||
case len(lcfg.Presets) != 0:
|
||||
break // imply --disable-all
|
||||
case lcfg.EnableAll:
|
||||
resultLintersSet = linterConfigsToMap(GetAllSupportedLinterConfigs())
|
||||
case lcfg.DisableAll:
|
||||
break
|
||||
default:
|
||||
resultLintersSet = linterConfigsToMap(enabledByDefaultLinters)
|
||||
}
|
||||
|
||||
// --presets can only add linters to default set
|
||||
for _, p := range lcfg.Presets {
|
||||
for _, lc := range GetAllLinterConfigsForPreset(p) {
|
||||
lc := lc
|
||||
resultLintersSet[lc.Linter.Name()] = &lc
|
||||
}
|
||||
}
|
||||
|
||||
// --fast removes slow linters from current set.
|
||||
// It should be after --presets to be able to run only fast linters in preset.
|
||||
// It should be before --enable and --disable to be able to enable or disable specific linter.
|
||||
if lcfg.Fast {
|
||||
for name := range resultLintersSet {
|
||||
if getLinterConfig(name).DoesFullImport {
|
||||
delete(resultLintersSet, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range lcfg.Enable {
|
||||
resultLintersSet[name] = getLinterConfig(name)
|
||||
}
|
||||
|
||||
for _, name := range lcfg.Disable {
|
||||
if name == "megacheck" {
|
||||
for _, ln := range getAllMegacheckSubLinterNames() {
|
||||
delete(resultLintersSet, ln)
|
||||
}
|
||||
}
|
||||
delete(resultLintersSet, name)
|
||||
}
|
||||
|
||||
optimizeLintersSet(resultLintersSet)
|
||||
return resultLintersSet
|
||||
}
|
||||
|
||||
func getAllMegacheckSubLinterNames() []string {
|
||||
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
|
||||
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
|
||||
staticcheckName := golinters.Megacheck{StaticcheckEnabled: true}.Name()
|
||||
return []string{unusedName, gosimpleName, staticcheckName}
|
||||
}
|
||||
|
||||
func optimizeLintersSet(linters map[string]*linter.Config) {
|
||||
unusedName := golinters.Megacheck{UnusedEnabled: true}.Name()
|
||||
gosimpleName := golinters.Megacheck{GosimpleEnabled: true}.Name()
|
||||
staticcheckName := golinters.Megacheck{StaticcheckEnabled: true}.Name()
|
||||
fullName := golinters.Megacheck{GosimpleEnabled: true, UnusedEnabled: true, StaticcheckEnabled: true}.Name()
|
||||
allNames := []string{unusedName, gosimpleName, staticcheckName, fullName}
|
||||
|
||||
megacheckCount := 0
|
||||
for _, n := range allNames {
|
||||
if linters[n] != nil {
|
||||
megacheckCount++
|
||||
}
|
||||
}
|
||||
|
||||
if megacheckCount <= 1 {
|
||||
return
|
||||
}
|
||||
|
||||
isFullEnabled := linters[fullName] != nil
|
||||
m := golinters.Megacheck{
|
||||
UnusedEnabled: isFullEnabled || linters[unusedName] != nil,
|
||||
GosimpleEnabled: isFullEnabled || linters[gosimpleName] != nil,
|
||||
StaticcheckEnabled: isFullEnabled || linters[staticcheckName] != nil,
|
||||
}
|
||||
|
||||
for _, n := range allNames {
|
||||
delete(linters, n)
|
||||
}
|
||||
|
||||
lc := *getLinterConfig("megacheck")
|
||||
lc.Linter = m
|
||||
linters[m.Name()] = &lc
|
||||
}
|
||||
|
||||
func GetEnabledLinters(cfg *config.Config, log logutils.Log) ([]linter.Config, error) {
|
||||
if err := validateEnabledDisabledLintersConfig(&cfg.Linters); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultLintersSet := getEnabledLintersSet(&cfg.Linters, GetAllEnabledByDefaultLinters())
|
||||
|
||||
var resultLinters []linter.Config
|
||||
for _, lc := range resultLintersSet {
|
||||
resultLinters = append(resultLinters, *lc)
|
||||
}
|
||||
|
||||
verbosePrintLintersStatus(cfg, resultLinters, log)
|
||||
|
||||
return resultLinters, nil
|
||||
}
|
||||
|
||||
func verbosePrintLintersStatus(cfg *config.Config, lcs []linter.Config, log logutils.Log) {
|
||||
var linterNames []string
|
||||
for _, lc := range lcs {
|
||||
linterNames = append(linterNames, lc.Linter.Name())
|
||||
}
|
||||
sort.StringSlice(linterNames).Sort()
|
||||
log.Infof("Active %d linters: %s", len(linterNames), linterNames)
|
||||
|
||||
if len(cfg.Linters.Presets) != 0 {
|
||||
sort.StringSlice(cfg.Linters.Presets).Sort()
|
||||
log.Infof("Active presets: %s", cfg.Linters.Presets)
|
||||
}
|
||||
}
|
93
pkg/lint/lintersdb/validator.go
Normal file
93
pkg/lint/lintersdb/validator.go
Normal file
@ -0,0 +1,93 @@
|
||||
package lintersdb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golangci/golangci-lint/pkg/config"
|
||||
)
|
||||
|
||||
type Validator struct {
|
||||
m *Manager
|
||||
}
|
||||
|
||||
func (v Validator) validateLintersNames(cfg *config.Linters) error {
|
||||
allNames := append([]string{}, cfg.Enable...)
|
||||
allNames = append(allNames, cfg.Disable...)
|
||||
for _, name := range allNames {
|
||||
if v.m.getLinterConfig(name) == nil {
|
||||
return fmt.Errorf("no such linter %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) validatePresets(cfg *config.Linters) error {
|
||||
allPresets := v.m.allPresetsSet()
|
||||
for _, p := range cfg.Presets {
|
||||
if !allPresets[p] {
|
||||
return fmt.Errorf("no such preset %q: only next presets exist: (%s)",
|
||||
p, strings.Join(v.m.AllPresets(), "|"))
|
||||
}
|
||||
}
|
||||
|
||||
if len(cfg.Presets) != 0 && cfg.EnableAll {
|
||||
return fmt.Errorf("--presets is incompatible with --enable-all")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) validateAllDisableEnableOptions(cfg *config.Linters) error {
|
||||
if cfg.EnableAll && cfg.DisableAll {
|
||||
return fmt.Errorf("--enable-all and --disable-all options must not be combined")
|
||||
}
|
||||
|
||||
if cfg.DisableAll {
|
||||
if len(cfg.Enable) == 0 && len(cfg.Presets) == 0 {
|
||||
return fmt.Errorf("all linters were disabled, but no one linter was enabled: must enable at least one")
|
||||
}
|
||||
|
||||
if len(cfg.Disable) != 0 {
|
||||
return fmt.Errorf("can't combine options --disable-all and --disable %s", cfg.Disable[0])
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.EnableAll && len(cfg.Enable) != 0 && !cfg.Fast {
|
||||
return fmt.Errorf("can't combine options --enable-all and --enable %s", cfg.Enable[0])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) validateDisabledAndEnabledAtOneMoment(cfg *config.Linters) error {
|
||||
enabledLintersSet := map[string]bool{}
|
||||
for _, name := range cfg.Enable {
|
||||
enabledLintersSet[name] = true
|
||||
}
|
||||
|
||||
for _, name := range cfg.Disable {
|
||||
if enabledLintersSet[name] {
|
||||
return fmt.Errorf("linter %q can't be disabled and enabled at one moment", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Validator) validateEnabledDisabledLintersConfig(cfg *config.Linters) error {
|
||||
validators := []func(cfg *config.Linters) error{
|
||||
v.validateLintersNames,
|
||||
v.validatePresets,
|
||||
v.validateAllDisableEnableOptions,
|
||||
v.validateDisabledAndEnabledAtOneMoment,
|
||||
}
|
||||
for _, v := range validators {
|
||||
if err := v(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user