github.com/thrasher-corp/golangci-lint@v1.17.3/pkg/lint/lintersdb/enabled_set.go (about)

     1  package lintersdb
     2  
     3  import (
     4  	"sort"
     5  
     6  	"github.com/golangci/golangci-lint/pkg/config"
     7  	"github.com/golangci/golangci-lint/pkg/lint/linter"
     8  	"github.com/golangci/golangci-lint/pkg/logutils"
     9  )
    10  
    11  type EnabledSet struct {
    12  	m   *Manager
    13  	v   *Validator
    14  	log logutils.Log
    15  	cfg *config.Config
    16  }
    17  
    18  func NewEnabledSet(m *Manager, v *Validator, log logutils.Log, cfg *config.Config) *EnabledSet {
    19  	return &EnabledSet{
    20  		m:   m,
    21  		v:   v,
    22  		log: log,
    23  		cfg: cfg,
    24  	}
    25  }
    26  
    27  // nolint:gocyclo
    28  func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*linter.Config) map[string]*linter.Config {
    29  	resultLintersSet := map[string]*linter.Config{}
    30  	switch {
    31  	case len(lcfg.Presets) != 0:
    32  		break // imply --disable-all
    33  	case lcfg.EnableAll:
    34  		resultLintersSet = linterConfigsToMap(es.m.GetAllSupportedLinterConfigs())
    35  	case lcfg.DisableAll:
    36  		break
    37  	default:
    38  		resultLintersSet = linterConfigsToMap(enabledByDefaultLinters)
    39  	}
    40  
    41  	// --presets can only add linters to default set
    42  	for _, p := range lcfg.Presets {
    43  		for _, lc := range es.m.GetAllLinterConfigsForPreset(p) {
    44  			lc := lc
    45  			resultLintersSet[lc.Name()] = lc
    46  		}
    47  	}
    48  
    49  	// --fast removes slow linters from current set.
    50  	// It should be after --presets to be able to run only fast linters in preset.
    51  	// It should be before --enable and --disable to be able to enable or disable specific linter.
    52  	if lcfg.Fast {
    53  		for name := range resultLintersSet {
    54  			if es.m.GetLinterConfig(name).NeedsSSARepr {
    55  				delete(resultLintersSet, name)
    56  			}
    57  		}
    58  	}
    59  
    60  	metaLinters := es.m.GetMetaLinters()
    61  
    62  	for _, name := range lcfg.Enable {
    63  		if metaLinter := metaLinters[name]; metaLinter != nil {
    64  			// e.g. if we use --enable=megacheck we should add staticcheck,unused and gosimple to result set
    65  			for _, childLinter := range metaLinter.DefaultChildLinterNames() {
    66  				resultLintersSet[childLinter] = es.m.GetLinterConfig(childLinter)
    67  			}
    68  			continue
    69  		}
    70  
    71  		lc := es.m.GetLinterConfig(name)
    72  		// it's important to use lc.Name() nor name because name can be alias
    73  		resultLintersSet[lc.Name()] = lc
    74  	}
    75  
    76  	for _, name := range lcfg.Disable {
    77  		if metaLinter := metaLinters[name]; metaLinter != nil {
    78  			// e.g. if we use --disable=megacheck we should remove staticcheck,unused and gosimple from result set
    79  			for _, childLinter := range metaLinter.DefaultChildLinterNames() {
    80  				delete(resultLintersSet, childLinter)
    81  			}
    82  			continue
    83  		}
    84  
    85  		lc := es.m.GetLinterConfig(name)
    86  		// it's important to use lc.Name() nor name because name can be alias
    87  		delete(resultLintersSet, lc.Name())
    88  	}
    89  
    90  	return resultLintersSet
    91  }
    92  
    93  func (es EnabledSet) optimizeLintersSet(linters map[string]*linter.Config) {
    94  	for _, metaLinter := range es.m.GetMetaLinters() {
    95  		var children []string
    96  		for _, child := range metaLinter.AllChildLinterNames() {
    97  			if _, ok := linters[child]; ok {
    98  				children = append(children, child)
    99  			}
   100  		}
   101  
   102  		if len(children) <= 1 {
   103  			continue
   104  		}
   105  
   106  		for _, child := range children {
   107  			delete(linters, child)
   108  		}
   109  		builtLinterConfig, err := metaLinter.BuildLinterConfig(children)
   110  		if err != nil {
   111  			panic("shouldn't fail during linter building: " + err.Error())
   112  		}
   113  		linters[metaLinter.Name()] = builtLinterConfig
   114  		es.log.Infof("Optimized sublinters %s into metalinter %s", children, metaLinter.Name())
   115  	}
   116  }
   117  
   118  func (es EnabledSet) Get(optimize bool) ([]*linter.Config, error) {
   119  	if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	resultLintersSet := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters())
   124  	es.verbosePrintLintersStatus(resultLintersSet)
   125  	if optimize {
   126  		es.optimizeLintersSet(resultLintersSet)
   127  	}
   128  
   129  	var resultLinters []*linter.Config
   130  	for _, lc := range resultLintersSet {
   131  		resultLinters = append(resultLinters, lc)
   132  	}
   133  
   134  	return resultLinters, nil
   135  }
   136  
   137  func (es EnabledSet) verbosePrintLintersStatus(lcs map[string]*linter.Config) {
   138  	var linterNames []string
   139  	for _, lc := range lcs {
   140  		linterNames = append(linterNames, lc.Name())
   141  	}
   142  	sort.StringSlice(linterNames).Sort()
   143  	es.log.Infof("Active %d linters: %s", len(linterNames), linterNames)
   144  
   145  	if len(es.cfg.Linters.Presets) != 0 {
   146  		sort.StringSlice(es.cfg.Linters.Presets).Sort()
   147  		es.log.Infof("Active presets: %s", es.cfg.Linters.Presets)
   148  	}
   149  }