Commit a18638c0 authored by Alan Donovan's avatar Alan Donovan

cmd/vendor: update to golang.org/x/tools@f62bfb54

Change-Id: I3b3035784ce89ba2ac5ab8f6448c45a3d38fa97d
Reviewed-on: https://go-review.googlesource.com/c/149778
Run-TryBot: Alan Donovan <adonovan@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 82c26009
...@@ -8,14 +8,8 @@ package main ...@@ -8,14 +8,8 @@ package main
import ( import (
"flag" "flag"
"fmt"
"log"
"os"
"strings"
"golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/unitchecker"
"golang.org/x/tools/go/analysis/internal/analysisflags"
"golang.org/x/tools/go/analysis/internal/unitchecker"
"golang.org/x/tools/go/analysis/passes/asmdecl" "golang.org/x/tools/go/analysis/passes/asmdecl"
"golang.org/x/tools/go/analysis/passes/assign" "golang.org/x/tools/go/analysis/passes/assign"
...@@ -41,84 +35,55 @@ import ( ...@@ -41,84 +35,55 @@ import (
"golang.org/x/tools/go/analysis/passes/unusedresult" "golang.org/x/tools/go/analysis/passes/unusedresult"
) )
var analyzers = []*analysis.Analyzer{ // Flags for legacy vet compatibility.
asmdecl.Analyzer, //
assign.Analyzer, // These flags, plus the shims in analysisflags, enable
atomic.Analyzer, // existing scripts that run vet to continue to work.
bools.Analyzer, //
buildtag.Analyzer, // Legacy vet had the concept of "experimental" checkers. There
cgocall.Analyzer, // was exactly one, shadow, and it had to be explicitly enabled
composite.Analyzer, // by the -shadow flag, which would of course disable all the
copylock.Analyzer, // other tristate flags, requiring the -all flag to reenable them.
httpresponse.Analyzer, // (By itself, -all did not enable all checkers.)
loopclosure.Analyzer, // The -all flag is no longer needed, so it is a no-op.
lostcancel.Analyzer, //
nilfunc.Analyzer, // The shadow analyzer has been removed from the suite,
pkgfact.Analyzer, // but can be run using these additional commands:
printf.Analyzer, // $ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
shift.Analyzer, // $ go vet -vettool=$(which shadow)
stdmethods.Analyzer, // Alternatively, one could build a multichecker containing all
structtag.Analyzer, // the desired checks (vet's suite + shadow) and run it in a
tests.Analyzer, // single "go vet" command.
unmarshal.Analyzer, func init() {
unreachable.Analyzer, _ = flag.Bool("source", false, "no effect (deprecated)")
unsafeptr.Analyzer, _ = flag.Bool("v", false, "no effect (deprecated)")
unusedresult.Analyzer, _ = flag.Bool("all", false, "no effect (deprecated)")
_ = flag.String("tags", "", "no effect (deprecated)")
} }
func main() { func main() {
log.SetFlags(0) unitchecker.Main(
log.SetPrefix("vet: ") asmdecl.Analyzer,
assign.Analyzer,
if err := analysis.Validate(analyzers); err != nil { atomic.Analyzer,
log.Fatal(err) bools.Analyzer,
} buildtag.Analyzer,
cgocall.Analyzer,
// Flags for legacy vet compatibility. composite.Analyzer,
// copylock.Analyzer,
// These flags, plus the shims in analysisflags, enable httpresponse.Analyzer,
// existing scripts that run vet to continue to work. loopclosure.Analyzer,
// lostcancel.Analyzer,
// Legacy vet had the concept of "experimental" checkers. There nilfunc.Analyzer,
// was exactly one, shadow, and it had to be explicitly enabled pkgfact.Analyzer,
// by the -shadow flag, which would of course disable all the printf.Analyzer,
// other tristate flags, requiring the -all flag to reenable them. shift.Analyzer,
// (By itself, -all did not enable all checkers.) stdmethods.Analyzer,
// The -all flag is no longer needed, so it is a no-op. structtag.Analyzer,
// tests.Analyzer,
// The shadow analyzer has been removed from the suite, unmarshal.Analyzer,
// but can be run using these additional commands: unreachable.Analyzer,
// $ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow unsafeptr.Analyzer,
// $ go vet -vettool=$(which shadow) unusedresult.Analyzer,
// Alternatively, one could build a multichecker containing all )
// the desired checks (vet's suite + shadow) and run it in a
// single "go vet" command.
for _, name := range []string{"source", "v", "all"} {
_ = flag.Bool(name, false, "no effect (deprecated)")
}
flag.Usage = func() {
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)
}
analyzers = analysisflags.Parse(analyzers, true)
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") {
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)
} }
...@@ -72,11 +72,13 @@ To add a new Analyzer to an existing driver, add another item to the list: ...@@ -72,11 +72,13 @@ To add a new Analyzer to an existing driver, add another item to the list:
A driver may use the name, flags, and documentation to provide on-line A driver may use the name, flags, and documentation to provide on-line
help that describes the analyses its performs. help that describes the analyses its performs.
The doc comment contains a brief one-line summary,
optionally followed by paragraphs of explanation.
The vet command, shown below, is an example of a driver that runs The vet command, shown below, is an example of a driver that runs
multiple analyzers. It is based on the multichecker package multiple analyzers. It is based on the multichecker package
(see the "Standalone commands" section for details). (see the "Standalone commands" section for details).
$ go build golang.org/x/tools/cmd/vet $ go build golang.org/x/tools/go/analysis/cmd/vet
$ ./vet help $ ./vet help
vet is a tool for static analysis of Go programs. vet is a tool for static analysis of Go programs.
...@@ -285,6 +287,16 @@ pointed to by fact. This scheme assumes that the concrete type of fact ...@@ -285,6 +287,16 @@ pointed to by fact. This scheme assumes that the concrete type of fact
is a pointer; this assumption is checked by the Validate function. is a pointer; this assumption is checked by the Validate function.
See the "printf" analyzer for an example of object facts in action. See the "printf" analyzer for an example of object facts in action.
Some driver implementations (such as those based on Bazel and Blaze) do
not currently apply analyzers to packages of the standard library.
Therefore, for best results, analyzer authors should not rely on
analysis facts being available for standard packages.
For example, although the printf checker is capable of deducing during
analysis of the log package that log.Printf is a printf-wrapper,
this fact is built in to the analyzer so that it correctly checks
calls to log.Printf even when run in a driver that does not apply
it to standard packages. We plan to remove this limitation in future.
Testing an Analyzer Testing an Analyzer
...@@ -298,14 +310,14 @@ diagnostics and facts (and no more). Expectations are expressed using ...@@ -298,14 +310,14 @@ diagnostics and facts (and no more). Expectations are expressed using
Standalone commands Standalone commands
Analyzers are provided in the form of packages that a driver program is Analyzers are provided in the form of packages that a driver program is
expected to import. The vet command imports a set of several analyses, expected to import. The vet command imports a set of several analyzers,
but users may wish to define their own analysis commands that perform but users may wish to define their own analysis commands that perform
additional checks. To simplify the task of creating an analysis command, additional checks. To simplify the task of creating an analysis command,
either for a single analyzer or for a whole suite, we provide the either for a single analyzer or for a whole suite, we provide the
singlechecker and multichecker subpackages. singlechecker and multichecker subpackages.
The singlechecker package provides the main function for a command that The singlechecker package provides the main function for a command that
runs one analysis. By convention, each analyzer such as runs one analyzer. By convention, each analyzer such as
go/passes/findcall should be accompanied by a singlechecker-based go/passes/findcall should be accompanied by a singlechecker-based
command such as go/analysis/passes/findcall/cmd/findcall, defined in its command such as go/analysis/passes/findcall/cmd/findcall, defined in its
entirety as: entirety as:
......
...@@ -3,39 +3,28 @@ package analysisflags ...@@ -3,39 +3,28 @@ package analysisflags
import ( import (
"flag" "flag"
"fmt" "fmt"
"io"
"log" "log"
"os"
"path/filepath"
"sort" "sort"
"strings" "strings"
"golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis"
) )
const usage = `PROGNAME is a tool for static analysis of Go programs. const help = `PROGNAME is a tool for static analysis of Go programs.
PROGNAME examines Go source code and reports suspicious constructs, such as Printf PROGNAME examines Go source code and reports suspicious constructs,
calls whose arguments do not align with the format string. It uses heuristics such as Printf calls whose arguments do not align with the format
that do not guarantee all reports are genuine problems, but it can find errors string. It uses heuristics that do not guarantee all reports are
not caught by the compilers. genuine problems, but it can find errors not caught by the compilers.
Usage: PROGNAME [-flag] [package]
` `
// PrintUsage prints the usage message to stderr.
func PrintUsage(out io.Writer) {
progname := filepath.Base(os.Args[0])
fmt.Fprintln(out, strings.Replace(usage, "PROGNAME", progname, -1))
}
// Help implements the help subcommand for a multichecker or vet-lite // Help implements the help subcommand for a multichecker or vet-lite
// style command. The optional args specify the analyzers to describe. // style command. The optional args specify the analyzers to describe.
// Help calls log.Fatal if no such analyzer exists. // Help calls log.Fatal if no such analyzer exists.
func Help(progname string, analyzers []*analysis.Analyzer, args []string) { func Help(progname string, analyzers []*analysis.Analyzer, args []string) {
// No args: show summary of all analyzers. // No args: show summary of all analyzers.
if len(args) == 0 { if len(args) == 0 {
PrintUsage(os.Stdout) fmt.Println(strings.Replace(help, "PROGNAME", progname, -1))
fmt.Println("Registered analyzers:") fmt.Println("Registered analyzers:")
fmt.Println() fmt.Println()
sort.Slice(analyzers, func(i, j int) bool { sort.Slice(analyzers, func(i, j int) bool {
......
...@@ -32,7 +32,7 @@ func init() { ...@@ -32,7 +32,7 @@ func init() {
var Analyzer = &analysis.Analyzer{ var Analyzer = &analysis.Analyzer{
Name: "printf", Name: "printf",
Doc: "check printf-like invocations", Doc: doc,
Requires: []*analysis.Analyzer{inspect.Analyzer}, Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: run, Run: run,
FactTypes: []analysis.Fact{new(isWrapper)}, FactTypes: []analysis.Fact{new(isWrapper)},
...@@ -43,12 +43,12 @@ const doc = `check consistency of Printf format strings and arguments ...@@ -43,12 +43,12 @@ const doc = `check consistency of Printf format strings and arguments
The check applies to known functions (for example, those in package fmt) The check applies to known functions (for example, those in package fmt)
as well as any detected wrappers of known functions. as well as any detected wrappers of known functions.
A function that wants to avail itself of printf checking but does not A function that wants to avail itself of printf checking but is not
get found by this analyzer's heuristics (for example, due to use of found by this analyzer's heuristics (for example, due to use of
dynamic calls) can insert a bogus call: dynamic calls) can insert a bogus call:
if false { if false {
fmt.Sprintf(format, args...) // enable printf checking _ = fmt.Sprintf(format, args...) // enable printf checking
} }
The -funcs flag specifies a comma-separated list of names of additional The -funcs flag specifies a comma-separated list of names of additional
...@@ -843,7 +843,22 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) bool { ...@@ -843,7 +843,22 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) bool {
} }
// Is the expression e within the body of that String method? // Is the expression e within the body of that String method?
return stringMethod.Pkg() == pass.Pkg && stringMethod.Scope().Contains(e.Pos()) if stringMethod.Pkg() != pass.Pkg || !stringMethod.Scope().Contains(e.Pos()) {
return false
}
// Is it the receiver r, or &r?
recv := stringMethod.Type().(*types.Signature).Recv()
if recv == nil {
return false
}
if u, ok := e.(*ast.UnaryExpr); ok && u.Op == token.AND {
e = u.X // strip off & from &r
}
if id, ok := e.(*ast.Ident); ok {
return pass.TypesInfo.Uses[id] == recv
}
return false
} }
// isFunctionValue reports whether the expression is a function as opposed to a function call. // isFunctionValue reports whether the expression is a function as opposed to a function call.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment