go/analysis/cmd/vet-lite: remove deprecation warnings
Per discussion with Russ, the -all/-source/-v flags now silently do nothing, and the -printffuncs (et al) shims now silently delegate to -printf.funcs, and the -NAME.enable (et al) flags are now called just -NAME. Various minor tweaks to command-line help messages. Change-Id: If6587937f58446e605eca4d3a5be0aaf6287065d Reviewed-on: https://go-review.googlesource.com/c/148879 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
a8570e12b6
commit
150d8ac285
|
@ -8,6 +8,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -41,7 +42,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var analyzers = []*analysis.Analyzer{
|
var analyzers = []*analysis.Analyzer{
|
||||||
// For now, just the traditional vet suite:
|
|
||||||
asmdecl.Analyzer,
|
asmdecl.Analyzer,
|
||||||
assign.Analyzer,
|
assign.Analyzer,
|
||||||
atomic.Analyzer,
|
atomic.Analyzer,
|
||||||
|
@ -56,7 +56,6 @@ var analyzers = []*analysis.Analyzer{
|
||||||
nilfunc.Analyzer,
|
nilfunc.Analyzer,
|
||||||
pkgfact.Analyzer,
|
pkgfact.Analyzer,
|
||||||
printf.Analyzer,
|
printf.Analyzer,
|
||||||
// shadow.Analyzer, // experimental; not enabled by default
|
|
||||||
shift.Analyzer,
|
shift.Analyzer,
|
||||||
stdmethods.Analyzer,
|
stdmethods.Analyzer,
|
||||||
structtag.Analyzer,
|
structtag.Analyzer,
|
||||||
|
@ -77,47 +76,49 @@ func main() {
|
||||||
|
|
||||||
// Flags for legacy vet compatibility.
|
// Flags for legacy vet compatibility.
|
||||||
//
|
//
|
||||||
// These flags, plus the shims in analysisflags, enable all
|
// These flags, plus the shims in analysisflags, enable
|
||||||
// existing scripts that run vet to continue to work.
|
// existing scripts that run vet to continue to work.
|
||||||
//
|
//
|
||||||
// We still need to deal with legacy vet's "experimental"
|
// Legacy vet had the concept of "experimental" checkers. There
|
||||||
// checkers. In vet there is exactly one such checker, shadow,
|
// was exactly one, shadow, and it had to be explicitly enabled
|
||||||
// and it must be enabled explicitly with the -shadow flag, but
|
// by the -shadow flag, which would of course disable all the
|
||||||
// of course setting it disables all the other tristate flags,
|
// other tristate flags, requiring the -all flag to reenable them.
|
||||||
// requiring the -all flag to reenable them.
|
// (By itself, -all did not enable all checkers.)
|
||||||
|
// The -all flag is no longer needed, so it is a no-op.
|
||||||
//
|
//
|
||||||
// I don't believe this feature carries its weight. I propose we
|
// The shadow analyzer has been removed from the suite,
|
||||||
// simply skip shadow for now; the few users that want it can
|
// but can be run using these additional commands:
|
||||||
// run "go vet -vettool=..." using a vet tool that includes
|
// $ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
|
||||||
// shadow, either as an additional step, with a shadow
|
// $ go vet -vettool=$(which shadow)
|
||||||
// "singlechecker", or in place of the regular vet step on a
|
// Alternatively, one could build a multichecker containing all
|
||||||
// multichecker with a hand-picked suite of checkers.
|
// the desired checks (vet's suite + shadow) and run it in a
|
||||||
// Or, we could improve the shadow checker to the point where it
|
// single "go vet" command.
|
||||||
// need not be experimental.
|
|
||||||
for _, name := range []string{"source", "v", "all"} {
|
for _, name := range []string{"source", "v", "all"} {
|
||||||
flag.Var(warnBoolFlag(name), name, "no effect (deprecated)")
|
_ = flag.Bool(name, false, "no effect (deprecated)")
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
analysisflags.Help("vet", analyzers, nil)
|
fmt.Fprintln(os.Stderr, `Usage of vet:
|
||||||
|
vet unit.cfg # execute analysis specified by config file
|
||||||
|
vet help # general help
|
||||||
|
vet help name # help on specific analyzer and its flags`)
|
||||||
|
flag.PrintDefaults()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
analyzers = analysisflags.Parse(analyzers, true)
|
analyzers = analysisflags.Parse(analyzers, true)
|
||||||
|
|
||||||
args := flag.Args()
|
args := flag.Args()
|
||||||
|
if len(args) == 0 {
|
||||||
|
flag.Usage()
|
||||||
|
}
|
||||||
|
if args[0] == "help" {
|
||||||
|
analysisflags.Help("vet", analyzers, args[1:])
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
if len(args) != 1 || !strings.HasSuffix(args[0], ".cfg") {
|
if len(args) != 1 || !strings.HasSuffix(args[0], ".cfg") {
|
||||||
log.Fatalf("invalid command: want .cfg file (this reduced version of vet is intended to be run only by the 'go vet' command)")
|
log.Fatalf("invalid command: want .cfg file (this reduced version of vet is intended to be run only by the 'go vet' command)")
|
||||||
}
|
}
|
||||||
|
|
||||||
unitchecker.Main(args[0], analyzers)
|
unitchecker.Main(args[0], analyzers)
|
||||||
}
|
}
|
||||||
|
|
||||||
type warnBoolFlag string
|
|
||||||
|
|
||||||
func (f warnBoolFlag) Set(s string) error {
|
|
||||||
log.Printf("warning: deprecated flag -%s has no effect", string(f))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (f warnBoolFlag) IsBoolFlag() bool { return true }
|
|
||||||
func (f warnBoolFlag) String() string { return "false" }
|
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
// using the golang.org/x/tools/go/packages API to load packages in any
|
// using the golang.org/x/tools/go/packages API to load packages in any
|
||||||
// build system.
|
// build system.
|
||||||
//
|
//
|
||||||
// Each analysis flag name is preceded by the analysis name: --analysis.flag.
|
// Each analyzer flag name is preceded by the analyzer name: -NAME.flag.
|
||||||
// In addition, the --analysis.enabled flag controls whether the
|
// In addition, the -NAME flag itself controls whether the
|
||||||
// diagnostics of that analysis are displayed. (A disabled analysis may yet
|
// diagnostics of that analyzer are displayed. (A disabled analyzer may yet
|
||||||
// be run if it is required by some other analysis that is enabled.)
|
// be run if it is required by some other analyzer that is enabled.)
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -58,9 +58,7 @@ func main() {
|
||||||
loopclosure.Analyzer,
|
loopclosure.Analyzer,
|
||||||
lostcancel.Analyzer,
|
lostcancel.Analyzer,
|
||||||
nilfunc.Analyzer,
|
nilfunc.Analyzer,
|
||||||
pkgfact.Analyzer,
|
|
||||||
printf.Analyzer,
|
printf.Analyzer,
|
||||||
// shadow.Analyzer, // experimental; not enabled by default
|
|
||||||
shift.Analyzer,
|
shift.Analyzer,
|
||||||
stdmethods.Analyzer,
|
stdmethods.Analyzer,
|
||||||
structtag.Analyzer,
|
structtag.Analyzer,
|
||||||
|
@ -72,12 +70,9 @@ func main() {
|
||||||
|
|
||||||
// for debugging:
|
// for debugging:
|
||||||
findcall.Analyzer,
|
findcall.Analyzer,
|
||||||
|
pkgfact.Analyzer,
|
||||||
|
|
||||||
// use SSA:
|
// uses SSA:
|
||||||
nilness.Analyzer,
|
nilness.Analyzer,
|
||||||
|
|
||||||
// Work in progress:
|
|
||||||
// httpheader.Analyzer,
|
|
||||||
// deadcode.Analyzer,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse creates a flag for each of the analyzer's flags,
|
// Parse creates a flag for each of the analyzer's flags,
|
||||||
// including (in multi mode) an --analysis.enable flag,
|
// including (in multi mode) a flag named after the analyzer,
|
||||||
// parses the flags, then filters and returns the list of
|
// parses the flags, then filters and returns the list of
|
||||||
// analyzers enabled by flags.
|
// analyzers enabled by flags.
|
||||||
func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
|
func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
|
||||||
|
@ -36,16 +36,15 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
|
||||||
for _, a := range analyzers {
|
for _, a := range analyzers {
|
||||||
var prefix string
|
var prefix string
|
||||||
|
|
||||||
// Add -analysis.enable flag.
|
// Add -NAME flag to enable it.
|
||||||
if multi {
|
if multi {
|
||||||
prefix = a.Name + "."
|
prefix = a.Name + "."
|
||||||
|
|
||||||
enable := new(triState)
|
enable := new(triState)
|
||||||
enableName := prefix + "enable"
|
|
||||||
enableUsage := "enable " + a.Name + " analysis"
|
enableUsage := "enable " + a.Name + " analysis"
|
||||||
flag.Var(enable, enableName, enableUsage)
|
flag.Var(enable, a.Name, enableUsage)
|
||||||
enabled[a] = enable
|
enabled[a] = enable
|
||||||
analysisFlags = append(analysisFlags, analysisFlag{enableName, true, enableUsage})
|
analysisFlags = append(analysisFlags, analysisFlag{a.Name, true, enableUsage})
|
||||||
}
|
}
|
||||||
|
|
||||||
a.Flags.VisitAll(func(f *flag.Flag) {
|
a.Flags.VisitAll(func(f *flag.Flag) {
|
||||||
|
@ -73,8 +72,7 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
|
||||||
for old, new := range vetLegacyFlags {
|
for old, new := range vetLegacyFlags {
|
||||||
newFlag := flag.Lookup(new)
|
newFlag := flag.Lookup(new)
|
||||||
if newFlag != nil && flag.Lookup(old) == nil {
|
if newFlag != nil && flag.Lookup(old) == nil {
|
||||||
oldFlag := &warnFlag{old, new, newFlag.Value}
|
flag.Var(newFlag.Value, old, "deprecated alias for -"+new)
|
||||||
flag.Var(oldFlag, old, "deprecated alias for -"+new)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +88,8 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any --foo.enable flag is true, run only those analyzers. Otherwise,
|
// If any -NAME flag is true, run only those analyzers. Otherwise,
|
||||||
// if any --foo.enable flag is false, run all but those analyzers.
|
// if any -NAME flag is false, run all but those analyzers.
|
||||||
if multi {
|
if multi {
|
||||||
var hasTrue, hasFalse bool
|
var hasTrue, hasFalse bool
|
||||||
for _, ts := range enabled {
|
for _, ts := range enabled {
|
||||||
|
@ -204,7 +202,7 @@ func (ts *triState) Set(value string) error {
|
||||||
b, err := strconv.ParseBool(value)
|
b, err := strconv.ParseBool(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// This error message looks poor but package "flag" adds
|
// This error message looks poor but package "flag" adds
|
||||||
// "invalid boolean value %q for -foo.enable: %s"
|
// "invalid boolean value %q for -NAME: %s"
|
||||||
return fmt.Errorf("want true or false")
|
return fmt.Errorf("want true or false")
|
||||||
}
|
}
|
||||||
if b {
|
if b {
|
||||||
|
@ -234,59 +232,11 @@ func (ts triState) IsBoolFlag() bool {
|
||||||
// Legacy flag support
|
// Legacy flag support
|
||||||
|
|
||||||
// vetLegacyFlags maps flags used by legacy vet to their corresponding
|
// vetLegacyFlags maps flags used by legacy vet to their corresponding
|
||||||
// new names. Uses of the old names will continue to work, but with a
|
// new names. The old names will continue to work.
|
||||||
// log message. TODO(adonovan): delete this mechanism after Nov 2019.
|
|
||||||
var vetLegacyFlags = map[string]string{
|
var vetLegacyFlags = map[string]string{
|
||||||
"asmdecl": "asmdecl.enable",
|
|
||||||
"assign": "assign.enable",
|
|
||||||
"atomic": "atomic.enable",
|
|
||||||
"bool": "bools.enable",
|
|
||||||
"buildtags": "buildtag.enable",
|
|
||||||
"cgocall": "cgocall.enable",
|
|
||||||
"composites": "composites.enable",
|
|
||||||
"compositewhitelist": "composites.whitelist",
|
"compositewhitelist": "composites.whitelist",
|
||||||
"copylocks": "copylocks.enable",
|
|
||||||
"flags": "flags.enable",
|
|
||||||
"httpresponse": "httpresponse.enable",
|
|
||||||
"lostcancel": "lostcancel.enable",
|
|
||||||
"methods": "stdmethods.enable",
|
|
||||||
"nilfunc": "nilfunc.enable",
|
|
||||||
"printf": "printf.enable",
|
|
||||||
"printfuncs": "printf.funcs",
|
"printfuncs": "printf.funcs",
|
||||||
"rangeloops": "loopclosure.enable",
|
|
||||||
"shadow": "shadow.enable",
|
|
||||||
"shadowstrict": "shadow.strict",
|
"shadowstrict": "shadow.strict",
|
||||||
"shift": "shift.enable",
|
|
||||||
"source": "source.enable",
|
|
||||||
"structtags": "structtag.enable",
|
|
||||||
"tests": "tests.enable",
|
|
||||||
// "unmarshal": "unmarshal.enable", // TODO(adonovan) a new checker
|
|
||||||
"unreachable": "unreachable.enable",
|
|
||||||
"unsafeptr": "unsafeptr.enable",
|
|
||||||
"unusedresult": "unusedresult.enable",
|
|
||||||
"unusedfuncs": "unusedresult.funcs",
|
"unusedfuncs": "unusedresult.funcs",
|
||||||
"unusedstringmethods": "unusedresult.stringmethods",
|
"unusedstringmethods": "unusedresult.stringmethods",
|
||||||
}
|
}
|
||||||
|
|
||||||
type warnFlag struct {
|
|
||||||
old, new string
|
|
||||||
flag.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *warnFlag) Set(s string) error {
|
|
||||||
log.Printf("warning: deprecated flag -%s; use -%s instead", f.old, f.new)
|
|
||||||
return f.Value.Set(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *warnFlag) IsBoolFlag() bool {
|
|
||||||
b, ok := f.Value.(interface{ IsBoolFlag() bool })
|
|
||||||
return ok && b.IsBoolFlag()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *warnFlag) String() string {
|
|
||||||
// The flag package may call new(warnFlag).String.
|
|
||||||
if f.Value == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return f.Value.String()
|
|
||||||
}
|
|
||||||
|
|
|
@ -45,11 +45,11 @@ func TestExec(t *testing.T) {
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{"", "[a1 a2 a3]"},
|
{"", "[a1 a2 a3]"},
|
||||||
{"-a1.enable=0", "[a2 a3]"},
|
{"-a1=0", "[a2 a3]"},
|
||||||
{"-a1.enable=1", "[a1]"},
|
{"-a1=1", "[a1]"},
|
||||||
{"-a1.enable", "[a1]"},
|
{"-a1", "[a1]"},
|
||||||
{"-a1.enable=1 -a3.enable=1", "[a1 a3]"},
|
{"-a1=1 -a3=1", "[a1 a3]"},
|
||||||
{"-a1.enable=1 -a3.enable=0", "[a1]"},
|
{"-a1=1 -a3=0", "[a1]"},
|
||||||
} {
|
} {
|
||||||
cmd := exec.Command(progname, "-test.run=TestExec")
|
cmd := exec.Command(progname, "-test.run=TestExec")
|
||||||
cmd.Env = append(os.Environ(), "ANALYSISFLAGS_CHILD=1", "FLAGS="+test.flags)
|
cmd.Env = append(os.Environ(), "ANALYSISFLAGS_CHILD=1", "FLAGS="+test.flags)
|
||||||
|
|
|
@ -46,8 +46,8 @@ func Help(progname string, analyzers []*analysis.Analyzer, args []string) {
|
||||||
fmt.Printf(" %-12s %s\n", a.Name, title)
|
fmt.Printf(" %-12s %s\n", a.Name, title)
|
||||||
}
|
}
|
||||||
fmt.Println("\nBy default all analyzers are run.")
|
fmt.Println("\nBy default all analyzers are run.")
|
||||||
fmt.Println("To select specific analyzers, use the -NAME.enable flag for each one,")
|
fmt.Println("To select specific analyzers, use the -NAME flag for each one,")
|
||||||
fmt.Println(" or -NAME.enable=false to run all analyzers not explicitly disabled.")
|
fmt.Println(" or -NAME=false to run all analyzers not explicitly disabled.")
|
||||||
|
|
||||||
// Show only the core command-line flags.
|
// Show only the core command-line flags.
|
||||||
fmt.Println("\nCore flags:")
|
fmt.Println("\nCore flags:")
|
||||||
|
|
Loading…
Reference in New Issue