gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/kisielk/errcheck/main.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "flag" 6 "fmt" 7 "os" 8 "path/filepath" 9 "regexp" 10 "runtime" 11 "strings" 12 13 "github.com/kisielk/errcheck/internal/errcheck" 14 ) 15 16 const ( 17 exitCodeOk int = iota 18 exitUncheckedError 19 exitFatalError 20 ) 21 22 var abspath bool 23 24 type ignoreFlag map[string]*regexp.Regexp 25 26 func (f ignoreFlag) String() string { 27 pairs := make([]string, 0, len(f)) 28 for pkg, re := range f { 29 prefix := "" 30 if pkg != "" { 31 prefix = pkg + ":" 32 } 33 pairs = append(pairs, prefix+re.String()) 34 } 35 return fmt.Sprintf("%q", strings.Join(pairs, ",")) 36 } 37 38 func (f ignoreFlag) Set(s string) error { 39 if s == "" { 40 return nil 41 } 42 for _, pair := range strings.Split(s, ",") { 43 colonIndex := strings.Index(pair, ":") 44 var pkg, re string 45 if colonIndex == -1 { 46 pkg = "" 47 re = pair 48 } else { 49 pkg = pair[:colonIndex] 50 re = pair[colonIndex+1:] 51 } 52 regex, err := regexp.Compile(re) 53 if err != nil { 54 return err 55 } 56 f[pkg] = regex 57 } 58 return nil 59 } 60 61 type tagsFlag []string 62 63 func (f *tagsFlag) String() string { 64 return fmt.Sprintf("%q", strings.Join(*f, " ")) 65 } 66 67 func (f *tagsFlag) Set(s string) error { 68 if s == "" { 69 return nil 70 } 71 tags := strings.Split(s, " ") 72 if tags == nil { 73 return nil 74 } 75 for _, tag := range tags { 76 if tag != "" { 77 *f = append(*f, tag) 78 } 79 } 80 return nil 81 } 82 83 var dotStar = regexp.MustCompile(".*") 84 85 func reportUncheckedErrors(e *errcheck.UncheckedErrors, verbose bool) { 86 wd, err := os.Getwd() 87 if err != nil { 88 wd = "" 89 } 90 for _, uncheckedError := range e.Errors { 91 pos := uncheckedError.Pos.String() 92 if !abspath { 93 newPos, err := filepath.Rel(wd, pos) 94 if err == nil { 95 pos = newPos 96 } 97 } 98 99 if verbose && uncheckedError.FuncName != "" { 100 fmt.Printf("%s:\t%s\t%s\n", pos, uncheckedError.FuncName, uncheckedError.Line) 101 } else { 102 fmt.Printf("%s:\t%s\n", pos, uncheckedError.Line) 103 } 104 } 105 } 106 107 func mainCmd(args []string) int { 108 runtime.GOMAXPROCS(runtime.NumCPU()) 109 110 checker := errcheck.NewChecker() 111 paths, err := parseFlags(checker, args) 112 if err != exitCodeOk { 113 return err 114 } 115 116 if err := checker.CheckPackages(paths...); err != nil { 117 if e, ok := err.(*errcheck.UncheckedErrors); ok { 118 reportUncheckedErrors(e, checker.Verbose) 119 return exitUncheckedError 120 } else if err == errcheck.ErrNoGoFiles { 121 fmt.Fprintln(os.Stderr, err) 122 return exitCodeOk 123 } 124 fmt.Fprintf(os.Stderr, "error: failed to check packages: %s\n", err) 125 return exitFatalError 126 } 127 return exitCodeOk 128 } 129 130 func parseFlags(checker *errcheck.Checker, args []string) ([]string, int) { 131 flags := flag.NewFlagSet(args[0], flag.ContinueOnError) 132 flags.BoolVar(&checker.Blank, "blank", false, "if true, check for errors assigned to blank identifier") 133 flags.BoolVar(&checker.Asserts, "asserts", false, "if true, check for ignored type assertion results") 134 flags.BoolVar(&checker.WithoutTests, "ignoretests", false, "if true, checking of _test.go files is disabled") 135 flags.BoolVar(&checker.WithoutGeneratedCode, "ignoregenerated", false, "if true, checking of files with generated code is disabled") 136 flags.BoolVar(&checker.Verbose, "verbose", false, "produce more verbose logging") 137 138 flags.BoolVar(&abspath, "abspath", false, "print absolute paths to files") 139 140 tags := tagsFlag{} 141 flags.Var(&tags, "tags", "space-separated list of build tags to include") 142 ignorePkg := flags.String("ignorepkg", "", "comma-separated list of package paths to ignore") 143 ignore := ignoreFlag(map[string]*regexp.Regexp{}) 144 flags.Var(ignore, "ignore", "[deprecated] comma-separated list of pairs of the form pkg:regex\n"+ 145 " the regex is used to ignore names within pkg.") 146 147 var excludeFile string 148 flags.StringVar(&excludeFile, "exclude", "", "Path to a file containing a list of functions to exclude from checking") 149 150 if err := flags.Parse(args[1:]); err != nil { 151 return nil, exitFatalError 152 } 153 154 if excludeFile != "" { 155 exclude := make(map[string]bool) 156 fh, err := os.Open(excludeFile) 157 if err != nil { 158 fmt.Fprintf(os.Stderr, "Could not read exclude file: %s\n", err) 159 return nil, exitFatalError 160 } 161 scanner := bufio.NewScanner(fh) 162 for scanner.Scan() { 163 name := scanner.Text() 164 exclude[name] = true 165 166 if checker.Verbose { 167 fmt.Printf("Excluding %s\n", name) 168 } 169 } 170 if err := scanner.Err(); err != nil { 171 fmt.Fprintf(os.Stderr, "Could not read exclude file: %s\n", err) 172 return nil, exitFatalError 173 } 174 checker.SetExclude(exclude) 175 } 176 177 checker.Tags = tags 178 for _, pkg := range strings.Split(*ignorePkg, ",") { 179 if pkg != "" { 180 ignore[pkg] = dotStar 181 } 182 } 183 checker.Ignore = ignore 184 185 paths := flags.Args() 186 if len(paths) == 0 { 187 paths = []string{"."} 188 } 189 return paths, exitCodeOk 190 } 191 192 func main() { 193 os.Exit(mainCmd(os.Args)) 194 }