diff --git a/src/cmd/go/internal/vet/vetflag.go b/src/cmd/go/internal/vet/vetflag.go index 22bce16cf34..9b5184a4d4e 100644 --- a/src/cmd/go/internal/vet/vetflag.go +++ b/src/cmd/go/internal/vet/vetflag.go @@ -23,20 +23,39 @@ import ( // go vet flag processing // -// We query the flags of the tool specified by GOVETTOOL (default: -// cmd/vet) and accept any of those flags plus any flag valid for 'go -// build'. The tool must support -flags, which prints a description of -// its flags in JSON to stdout. +// We query the flags of the tool specified by -vettool and accept any +// of those flags plus any flag valid for 'go build'. The tool must +// support -flags, which prints a description of its flags in JSON to +// stdout. -// GOVETTOOL specifies the vet command to run. -// This must be an environment variable because -// we need it before flag processing, as we execute -// $GOVETTOOL to discover the set of flags it supports. +// vetTool specifies the vet command to run. +// Any tool that supports the (still unpublished) vet +// command-line protocol may be supplied; see +// golang.org/x/tools/go/analysis/unitchecker for one +// implementation. It is also used by tests. // -// Using an environment variable also makes it easy for users to opt in -// to (and later, opt out of) the new cmd/vet analysis driver during the -// transition. It is also used by tests. -var vetTool = os.Getenv("GOVETTOOL") +// The default behavior (vetTool=="") runs 'go tool vet'. +// +var vetTool string // -vettool + +func init() { + // Extract -vettool by ad hoc flag processing: + // its value is needed even before we can declare + // the flags available during main flag processing. + for i, arg := range os.Args { + if arg == "-vettool" || arg == "--vettool" { + if i+1 >= len(os.Args) { + log.Fatalf("%s requires a filename", arg) + } + vetTool = os.Args[i+1] + break + } else if strings.HasPrefix(arg, "-vettool=") || + strings.HasPrefix(arg, "--vettool=") { + vetTool = arg[strings.IndexByte(arg, '=')+1:] + break + } + } +} // vetFlags processes the command line, splitting it at the first non-flag // into the list of flags and list of packages. @@ -94,6 +113,9 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) { // Add build flags to vetFlagDefn. var cmd base.Command work.AddBuildFlags(&cmd) + // This flag declaration is a placeholder: + // -vettool is actually parsed by the init function above. + cmd.Flag.StringVar(new(string), "vettool", "", "path to vet tool binary") cmd.Flag.VisitAll(func(f *flag.Flag) { vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{ Name: f.Name, diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index a6cfb50558b..c5aa1db50b8 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -178,7 +178,8 @@ func (b *Builder) toolID(name string) string { path := base.Tool(name) desc := "go tool " + name - // Special case: undocumented $GOVETTOOL overrides usual vet, for testing vet. + // Special case: undocumented -vettool overrides usual vet, + // for testing vet or supplying an alternative analysis tool. if name == "vet" && VetTool != "" { path = VetTool desc = VetTool diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go index da5a6ed87c7..6b2125924d7 100644 --- a/src/cmd/vet/vet_test.go +++ b/src/cmd/vet/vet_test.go @@ -118,12 +118,11 @@ func TestVetPrint(t *testing.T) { Build(t) file := filepath.Join("testdata", "print.go") cmd := exec.Command( - "go", "vet", + "go", "vet", "-vettool="+binary, "-printf", "-printfuncs=Warn:1,Warnf:1", file, ) - cmd.Env = append(os.Environ(), "GOVETTOOL="+binary) errchk(cmd, []string{file}, t) }