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