github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/staticcheck_common.go (about)

     1  package golinters
     2  
     3  import (
     4  	"strings"
     5  	"unicode"
     6  
     7  	"golang.org/x/tools/go/analysis"
     8  	"honnef.co/go/tools/analysis/lint"
     9  	scconfig "honnef.co/go/tools/config"
    10  
    11  	"github.com/elek/golangci-lint/pkg/config"
    12  	"github.com/elek/golangci-lint/pkg/logutils"
    13  )
    14  
    15  var debugf = logutils.Debug("megacheck")
    16  
    17  func getGoVersion(settings *config.StaticCheckSettings) string {
    18  	var goVersion string
    19  	if settings != nil {
    20  		goVersion = settings.GoVersion
    21  	}
    22  
    23  	if goVersion != "" {
    24  		return goVersion
    25  	}
    26  
    27  	// TODO: uses "1.13" for backward compatibility, but in the future (v2) must be set by using build.Default.ReleaseTags like staticcheck.
    28  	return "1.13"
    29  }
    30  
    31  func setupStaticCheckAnalyzers(src []*lint.Analyzer, goVersion string, checks []string) []*analysis.Analyzer {
    32  	var names []string
    33  	for _, a := range src {
    34  		names = append(names, a.Analyzer.Name)
    35  	}
    36  
    37  	filter := filterAnalyzerNames(names, checks)
    38  
    39  	var ret []*analysis.Analyzer
    40  	for _, a := range src {
    41  		if filter[a.Analyzer.Name] {
    42  			setAnalyzerGoVersion(a.Analyzer, goVersion)
    43  			ret = append(ret, a.Analyzer)
    44  		}
    45  	}
    46  
    47  	return ret
    48  }
    49  
    50  func setAnalyzerGoVersion(a *analysis.Analyzer, goVersion string) {
    51  	if v := a.Flags.Lookup("go"); v != nil {
    52  		if err := v.Value.Set(goVersion); err != nil {
    53  			debugf("Failed to set go version: %s", err)
    54  		}
    55  	}
    56  }
    57  
    58  func staticCheckConfig(settings *config.StaticCheckSettings) *scconfig.Config {
    59  	var cfg *scconfig.Config
    60  
    61  	if settings == nil || !settings.HasConfiguration() {
    62  		return &scconfig.Config{
    63  			Checks:                  []string{"*"}, // override for compatibility reason. Must drop in the next major version.
    64  			Initialisms:             scconfig.DefaultConfig.Initialisms,
    65  			DotImportWhitelist:      scconfig.DefaultConfig.DotImportWhitelist,
    66  			HTTPStatusCodeWhitelist: scconfig.DefaultConfig.HTTPStatusCodeWhitelist,
    67  		}
    68  	}
    69  
    70  	cfg = &scconfig.Config{
    71  		Checks:                  settings.Checks,
    72  		Initialisms:             settings.Initialisms,
    73  		DotImportWhitelist:      settings.DotImportWhitelist,
    74  		HTTPStatusCodeWhitelist: settings.HTTPStatusCodeWhitelist,
    75  	}
    76  
    77  	if len(cfg.Checks) == 0 {
    78  		cfg.Checks = append(cfg.Checks, "*") // override for compatibility reason. Must drop in the next major version.
    79  	}
    80  
    81  	if len(cfg.Initialisms) == 0 {
    82  		cfg.Initialisms = append(cfg.Initialisms, scconfig.DefaultConfig.Initialisms...)
    83  	}
    84  
    85  	if len(cfg.DotImportWhitelist) == 0 {
    86  		cfg.DotImportWhitelist = append(cfg.DotImportWhitelist, scconfig.DefaultConfig.DotImportWhitelist...)
    87  	}
    88  
    89  	if len(cfg.HTTPStatusCodeWhitelist) == 0 {
    90  		cfg.HTTPStatusCodeWhitelist = append(cfg.HTTPStatusCodeWhitelist, scconfig.DefaultConfig.HTTPStatusCodeWhitelist...)
    91  	}
    92  
    93  	cfg.Checks = normalizeList(cfg.Checks)
    94  	cfg.Initialisms = normalizeList(cfg.Initialisms)
    95  	cfg.DotImportWhitelist = normalizeList(cfg.DotImportWhitelist)
    96  	cfg.HTTPStatusCodeWhitelist = normalizeList(cfg.HTTPStatusCodeWhitelist)
    97  
    98  	return cfg
    99  }
   100  
   101  // https://github.com/dominikh/go-tools/blob/9bf17c0388a65710524ba04c2d821469e639fdc2/lintcmd/lint.go#L437-L477
   102  // nolint // Keep the original source code.
   103  func filterAnalyzerNames(analyzers []string, checks []string) map[string]bool {
   104  	allowedChecks := map[string]bool{}
   105  
   106  	for _, check := range checks {
   107  		b := true
   108  		if len(check) > 1 && check[0] == '-' {
   109  			b = false
   110  			check = check[1:]
   111  		}
   112  
   113  		if check == "*" || check == "all" {
   114  			// Match all
   115  			for _, c := range analyzers {
   116  				allowedChecks[c] = b
   117  			}
   118  		} else if strings.HasSuffix(check, "*") {
   119  			// Glob
   120  			prefix := check[:len(check)-1]
   121  			isCat := strings.IndexFunc(prefix, func(r rune) bool { return unicode.IsNumber(r) }) == -1
   122  
   123  			for _, a := range analyzers {
   124  				idx := strings.IndexFunc(a, func(r rune) bool { return unicode.IsNumber(r) })
   125  				if isCat {
   126  					// Glob is S*, which should match S1000 but not SA1000
   127  					cat := a[:idx]
   128  					if prefix == cat {
   129  						allowedChecks[a] = b
   130  					}
   131  				} else {
   132  					// Glob is S1*
   133  					if strings.HasPrefix(a, prefix) {
   134  						allowedChecks[a] = b
   135  					}
   136  				}
   137  			}
   138  		} else {
   139  			// Literal check name
   140  			allowedChecks[check] = b
   141  		}
   142  	}
   143  	return allowedChecks
   144  }
   145  
   146  // https://github.com/dominikh/go-tools/blob/9bf17c0388a65710524ba04c2d821469e639fdc2/config/config.go#L95-L116
   147  func normalizeList(list []string) []string {
   148  	if len(list) > 1 {
   149  		nlist := make([]string, 0, len(list))
   150  		nlist = append(nlist, list[0])
   151  		for i, el := range list[1:] {
   152  			if el != list[i] {
   153  				nlist = append(nlist, el)
   154  			}
   155  		}
   156  		list = nlist
   157  	}
   158  
   159  	for _, el := range list {
   160  		if el == "inherit" {
   161  			// This should never happen, because the default config
   162  			// should not use "inherit"
   163  			panic(`unresolved "inherit"`)
   164  		}
   165  	}
   166  
   167  	return list
   168  }