github.com/atc0005/golangci-lint@v1.10.1/pkg/golinters/utils.go (about)

     1  package golinters
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/token"
     7  	"regexp"
     8  	"strings"
     9  	"sync"
    10  
    11  	"github.com/golangci/golangci-lint/pkg/lint/linter"
    12  	"github.com/golangci/golangci-lint/pkg/packages"
    13  
    14  	"github.com/golangci/golangci-lint/pkg/config"
    15  )
    16  
    17  func formatCode(code string, _ *config.Config) string {
    18  	if strings.Contains(code, "`") {
    19  		return code // TODO: properly escape or remove
    20  	}
    21  
    22  	return fmt.Sprintf("`%s`", code)
    23  }
    24  
    25  func formatCodeBlock(code string, _ *config.Config) string {
    26  	if strings.Contains(code, "`") {
    27  		return code // TODO: properly escape or remove
    28  	}
    29  
    30  	return fmt.Sprintf("```\n%s\n```", code)
    31  }
    32  
    33  type replacePattern struct {
    34  	re   string
    35  	repl string
    36  }
    37  
    38  type replaceRegexp struct {
    39  	re   *regexp.Regexp
    40  	repl string
    41  }
    42  
    43  var replaceRegexps []replaceRegexp
    44  var replaceRegexpsOnce sync.Once
    45  
    46  var replacePatterns = []replacePattern{
    47  	// unparam
    48  	{`^(\S+) - (\S+) is unused$`, "`${1}` - `${2}` is unused"},
    49  	{`^(\S+) - (\S+) always receives (\S+) \((.*)\)$`, "`${1}` - `${2}` always receives `${3}` (`${4}`)"},
    50  	{`^(\S+) - (\S+) always receives (.*)$`, "`${1}` - `${2}` always receives `${3}`"},
    51  
    52  	// interfacer
    53  	{`^(\S+) can be (\S+)$`, "`${1}` can be `${2}`"},
    54  
    55  	// govet
    56  	{`^(\S+) arg list ends with redundant newline$`, "`${1}` arg list ends with redundant newline"},
    57  	{`^(\S+) composite literal uses unkeyed fields$`, "`${1}` composite literal uses unkeyed fields"},
    58  
    59  	// gas
    60  	{`^Blacklisted import (\S+): weak cryptographic primitive$`,
    61  		"Blacklisted import `${1}`: weak cryptographic primitive"},
    62  	{`^TLS InsecureSkipVerify set true.$`, "TLS `InsecureSkipVerify` set true."},
    63  
    64  	// megacheck
    65  	{`^this value of (\S+) is never used$`, "this value of `${1}` is never used"},
    66  	{`^should use time.Since instead of time.Now().Sub$`,
    67  		"should use `time.Since` instead of `time.Now().Sub`"},
    68  	{`^(func|const|field|type) (\S+) is unused$`, "${1} `${2}` is unused"},
    69  }
    70  
    71  func markIdentifiers(s string) string {
    72  	replaceRegexpsOnce.Do(func() {
    73  		for _, p := range replacePatterns {
    74  			r := replaceRegexp{
    75  				re:   regexp.MustCompile(p.re),
    76  				repl: p.repl,
    77  			}
    78  			replaceRegexps = append(replaceRegexps, r)
    79  		}
    80  	})
    81  
    82  	for _, rr := range replaceRegexps {
    83  		rs := rr.re.ReplaceAllString(s, rr.repl)
    84  		if rs != s {
    85  			return rs
    86  		}
    87  	}
    88  
    89  	return s
    90  }
    91  
    92  func getASTFilesForPkg(ctx *linter.Context, pkg *packages.Package) ([]*ast.File, *token.FileSet, error) {
    93  	filenames := pkg.Files(ctx.Cfg.Run.AnalyzeTests)
    94  	files := make([]*ast.File, 0, len(filenames))
    95  	var fset *token.FileSet
    96  	for _, filename := range filenames {
    97  		f := ctx.ASTCache.Get(filename)
    98  		if f == nil {
    99  			return nil, nil, fmt.Errorf("no AST for file %s in cache: %+v", filename, *ctx.ASTCache)
   100  		}
   101  
   102  		if f.Err != nil {
   103  			return nil, nil, fmt.Errorf("can't load AST for file %s: %s", f.Name, f.Err)
   104  		}
   105  
   106  		files = append(files, f.F)
   107  		fset = f.Fset
   108  	}
   109  
   110  	return files, fset, nil
   111  }