github.com/serversong/goreporter@v0.0.0-20200325104552-3cfaf44fd178/linters/simplecode/lint/lintutil/util.go (about) 1 // Copyright (c) 2013 The Go Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file or at 5 // https://developers.google.com/open-source/licenses/bsd. 6 7 // Package lintutil provides helpers for writing linter command lines. 8 package lintutil // import "github.com/360EntSecGroup-Skylar/goreporter/linters/simplecode/lint/lintutil" 9 10 import ( 11 "flag" 12 "fmt" 13 "go/build" 14 "io/ioutil" 15 "os" 16 "path/filepath" 17 "strings" 18 19 "github.com/360EntSecGroup-Skylar/goreporter/linters/simplecode/lint" 20 21 "github.com/360EntSecGroup-Skylar/goreporter/linters/simplecode/gotool" 22 ) 23 24 var ( 25 excepts = []string{"vendor"} 26 ) 27 28 func usage(name string, flags *flag.FlagSet) func() { 29 return func() { 30 fmt.Fprintf(os.Stderr, "Usage of %s:\n", name) 31 fmt.Fprintf(os.Stderr, "\t%s [flags] # runs on package in current directory\n", name) 32 fmt.Fprintf(os.Stderr, "\t%s [flags] packages\n", name) 33 fmt.Fprintf(os.Stderr, "\t%s [flags] directory\n", name) 34 fmt.Fprintf(os.Stderr, "\t%s [flags] files... # must be a single package\n", name) 35 fmt.Fprintf(os.Stderr, "Flags:\n") 36 flags.PrintDefaults() 37 } 38 } 39 40 type runner struct { 41 funcs []lint.Func 42 minConfidence float64 43 tags []string 44 SimpleResult []string 45 46 unclean bool 47 } 48 49 func (runner runner) resolveRelative(importPaths []string) (goFiles bool, err error) { 50 if len(importPaths) == 0 { 51 return false, nil 52 } 53 if strings.HasSuffix(importPaths[0], ".go") { 54 // User is specifying a package in terms of .go files, don't resolve 55 return true, nil 56 } 57 wd, err := os.Getwd() 58 if err != nil { 59 return false, err 60 } 61 ctx := build.Default 62 ctx.BuildTags = runner.tags 63 for i, path := range importPaths { 64 githubIndex := strings.LastIndex(path, "github.com") 65 if githubIndex < len(path) && githubIndex >= 0 { 66 path = path[githubIndex:] 67 } 68 bpkg, err := ctx.Import(path, wd, build.FindOnly) 69 if err != nil { 70 return false, fmt.Errorf("can't load package %q: %v", path, err) 71 } 72 importPaths[i] = bpkg.ImportPath 73 } 74 return false, nil 75 } 76 77 func ProcessArgs(except, name string, funcs []lint.Func, args []string) []string { 78 excepts = append(excepts, strings.Split(except, ",")...) 79 flags := &flag.FlagSet{} 80 flags.Usage = usage(name, flags) 81 var minConfidence = flags.Float64("min_confidence", 0.8, "minimum confidence of a problem to print it") 82 var tags = flags.String("tags", "", "List of `build tags`") 83 flags.Parse(args) 84 85 runner := &runner{ 86 funcs: funcs, 87 minConfidence: *minConfidence, 88 tags: strings.Fields(*tags), 89 } 90 paths := gotool.ImportPaths(flags.Args()) 91 goFiles, err := runner.resolveRelative(paths) 92 if err != nil { 93 fmt.Fprintln(os.Stderr, err) 94 runner.unclean = true 95 } 96 if goFiles { 97 runner.lintFiles(paths...) 98 } else { 99 for _, path := range paths { 100 runner.lintPackage(path) 101 } 102 } 103 return runner.SimpleResult 104 } 105 106 func (runner *runner) lintFiles(filenames ...string) { 107 files := make(map[string][]byte) 108 for _, filename := range filenames { 109 src, err := ioutil.ReadFile(filename) 110 if err != nil { 111 fmt.Fprintln(os.Stderr, err) 112 runner.unclean = true 113 continue 114 } 115 files[filename] = src 116 } 117 118 l := &lint.Linter{ 119 Funcs: runner.funcs, 120 } 121 ps, err := l.LintFiles(files) 122 if err != nil { 123 fmt.Fprintf(os.Stderr, "%v\n", err) 124 runner.unclean = true 125 return 126 } 127 if len(ps) > 0 { 128 runner.unclean = true 129 } 130 for _, p := range ps { 131 if p.Confidence >= runner.minConfidence { 132 runner.SimpleResult = append(runner.SimpleResult, fmt.Sprintf("%v: %s", p.Position, p.Text)) 133 } 134 } 135 } 136 137 func (runner *runner) lintPackage(pkgname string) { 138 ctx := build.Default 139 ctx.BuildTags = runner.tags 140 pkg, err := ctx.Import(pkgname, ".", 0) 141 runner.lintImportedPackage(pkg, err) 142 } 143 144 func (runner *runner) lintImportedPackage(pkg *build.Package, err error) { 145 if err != nil { 146 if _, nogo := err.(*build.NoGoError); nogo { 147 // Don't complain if the failure is due to no Go source files. 148 return 149 } 150 fmt.Fprintln(os.Stderr, err) 151 runner.unclean = true 152 return 153 } 154 155 var files []string 156 xtest := pkg.XTestGoFiles 157 files = append(files, filterFiles(pkg.GoFiles, pkg.Dir)...) 158 files = append(files, filterFiles(pkg.CgoFiles, pkg.Dir)...) 159 files = append(files, filterFiles(pkg.TestGoFiles, pkg.Dir)...) 160 if pkg.Dir != "." { 161 for i, f := range xtest { 162 xtest[i] = filepath.Join(pkg.Dir, f) 163 } 164 } 165 runner.lintFiles(xtest...) 166 runner.lintFiles(files...) 167 } 168 169 func filterFiles(files []string, pkgDir string) (filtedFiles []string) { 170 if pkgDir != "." { 171 for i, f := range files { 172 files[i] = filepath.Join(pkgDir, f) 173 if !exceptPkg(files[i]) { 174 filtedFiles = append(filtedFiles, files[i]) 175 } 176 } 177 } else { 178 return files 179 } 180 return filtedFiles 181 } 182 183 // exceptPkg is a function that will determine whether the package is an exception. 184 func exceptPkg(pkg string) bool { 185 if len(excepts) == 0 { 186 return false 187 } 188 for _, va := range excepts { 189 if strings.Contains(pkg, va) { 190 return true 191 } 192 } 193 return false 194 }