gitee.com/wgliang/goreporter@v0.0.0-20180902115603-df1b20f7c5d0/linters/golint/linter.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 // golint lints the Go source files named on its command line. 8 package golint 9 10 import ( 11 "flag" 12 "fmt" 13 "go/build" 14 "io/ioutil" 15 "os" 16 "path/filepath" 17 "strings" 18 ) 19 20 var ( 21 minConfidence = flag.Float64("min_confidence", 0.8, "minimum confidence of a problem to print it") 22 setExitStatus = flag.Bool("set_exit_status", false, "set exit status to 1 if any issues are found") 23 suggestions int 24 ) 25 26 func usage() { 27 fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) 28 fmt.Fprintf(os.Stderr, "\tgolint [flags] # runs on package in current directory\n") 29 fmt.Fprintf(os.Stderr, "\tgolint [flags] [packages]\n") 30 fmt.Fprintf(os.Stderr, "\tgolint [flags] [directories] # where a '/...' suffix includes all sub-directories\n") 31 fmt.Fprintf(os.Stderr, "\tgolint [flags] [files] # all must belong to a single package\n") 32 fmt.Fprintf(os.Stderr, "Flags:\n") 33 flag.PrintDefaults() 34 } 35 36 func GoLinter(projectPath []string) (results []string) { 37 flag.Usage = usage 38 flag.Parse() 39 40 // dirsRun, filesRun, and pkgsRun indicate whether golint is applied to 41 // directory, file or package targets. The distinction affects which 42 // checks are run. It is no valid to mix target types. 43 var dirsRun, filesRun, pkgsRun int 44 var args []string 45 for _, arg := range projectPath { 46 if strings.HasSuffix(arg, "/...") && isDir(arg[:len(arg)-len("/...")]) { 47 dirsRun = 1 48 args = append(args, allPackagesInFS(arg)...) 49 } else if isDir(arg) { 50 dirsRun = 1 51 args = append(args, arg) 52 } else if exists(arg) { 53 filesRun = 1 54 args = append(args, arg) 55 } else { 56 pkgsRun = 1 57 args = append(args, arg) 58 } 59 } 60 61 if dirsRun+filesRun+pkgsRun != 1 { 62 usage() 63 os.Exit(2) 64 } 65 switch { 66 case dirsRun == 1: 67 for _, dir := range args { 68 results = append(results, lintDir(dir)...) 69 } 70 case filesRun == 1: 71 return lintFiles(args...) 72 case pkgsRun == 1: 73 for _, pkg := range importPaths(args) { 74 results = append(results, lintPackage(pkg)...) 75 } 76 } 77 78 return 79 } 80 81 func isDir(filename string) bool { 82 fi, err := os.Stat(filename) 83 return err == nil && fi.IsDir() 84 } 85 86 func exists(filename string) bool { 87 _, err := os.Stat(filename) 88 return err == nil 89 } 90 91 func lintFiles(filenames ...string) (results []string) { 92 files := make(map[string][]byte) 93 for _, filename := range filenames { 94 src, err := ioutil.ReadFile(filename) 95 if err != nil { 96 fmt.Fprintln(os.Stderr, err) 97 continue 98 } 99 files[filename] = src 100 } 101 102 l := new(Linter) 103 ps, err := l.LintFiles(files) 104 if err != nil { 105 fmt.Fprintf(os.Stderr, "%v\n", err) 106 return 107 } 108 109 for _, p := range ps { 110 if p.Confidence >= *minConfidence { 111 results = append(results, fmt.Sprintf("%v: %s", p.Position, p.Text)) 112 // suggestions++ 113 } 114 } 115 return results 116 } 117 118 func lintDir(dirname string) []string { 119 pkg, err := build.ImportDir(dirname, 0) 120 return lintImportedPackage(pkg, err) 121 } 122 123 func lintPackage(pkgname string) []string { 124 pkg, err := build.Import(pkgname, ".", 0) 125 return lintImportedPackage(pkg, err) 126 } 127 128 func lintImportedPackage(pkg *build.Package, err error) (results []string) { 129 if err != nil { 130 if _, nogo := err.(*build.NoGoError); nogo { 131 // Don't complain if the failure is due to no Go source files. 132 return 133 } 134 fmt.Fprintln(os.Stderr, err) 135 return 136 } 137 138 var files []string 139 files = append(files, pkg.GoFiles...) 140 files = append(files, pkg.CgoFiles...) 141 files = append(files, pkg.TestGoFiles...) 142 if pkg.Dir != "." { 143 for i, f := range files { 144 files[i] = filepath.Join(pkg.Dir, f) 145 } 146 } 147 // TODO(dsymonds): Do foo_test too (pkg.XTestGoFiles) 148 149 return lintFiles(files...) 150 }