www.github.com/golangci/golangci-lint.git@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 }