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  }