github.com/gwaycc/gometalinter@v3.0.0+incompatible/_linters/src/mvdan.cc/lint/cmd/metalint/main.go (about)

     1  // Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
     2  // See LICENSE for licensing information
     3  
     4  package main // import "mvdan.cc/lint/cmd/metalint"
     5  
     6  import (
     7  	"flag"
     8  	"fmt"
     9  	"os"
    10  	"strings"
    11  
    12  	"golang.org/x/tools/go/loader"
    13  	"golang.org/x/tools/go/ssa"
    14  	"golang.org/x/tools/go/ssa/ssautil"
    15  
    16  	"mvdan.cc/lint"
    17  
    18  	"github.com/kisielk/gotool"
    19  
    20  	interfacer "mvdan.cc/interfacer/check"
    21  	unparam "mvdan.cc/unparam/check"
    22  )
    23  
    24  var tests = flag.Bool("tests", false, "include tests")
    25  
    26  func main() {
    27  	flag.Parse()
    28  	if err := runLinters(flag.Args()...); err != nil {
    29  		fmt.Fprintln(os.Stderr, err)
    30  		os.Exit(1)
    31  	}
    32  }
    33  
    34  var linters = [...]struct {
    35  	name    string
    36  	checker lint.Checker
    37  }{
    38  	{"unparam", &unparam.Checker{}},
    39  	{"interfacer", &interfacer.Checker{}},
    40  }
    41  
    42  type metaChecker struct {
    43  	wd string
    44  
    45  	lprog *loader.Program
    46  	prog  *ssa.Program
    47  }
    48  
    49  func runLinters(args ...string) error {
    50  	paths := gotool.ImportPaths(args)
    51  	wd, err := os.Getwd()
    52  	if err != nil {
    53  		return err
    54  	}
    55  	c := &metaChecker{wd: wd}
    56  	var conf loader.Config
    57  	if _, err := conf.FromArgs(paths, *tests); err != nil {
    58  		return err
    59  	}
    60  	if c.lprog, err = conf.Load(); err != nil {
    61  		return err
    62  	}
    63  	for _, l := range linters {
    64  		l.checker.Program(c.lprog)
    65  		if ssaChecker, ok := l.checker.(lint.WithSSA); ok {
    66  			if c.prog == nil {
    67  				c.prog = ssautil.CreateProgram(c.lprog, 0)
    68  				c.prog.Build()
    69  			}
    70  			ssaChecker.ProgramSSA(c.prog)
    71  		}
    72  		issues, err := l.checker.Check()
    73  		if err != nil {
    74  			return err
    75  		}
    76  		c.printIssues(l.name, issues)
    77  	}
    78  	return nil
    79  }
    80  
    81  func (c *metaChecker) printIssues(name string, issues []lint.Issue) {
    82  	for _, issue := range issues {
    83  		fpos := c.lprog.Fset.Position(issue.Pos()).String()
    84  		if strings.HasPrefix(fpos, c.wd) {
    85  			fpos = fpos[len(c.wd)+1:]
    86  		}
    87  		fmt.Printf("%s: %s (%s)\n", fpos, issue.Message(), name)
    88  	}
    89  }