aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/golang.org
diff options
context:
space:
mode:
authorJohn Olheiser <john.olheiser@gmail.com>2020-04-05 01:20:50 -0500
committerGitHub <noreply@github.com>2020-04-05 07:20:50 +0100
commitbaadb51445b1d990f72a37b0ef7575f5ed72824a (patch)
tree192fa25f2dc144bfa5c78adafc9ccd8f92db86bb /vendor/golang.org
parentb74d30ae275b4f025f689efca748dd0cbd826b22 (diff)
downloadgitea-baadb51445b1d990f72a37b0ef7575f5ed72824a.tar.gz
gitea-baadb51445b1d990f72a37b0ef7575f5ed72824a.zip
Add gitea-vet (#10948)
* Add copyright Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add gitea-vet and fix non-compliance Signed-off-by: jolheiser <john.olheiser@gmail.com> * Combine tools.go into build.go and clean up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove extra GO111MODULE=on Signed-off-by: jolheiser <john.olheiser@gmail.com>
Diffstat (limited to 'vendor/golang.org')
-rw-r--r--vendor/golang.org/x/mod/module/module.go6
-rw-r--r--vendor/golang.org/x/tools/go/analysis/analysis.go221
-rw-r--r--vendor/golang.org/x/tools/go/analysis/diagnostic.go61
-rw-r--r--vendor/golang.org/x/tools/go/analysis/doc.go301
-rw-r--r--vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go388
-rw-r--r--vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go92
-rw-r--r--vendor/golang.org/x/tools/go/analysis/internal/facts/facts.go323
-rw-r--r--vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go88
-rw-r--r--vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go396
-rw-r--r--vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go9
-rw-r--r--vendor/golang.org/x/tools/go/analysis/validate.go97
-rw-r--r--vendor/golang.org/x/tools/go/types/objectpath/objectpath.go523
-rw-r--r--vendor/golang.org/x/tools/imports/forward.go5
-rw-r--r--vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go5
-rw-r--r--vendor/golang.org/x/tools/internal/gocommand/invoke.go37
-rw-r--r--vendor/golang.org/x/tools/internal/gopathwalk/walk.go32
-rw-r--r--vendor/golang.org/x/tools/internal/imports/fix.go19
-rw-r--r--vendor/golang.org/x/tools/internal/imports/imports.go7
-rw-r--r--vendor/golang.org/x/tools/internal/imports/mod.go6
-rw-r--r--vendor/golang.org/x/xerrors/fmt.go138
20 files changed, 2669 insertions, 85 deletions
diff --git a/vendor/golang.org/x/mod/module/module.go b/vendor/golang.org/x/mod/module/module.go
index 21f123957d..6cd37280a8 100644
--- a/vendor/golang.org/x/mod/module/module.go
+++ b/vendor/golang.org/x/mod/module/module.go
@@ -123,8 +123,12 @@ type Version struct {
Version string `json:",omitempty"`
}
-// String returns the module version syntax Path@Version.
+// String returns a representation of the Version suitable for logging
+// (Path@Version, or just Path if Version is empty).
func (m Version) String() string {
+ if m.Version == "" {
+ return m.Path
+ }
return m.Path + "@" + m.Version
}
diff --git a/vendor/golang.org/x/tools/go/analysis/analysis.go b/vendor/golang.org/x/tools/go/analysis/analysis.go
new file mode 100644
index 0000000000..ea605f4fd4
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/analysis.go
@@ -0,0 +1,221 @@
+package analysis
+
+import (
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+ "reflect"
+)
+
+// An Analyzer describes an analysis function and its options.
+type Analyzer struct {
+ // The Name of the analyzer must be a valid Go identifier
+ // as it may appear in command-line flags, URLs, and so on.
+ Name string
+
+ // Doc is the documentation for the analyzer.
+ // The part before the first "\n\n" is the title
+ // (no capital or period, max ~60 letters).
+ Doc string
+
+ // Flags defines any flags accepted by the analyzer.
+ // The manner in which these flags are exposed to the user
+ // depends on the driver which runs the analyzer.
+ Flags flag.FlagSet
+
+ // Run applies the analyzer to a package.
+ // It returns an error if the analyzer failed.
+ //
+ // On success, the Run function may return a result
+ // computed by the Analyzer; its type must match ResultType.
+ // The driver makes this result available as an input to
+ // another Analyzer that depends directly on this one (see
+ // Requires) when it analyzes the same package.
+ //
+ // To pass analysis results between packages (and thus
+ // potentially between address spaces), use Facts, which are
+ // serializable.
+ Run func(*Pass) (interface{}, error)
+
+ // RunDespiteErrors allows the driver to invoke
+ // the Run method of this analyzer even on a
+ // package that contains parse or type errors.
+ RunDespiteErrors bool
+
+ // Requires is a set of analyzers that must run successfully
+ // before this one on a given package. This analyzer may inspect
+ // the outputs produced by each analyzer in Requires.
+ // The graph over analyzers implied by Requires edges must be acyclic.
+ //
+ // Requires establishes a "horizontal" dependency between
+ // analysis passes (different analyzers, same package).
+ Requires []*Analyzer
+
+ // ResultType is the type of the optional result of the Run function.
+ ResultType reflect.Type
+
+ // FactTypes indicates that this analyzer imports and exports
+ // Facts of the specified concrete types.
+ // An analyzer that uses facts may assume that its import
+ // dependencies have been similarly analyzed before it runs.
+ // Facts must be pointers.
+ //
+ // FactTypes establishes a "vertical" dependency between
+ // analysis passes (same analyzer, different packages).
+ FactTypes []Fact
+}
+
+func (a *Analyzer) String() string { return a.Name }
+
+// A Pass provides information to the Run function that
+// applies a specific analyzer to a single Go package.
+//
+// It forms the interface between the analysis logic and the driver
+// program, and has both input and an output components.
+//
+// As in a compiler, one pass may depend on the result computed by another.
+//
+// The Run function should not call any of the Pass functions concurrently.
+type Pass struct {
+ Analyzer *Analyzer // the identity of the current analyzer
+
+ // syntax and type information
+ Fset *token.FileSet // file position information
+ Files []*ast.File // the abstract syntax tree of each file
+ OtherFiles []string // names of non-Go files of this package
+ Pkg *types.Package // type information about the package
+ TypesInfo *types.Info // type information about the syntax trees
+ TypesSizes types.Sizes // function for computing sizes of types
+
+ // Report reports a Diagnostic, a finding about a specific location
+ // in the analyzed source code such as a potential mistake.
+ // It may be called by the Run function.
+ Report func(Diagnostic)
+
+ // ResultOf provides the inputs to this analysis pass, which are
+ // the corresponding results of its prerequisite analyzers.
+ // The map keys are the elements of Analysis.Required,
+ // and the type of each corresponding value is the required
+ // analysis's ResultType.
+ ResultOf map[*Analyzer]interface{}
+
+ // -- facts --
+
+ // ImportObjectFact retrieves a fact associated with obj.
+ // Given a value ptr of type *T, where *T satisfies Fact,
+ // ImportObjectFact copies the value to *ptr.
+ //
+ // ImportObjectFact panics if called after the pass is complete.
+ // ImportObjectFact is not concurrency-safe.
+ ImportObjectFact func(obj types.Object, fact Fact) bool
+
+ // ImportPackageFact retrieves a fact associated with package pkg,
+ // which must be this package or one of its dependencies.
+ // See comments for ImportObjectFact.
+ ImportPackageFact func(pkg *types.Package, fact Fact) bool
+
+ // ExportObjectFact associates a fact of type *T with the obj,
+ // replacing any previous fact of that type.
+ //
+ // ExportObjectFact panics if it is called after the pass is
+ // complete, or if obj does not belong to the package being analyzed.
+ // ExportObjectFact is not concurrency-safe.
+ ExportObjectFact func(obj types.Object, fact Fact)
+
+ // ExportPackageFact associates a fact with the current package.
+ // See comments for ExportObjectFact.
+ ExportPackageFact func(fact Fact)
+
+ // AllPackageFacts returns a new slice containing all package facts of the analysis's FactTypes
+ // in unspecified order.
+ // WARNING: This is an experimental API and may change in the future.
+ AllPackageFacts func() []PackageFact
+
+ // AllObjectFacts returns a new slice containing all object facts of the analysis's FactTypes
+ // in unspecified order.
+ // WARNING: This is an experimental API and may change in the future.
+ AllObjectFacts func() []ObjectFact
+
+ /* Further fields may be added in future. */
+ // For example, suggested or applied refactorings.
+}
+
+// PackageFact is a package together with an associated fact.
+// WARNING: This is an experimental API and may change in the future.
+type PackageFact struct {
+ Package *types.Package
+ Fact Fact
+}
+
+// ObjectFact is an object together with an associated fact.
+// WARNING: This is an experimental API and may change in the future.
+type ObjectFact struct {
+ Object types.Object
+ Fact Fact
+}
+
+// Reportf is a helper function that reports a Diagnostic using the
+// specified position and formatted error message.
+func (pass *Pass) Reportf(pos token.Pos, format string, args ...interface{}) {
+ msg := fmt.Sprintf(format, args...)
+ pass.Report(Diagnostic{Pos: pos, Message: msg})
+}
+
+// The Range interface provides a range. It's equivalent to and satisfied by
+// ast.Node.
+type Range interface {
+ Pos() token.Pos // position of first character belonging to the node
+ End() token.Pos // position of first character immediately after the node
+}
+
+// ReportRangef is a helper function that reports a Diagnostic using the
+// range provided. ast.Node values can be passed in as the range because
+// they satisfy the Range interface.
+func (pass *Pass) ReportRangef(rng Range, format string, args ...interface{}) {
+ msg := fmt.Sprintf(format, args...)
+ pass.Report(Diagnostic{Pos: rng.Pos(), End: rng.End(), Message: msg})
+}
+
+func (pass *Pass) String() string {
+ return fmt.Sprintf("%s@%s", pass.Analyzer.Name, pass.Pkg.Path())
+}
+
+// A Fact is an intermediate fact produced during analysis.
+//
+// Each fact is associated with a named declaration (a types.Object) or
+// with a package as a whole. A single object or package may have
+// multiple associated facts, but only one of any particular fact type.
+//
+// A Fact represents a predicate such as "never returns", but does not
+// represent the subject of the predicate such as "function F" or "package P".
+//
+// Facts may be produced in one analysis pass and consumed by another
+// analysis pass even if these are in different address spaces.
+// If package P imports Q, all facts about Q produced during
+// analysis of that package will be available during later analysis of P.
+// Facts are analogous to type export data in a build system:
+// just as export data enables separate compilation of several passes,
+// facts enable "separate analysis".
+//
+// Each pass (a, p) starts with the set of facts produced by the
+// same analyzer a applied to the packages directly imported by p.
+// The analysis may add facts to the set, and they may be exported in turn.
+// An analysis's Run function may retrieve facts by calling
+// Pass.Import{Object,Package}Fact and update them using
+// Pass.Export{Object,Package}Fact.
+//
+// A fact is logically private to its Analysis. To pass values
+// between different analyzers, use the results mechanism;
+// see Analyzer.Requires, Analyzer.ResultType, and Pass.ResultOf.
+//
+// A Fact type must be a pointer.
+// Facts are encoded and decoded using encoding/gob.
+// A Fact may implement the GobEncoder/GobDecoder interfaces
+// to customize its encoding. Fact encoding should not fail.
+//
+// A Fact should not be modified once exported.
+type Fact interface {
+ AFact() // dummy method to avoid type errors
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/diagnostic.go b/vendor/golang.org/x/tools/go/analysis/diagnostic.go
new file mode 100644
index 0000000000..57eaf6faa2
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/diagnostic.go
@@ -0,0 +1,61 @@
+package analysis
+
+import "go/token"
+
+// A Diagnostic is a message associated with a source location or range.
+//
+// An Analyzer may return a variety of diagnostics; the optional Category,
+// which should be a constant, may be used to classify them.
+// It is primarily intended to make it easy to look up documentation.
+//
+// If End is provided, the diagnostic is specified to apply to the range between
+// Pos and End.
+type Diagnostic struct {
+ Pos token.Pos
+ End token.Pos // optional
+ Category string // optional
+ Message string
+
+ // SuggestedFixes contains suggested fixes for a diagnostic which can be used to perform
+ // edits to a file that address the diagnostic.
+ // TODO(matloob): Should multiple SuggestedFixes be allowed for a diagnostic?
+ // Diagnostics should not contain SuggestedFixes that overlap.
+ // Experimental: This API is experimental and may change in the future.
+ SuggestedFixes []SuggestedFix // optional
+
+ // Experimental: This API is experimental and may change in the future.
+ Related []RelatedInformation // optional
+}
+
+// RelatedInformation contains information related to a diagnostic.
+// For example, a diagnostic that flags duplicated declarations of a
+// variable may include one RelatedInformation per existing
+// declaration.
+type RelatedInformation struct {
+ Pos token.Pos
+ End token.Pos
+ Message string
+}
+
+// A SuggestedFix is a code change associated with a Diagnostic that a user can choose
+// to apply to their code. Usually the SuggestedFix is meant to fix the issue flagged
+// by the diagnostic.
+// TextEdits for a SuggestedFix should not overlap. TextEdits for a SuggestedFix
+// should not contain edits for other packages.
+// Experimental: This API is experimental and may change in the future.
+type SuggestedFix struct {
+ // A description for this suggested fix to be shown to a user deciding
+ // whether to accept it.
+ Message string
+ TextEdits []TextEdit
+}
+
+// A TextEdit represents the replacement of the code between Pos and End with the new text.
+// Each TextEdit should apply to a single file. End should not be earlier in the file than Pos.
+// Experimental: This API is experimental and may change in the future.
+type TextEdit struct {
+ // For a pure insertion, End can either be set to Pos or token.NoPos.
+ Pos token.Pos
+ End token.Pos
+ NewText []byte
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/doc.go b/vendor/golang.org/x/tools/go/analysis/doc.go
new file mode 100644
index 0000000000..ea56b724e8
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/doc.go
@@ -0,0 +1,301 @@
+/*
+
+Package analysis defines the interface between a modular static
+analysis and an analysis driver program.
+
+
+Background
+
+A static analysis is a function that inspects a package of Go code and
+reports a set of diagnostics (typically mistakes in the code), and
+perhaps produces other results as well, such as suggested refactorings
+or other facts. An analysis that reports mistakes is informally called a
+"checker". For example, the printf checker reports mistakes in
+fmt.Printf format strings.
+
+A "modular" analysis is one that inspects one package at a time but can
+save information from a lower-level package and use it when inspecting a
+higher-level package, analogous to separate compilation in a toolchain.
+The printf checker is modular: when it discovers that a function such as
+log.Fatalf delegates to fmt.Printf, it records this fact, and checks
+calls to that function too, including calls made from another package.
+
+By implementing a common interface, checkers from a variety of sources
+can be easily selected, incorporated, and reused in a wide range of
+driver programs including command-line tools (such as vet), text editors and
+IDEs, build and test systems (such as go build, Bazel, or Buck), test
+frameworks, code review tools, code-base indexers (such as SourceGraph),
+documentation viewers (such as godoc), batch pipelines for large code
+bases, and so on.
+
+
+Analyzer
+
+The primary type in the API is Analyzer. An Analyzer statically
+describes an analysis function: its name, documentation, flags,
+relationship to other analyzers, and of course, its logic.
+
+To define an analysis, a user declares a (logically constant) variable
+of type Analyzer. Here is a typical example from one of the analyzers in
+the go/analysis/passes/ subdirectory:
+
+ package unusedresult
+
+ var Analyzer = &analysis.Analyzer{
+ Name: "unusedresult",
+ Doc: "check for unused results of calls to some functions",
+ Run: run,
+ ...
+ }
+
+ func run(pass *analysis.Pass) (interface{}, error) {
+ ...
+ }
+
+An analysis driver is a program such as vet that runs a set of
+analyses and prints the diagnostics that they report.
+The driver program must import the list of Analyzers it needs.
+Typically each Analyzer resides in a separate package.
+To add a new Analyzer to an existing driver, add another item to the list:
+
+ import ( "unusedresult"; "nilness"; "printf" )
+
+ var analyses = []*analysis.Analyzer{
+ unusedresult.Analyzer,
+ nilness.Analyzer,
+ printf.Analyzer,
+ }
+
+A driver may use the name, flags, and documentation to provide on-line
+help that describes the analyses it performs.
+The doc comment contains a brief one-line summary,
+optionally followed by paragraphs of explanation.
+
+The Analyzer type has more fields besides those shown above:
+
+ type Analyzer struct {
+ Name string
+ Doc string
+ Flags flag.FlagSet
+ Run func(*Pass) (interface{}, error)
+ RunDespiteErrors bool
+ ResultType reflect.Type
+ Requires []*Analyzer
+ FactTypes []Fact
+ }
+
+The Flags field declares a set of named (global) flag variables that
+control analysis behavior. Unlike vet, analysis flags are not declared
+directly in the command line FlagSet; it is up to the driver to set the
+flag variables. A driver for a single analysis, a, might expose its flag
+f directly on the command line as -f, whereas a driver for multiple
+analyses might prefix the flag name by the analysis name (-a.f) to avoid
+ambiguity. An IDE might expose the flags through a graphical interface,
+and a batch pipeline might configure them from a config file.
+See the "findcall" analyzer for an example of flags in action.
+
+The RunDespiteErrors flag indicates whether the analysis is equipped to
+handle ill-typed code. If not, the driver will skip the analysis if
+there were parse or type errors.
+The optional ResultType field specifies the type of the result value
+computed by this analysis and made available to other analyses.
+The Requires field specifies a list of analyses upon which
+this one depends and whose results it may access, and it constrains the
+order in which a driver may run analyses.
+The FactTypes field is discussed in the section on Modularity.
+The analysis package provides a Validate function to perform basic
+sanity checks on an Analyzer, such as that its Requires graph is
+acyclic, its fact and result types are unique, and so on.
+
+Finally, the Run field contains a function to be called by the driver to
+execute the analysis on a single package. The driver passes it an
+instance of the Pass type.
+
+
+Pass
+
+A Pass describes a single unit of work: the application of a particular
+Analyzer to a particular package of Go code.
+The Pass provides information to the Analyzer's Run function about the
+package being analyzed, and provides operations to the Run function for
+reporting diagnostics and other information back to the driver.
+
+ type Pass struct {
+ Fset *token.FileSet
+ Files []*ast.File
+ OtherFiles []string
+ Pkg *types.Package
+ TypesInfo *types.Info
+ ResultOf map[*Analyzer]interface{}
+ Report func(Diagnostic)
+ ...
+ }
+
+The Fset, Files, Pkg, and TypesInfo fields provide the syntax trees,
+type information, and source positions for a single package of Go code.
+
+The OtherFiles field provides the names, but not the contents, of non-Go
+files such as assembly that are part of this package. See the "asmdecl"
+or "buildtags" analyzers for examples of loading non-Go files and reporting
+diagnostics against them.
+
+The ResultOf field provides the results computed by the analyzers
+required by this one, as expressed in its Analyzer.Requires field. The
+driver runs the required analyzers first and makes their results
+available in this map. Each Analyzer must return a value of the type
+described in its Analyzer.ResultType field.
+For example, the "ctrlflow" analyzer returns a *ctrlflow.CFGs, which
+provides a control-flow graph for each function in the package (see
+golang.org/x/tools/go/cfg); the "inspect" analyzer returns a value that
+enables other Analyzers to traverse the syntax trees of the package more
+efficiently; and the "buildssa" analyzer constructs an SSA-form
+intermediate representation.
+Each of these Analyzers extends the capabilities of later Analyzers
+without adding a dependency to the core API, so an analysis tool pays
+only for the extensions it needs.
+
+The Report function emits a diagnostic, a message associated with a
+source position. For most analyses, diagnostics are their primary
+result.
+For convenience, Pass provides a helper method, Reportf, to report a new
+diagnostic by formatting a string.
+Diagnostic is defined as:
+
+ type Diagnostic struct {
+ Pos token.Pos
+ Category string // optional
+ Message string
+ }
+
+The optional Category field is a short identifier that classifies the
+kind of message when an analysis produces several kinds of diagnostic.
+
+Most Analyzers inspect typed Go syntax trees, but a few, such as asmdecl
+and buildtag, inspect the raw text of Go source files or even non-Go
+files such as assembly. To report a diagnostic against a line of a
+raw text file, use the following sequence:
+
+ content, err := ioutil.ReadFile(filename)
+ if err != nil { ... }
+ tf := fset.AddFile(filename, -1, len(content))
+ tf.SetLinesForContent(content)
+ ...
+ pass.Reportf(tf.LineStart(line), "oops")
+
+
+Modular analysis with Facts
+
+To improve efficiency and scalability, large programs are routinely
+built using separate compilation: units of the program are compiled
+separately, and recompiled only when one of their dependencies changes;
+independent modules may be compiled in parallel. The same technique may
+be applied to static analyses, for the same benefits. Such analyses are
+described as "modular".
+
+A compiler’s type checker is an example of a modular static analysis.
+Many other checkers we would like to apply to Go programs can be
+understood as alternative or non-standard type systems. For example,
+vet's printf checker infers whether a function has the "printf wrapper"
+type, and it applies stricter checks to calls of such functions. In
+addition, it records which functions are printf wrappers for use by
+later analysis passes to identify other printf wrappers by induction.
+A result such as “f is a printf wrapper” that is not interesting by
+itself but serves as a stepping stone to an interesting result (such as
+a diagnostic) is called a "fact".
+
+The analysis API allows an analysis to define new types of facts, to
+associate facts of these types with objects (named entities) declared
+within the current package, or with the package as a whole, and to query
+for an existing fact of a given type associated with an object or
+package.
+
+An Analyzer that uses facts must declare their types:
+
+ var Analyzer = &analysis.Analyzer{
+ Name: "printf",
+ FactTypes: []analysis.Fact{new(isWrapper)},
+ ...
+ }
+
+ type isWrapper struct{} // => *types.Func f “is a printf wrapper”
+
+The driver program ensures that facts for a pass’s dependencies are
+generated before analyzing the package and is responsible for propagating
+facts from one package to another, possibly across address spaces.
+Consequently, Facts must be serializable. The API requires that drivers
+use the gob encoding, an efficient, robust, self-describing binary
+protocol. A fact type may implement the GobEncoder/GobDecoder interfaces
+if the default encoding is unsuitable. Facts should be stateless.
+
+The Pass type has functions to import and export facts,
+associated either with an object or with a package:
+
+ type Pass struct {
+ ...
+ ExportObjectFact func(types.Object, Fact)
+ ImportObjectFact func(types.Object, Fact) bool
+
+ ExportPackageFact func(fact Fact)
+ ImportPackageFact func(*types.Package, Fact) bool
+ }
+
+An Analyzer may only export facts associated with the current package or
+its objects, though it may import facts from any package or object that
+is an import dependency of the current package.
+
+Conceptually, ExportObjectFact(obj, fact) inserts fact into a hidden map keyed by
+the pair (obj, TypeOf(fact)), and the ImportObjectFact function
+retrieves the entry from this map and copies its value into the variable
+pointed to by fact. This scheme assumes that the concrete type of fact
+is a pointer; this assumption is checked by the Validate function.
+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 would like to remove this limitation in future.
+
+
+Testing an Analyzer
+
+The analysistest subpackage provides utilities for testing an Analyzer.
+In a few lines of code, it is possible to run an analyzer on a package
+of testdata files and check that it reported all the expected
+diagnostics and facts (and no more). Expectations are expressed using
+"// want ..." comments in the input code.
+
+
+Standalone commands
+
+Analyzers are provided in the form of packages that a driver program is
+expected to import. The vet command imports a set of several analyzers,
+but users may wish to define their own analysis commands that perform
+additional checks. To simplify the task of creating an analysis command,
+either for a single analyzer or for a whole suite, we provide the
+singlechecker and multichecker subpackages.
+
+The singlechecker package provides the main function for a command that
+runs one analyzer. By convention, each analyzer such as
+go/passes/findcall should be accompanied by a singlechecker-based
+command such as go/analysis/passes/findcall/cmd/findcall, defined in its
+entirety as:
+
+ package main
+
+ import (
+ "golang.org/x/tools/go/analysis/passes/findcall"
+ "golang.org/x/tools/go/analysis/singlechecker"
+ )
+
+ func main() { singlechecker.Main(findcall.Analyzer) }
+
+A tool that provides multiple analyzers can use multichecker in a
+similar way, giving it the list of Analyzers.
+
+*/
+package analysis
diff --git a/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go b/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
new file mode 100644
index 0000000000..0778f42207
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
@@ -0,0 +1,388 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package analysisflags defines helpers for processing flags of
+// analysis driver tools.
+package analysisflags
+
+import (
+ "crypto/sha256"
+ "encoding/gob"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "go/token"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "strconv"
+ "strings"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+// flags common to all {single,multi,unit}checkers.
+var (
+ JSON = false // -json
+ Context = -1 // -c=N: if N>0, display offending line plus N lines of context
+)
+
+// Parse creates a flag for each of the analyzer's flags,
+// including (in multi mode) a flag named after the analyzer,
+// parses the flags, then filters and returns the list of
+// analyzers enabled by flags.
+//
+// The result is intended to be passed to unitchecker.Run or checker.Run.
+// Use in unitchecker.Run will gob.Register all fact types for the returned
+// graph of analyzers but of course not the ones only reachable from
+// dropped analyzers. To avoid inconsistency about which gob types are
+// registered from run to run, Parse itself gob.Registers all the facts
+// only reachable from dropped analyzers.
+// This is not a particularly elegant API, but this is an internal package.
+func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
+ // Connect each analysis flag to the command line as -analysis.flag.
+ enabled := make(map[*analysis.Analyzer]*triState)
+ for _, a := range analyzers {
+ var prefix string
+
+ // Add -NAME flag to enable it.
+ if multi {
+ prefix = a.Name + "."
+
+ enable := new(triState)
+ enableUsage := "enable " + a.Name + " analysis"
+ flag.Var(enable, a.Name, enableUsage)
+ enabled[a] = enable
+ }
+
+ a.Flags.VisitAll(func(f *flag.Flag) {
+ if !multi && flag.Lookup(f.Name) != nil {
+ log.Printf("%s flag -%s would conflict with driver; skipping", a.Name, f.Name)
+ return
+ }
+
+ name := prefix + f.Name
+ flag.Var(f.Value, name, f.Usage)
+ })
+ }
+
+ // standard flags: -flags, -V.
+ printflags := flag.Bool("flags", false, "print analyzer flags in JSON")
+ addVersionFlag()
+
+ // flags common to all checkers
+ flag.BoolVar(&JSON, "json", JSON, "emit JSON output")
+ flag.IntVar(&Context, "c", Context, `display offending line with this many lines of context`)
+
+ // Add shims for legacy vet flags to enable existing
+ // scripts that run vet to continue to work.
+ _ = flag.Bool("source", false, "no effect (deprecated)")
+ _ = flag.Bool("v", false, "no effect (deprecated)")
+ _ = flag.Bool("all", false, "no effect (deprecated)")
+ _ = flag.String("tags", "", "no effect (deprecated)")
+ for old, new := range vetLegacyFlags {
+ newFlag := flag.Lookup(new)
+ if newFlag != nil && flag.Lookup(old) == nil {
+ flag.Var(newFlag.Value, old, "deprecated alias for -"+new)
+ }
+ }
+
+ flag.Parse() // (ExitOnError)
+
+ // -flags: print flags so that go vet knows which ones are legitimate.
+ if *printflags {
+ printFlags()
+ os.Exit(0)
+ }
+
+ everything := expand(analyzers)
+
+ // If any -NAME flag is true, run only those analyzers. Otherwise,
+ // if any -NAME flag is false, run all but those analyzers.
+ if multi {
+ var hasTrue, hasFalse bool
+ for _, ts := range enabled {
+ switch *ts {
+ case setTrue:
+ hasTrue = true
+ case setFalse:
+ hasFalse = true
+ }
+ }
+
+ var keep []*analysis.Analyzer
+ if hasTrue {
+ for _, a := range analyzers {
+ if *enabled[a] == setTrue {
+ keep = append(keep, a)
+ }
+ }
+ analyzers = keep
+ } else if hasFalse {
+ for _, a := range analyzers {
+ if *enabled[a] != setFalse {
+ keep = append(keep, a)
+ }
+ }
+ analyzers = keep
+ }
+ }
+
+ // Register fact types of skipped analyzers
+ // in case we encounter them in imported files.
+ kept := expand(analyzers)
+ for a := range everything {
+ if !kept[a] {
+ for _, f := range a.FactTypes {
+ gob.Register(f)
+ }
+ }
+ }
+
+ return analyzers
+}
+
+func expand(analyzers []*analysis.Analyzer) map[*analysis.Analyzer]bool {
+ seen := make(map[*analysis.Analyzer]bool)
+ var visitAll func([]*analysis.Analyzer)
+ visitAll = func(analyzers []*analysis.Analyzer) {
+ for _, a := range analyzers {
+ if !seen[a] {
+ seen[a] = true
+ visitAll(a.Requires)
+ }
+ }
+ }
+ visitAll(analyzers)
+ return seen
+}
+
+func printFlags() {
+ type jsonFlag struct {
+ Name string
+ Bool bool
+ Usage string
+ }
+ var flags []jsonFlag = nil
+ flag.VisitAll(func(f *flag.Flag) {
+ // Don't report {single,multi}checker debugging
+ // flags or fix as these have no effect on unitchecker
+ // (as invoked by 'go vet').
+ switch f.Name {
+ case "debug", "cpuprofile", "memprofile", "trace", "fix":
+ return
+ }
+
+ b, ok := f.Value.(interface{ IsBoolFlag() bool })
+ isBool := ok && b.IsBoolFlag()
+ flags = append(flags, jsonFlag{f.Name, isBool, f.Usage})
+ })
+ data, err := json.MarshalIndent(flags, "", "\t")
+ if err != nil {
+ log.Fatal(err)
+ }
+ os.Stdout.Write(data)
+}
+
+// addVersionFlag registers a -V flag that, if set,
+// prints the executable version and exits 0.
+//
+// If the -V flag already exists — for example, because it was already
+// registered by a call to cmd/internal/objabi.AddVersionFlag — then
+// addVersionFlag does nothing.
+func addVersionFlag() {
+ if flag.Lookup("V") == nil {
+ flag.Var(versionFlag{}, "V", "print version and exit")
+ }
+}
+
+// versionFlag minimally complies with the -V protocol required by "go vet".
+type versionFlag struct{}
+
+func (versionFlag) IsBoolFlag() bool { return true }
+func (versionFlag) Get() interface{} { return nil }
+func (versionFlag) String() string { return "" }
+func (versionFlag) Set(s string) error {
+ if s != "full" {
+ log.Fatalf("unsupported flag value: -V=%s", s)
+ }
+
+ // This replicates the minimal subset of
+ // cmd/internal/objabi.AddVersionFlag, which is private to the
+ // go tool yet forms part of our command-line interface.
+ // TODO(adonovan): clarify the contract.
+
+ // Print the tool version so the build system can track changes.
+ // Formats:
+ // $progname version devel ... buildID=...
+ // $progname version go1.9.1
+ progname := os.Args[0]
+ f, err := os.Open(progname)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := sha256.New()
+ if _, err := io.Copy(h, f); err != nil {
+ log.Fatal(err)
+ }
+ f.Close()
+ fmt.Printf("%s version devel comments-go-here buildID=%02x\n",
+ progname, string(h.Sum(nil)))
+ os.Exit(0)
+ return nil
+}
+
+// A triState is a boolean that knows whether
+// it has been set to either true or false.
+// It is used to identify whether a flag appears;
+// the standard boolean flag cannot
+// distinguish missing from unset.
+// It also satisfies flag.Value.
+type triState int
+
+const (
+ unset triState = iota
+ setTrue
+ setFalse
+)
+
+func triStateFlag(name string, value triState, usage string) *triState {
+ flag.Var(&value, name, usage)
+ return &value
+}
+
+// triState implements flag.Value, flag.Getter, and flag.boolFlag.
+// They work like boolean flags: we can say vet -printf as well as vet -printf=true
+func (ts *triState) Get() interface{} {
+ return *ts == setTrue
+}
+
+func (ts triState) isTrue() bool {
+ return ts == setTrue
+}
+
+func (ts *triState) Set(value string) error {
+ b, err := strconv.ParseBool(value)
+ if err != nil {
+ // This error message looks poor but package "flag" adds
+ // "invalid boolean value %q for -NAME: %s"
+ return fmt.Errorf("want true or false")
+ }
+ if b {
+ *ts = setTrue
+ } else {
+ *ts = setFalse
+ }
+ return nil
+}
+
+func (ts *triState) String() string {
+ switch *ts {
+ case unset:
+ return "true"
+ case setTrue:
+ return "true"
+ case setFalse:
+ return "false"
+ }
+ panic("not reached")
+}
+
+func (ts triState) IsBoolFlag() bool {
+ return true
+}
+
+// Legacy flag support
+
+// vetLegacyFlags maps flags used by legacy vet to their corresponding
+// new names. The old names will continue to work.
+var vetLegacyFlags = map[string]string{
+ // Analyzer name changes
+ "bool": "bools",
+ "buildtags": "buildtag",
+ "methods": "stdmethods",
+ "rangeloops": "loopclosure",
+
+ // Analyzer flags
+ "compositewhitelist": "composites.whitelist",
+ "printfuncs": "printf.funcs",
+ "shadowstrict": "shadow.strict",
+ "unusedfuncs": "unusedresult.funcs",
+ "unusedstringmethods": "unusedresult.stringmethods",
+}
+
+// ---- output helpers common to all drivers ----
+
+// PrintPlain prints a diagnostic in plain text form,
+// with context specified by the -c flag.
+func PrintPlain(fset *token.FileSet, diag analysis.Diagnostic) {
+ posn := fset.Position(diag.Pos)
+ fmt.Fprintf(os.Stderr, "%s: %s\n", posn, diag.Message)
+
+ // -c=N: show offending line plus N lines of context.
+ if Context >= 0 {
+ posn := fset.Position(diag.Pos)
+ end := fset.Position(diag.End)
+ if !end.IsValid() {
+ end = posn
+ }
+ data, _ := ioutil.ReadFile(posn.Filename)
+ lines := strings.Split(string(data), "\n")
+ for i := posn.Line - Context; i <= end.Line+Context; i++ {
+ if 1 <= i && i <= len(lines) {
+ fmt.Fprintf(os.Stderr, "%d\t%s\n", i, lines[i-1])
+ }
+ }
+ }
+}
+
+// A JSONTree is a mapping from package ID to analysis name to result.
+// Each result is either a jsonError or a list of jsonDiagnostic.
+type JSONTree map[string]map[string]interface{}
+
+// Add adds the result of analysis 'name' on package 'id'.
+// The result is either a list of diagnostics or an error.
+func (tree JSONTree) Add(fset *token.FileSet, id, name string, diags []analysis.Diagnostic, err error) {
+ var v interface{}
+ if err != nil {
+ type jsonError struct {
+ Err string `json:"error"`
+ }
+ v = jsonError{err.Error()}
+ } else if len(diags) > 0 {
+ type jsonDiagnostic struct {
+ Category string `json:"category,omitempty"`
+ Posn string `json:"posn"`
+ Message string `json:"message"`
+ }
+ var diagnostics []jsonDiagnostic
+ // TODO(matloob): Should the JSON diagnostics contain ranges?
+ // If so, how should they be formatted?
+ for _, f := range diags {
+ diagnostics = append(diagnostics, jsonDiagnostic{
+ Category: f.Category,
+ Posn: fset.Position(f.Pos).String(),
+ Message: f.Message,
+ })
+ }
+ v = diagnostics
+ }
+ if v != nil {
+ m, ok := tree[id]
+ if !ok {
+ m = make(map[string]interface{})
+ tree[id] = m
+ }
+ m[name] = v
+ }
+}
+
+func (tree JSONTree) Print() {
+ data, err := json.MarshalIndent(tree, "", "\t")
+ if err != nil {
+ log.Panicf("internal error: JSON marshalling failed: %v", err)
+ }
+ fmt.Printf("%s\n", data)
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go b/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go
new file mode 100644
index 0000000000..c5a70f3b7d
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go
@@ -0,0 +1,92 @@
+package analysisflags
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "sort"
+ "strings"
+
+ "golang.org/x/tools/go/analysis"
+)
+
+const help = `PROGNAME is a tool for static analysis of Go programs.
+
+PROGNAME examines Go source code and reports suspicious constructs,
+such as Printf calls whose arguments do not align with the format
+string. It uses heuristics that do not guarantee all reports are
+genuine problems, but it can find errors not caught by the compilers.
+`
+
+// Help implements the help subcommand for a multichecker or unitchecker
+// style command. The optional args specify the analyzers to describe.
+// Help calls log.Fatal if no such analyzer exists.
+func Help(progname string, analyzers []*analysis.Analyzer, args []string) {
+ // No args: show summary of all analyzers.
+ if len(args) == 0 {
+ fmt.Println(strings.Replace(help, "PROGNAME", progname, -1))
+ fmt.Println("Registered analyzers:")
+ fmt.Println()
+ sort.Slice(analyzers, func(i, j int) bool {
+ return analyzers[i].Name < analyzers[j].Name
+ })
+ for _, a := range analyzers {
+ title := strings.Split(a.Doc, "\n\n")[0]
+ fmt.Printf(" %-12s %s\n", a.Name, title)
+ }
+ fmt.Println("\nBy default all analyzers are run.")
+ fmt.Println("To select specific analyzers, use the -NAME flag for each one,")
+ fmt.Println(" or -NAME=false to run all analyzers not explicitly disabled.")
+
+ // Show only the core command-line flags.
+ fmt.Println("\nCore flags:")
+ fmt.Println()
+ fs := flag.NewFlagSet("", flag.ExitOnError)
+ flag.VisitAll(func(f *flag.Flag) {
+ if !strings.Contains(f.Name, ".") {
+ fs.Var(f.Value, f.Name, f.Usage)
+ }
+ })
+ fs.SetOutput(os.Stdout)
+ fs.PrintDefaults()
+
+ fmt.Printf("\nTo see details and flags of a specific analyzer, run '%s help name'.\n", progname)
+
+ return
+ }
+
+ // Show help on specific analyzer(s).
+outer:
+ for _, arg := range args {
+ for _, a := range analyzers {
+ if a.Name == arg {
+ paras := strings.Split(a.Doc, "\n\n")
+ title := paras[0]
+ fmt.Printf("%s: %s\n", a.Name, title)
+
+ // Show only the flags relating to this analysis,
+ // properly prefixed.
+ first := true
+ fs := flag.NewFlagSet(a.Name, flag.ExitOnError)
+ a.Flags.VisitAll(func(f *flag.Flag) {
+ if first {
+ first = false
+ fmt.Println("\nAnalyzer flags:")
+ fmt.Println()
+ }
+ fs.Var(f.Value, a.Name+"."+f.Name, f.Usage)
+ })
+ fs.SetOutput(os.Stdout)
+ fs.PrintDefaults()
+
+ if len(paras) > 1 {
+ fmt.Printf("\n%s\n", strings.Join(paras[1:], "\n\n"))
+ }
+
+ continue outer
+ }
+ }
+ log.Fatalf("Analyzer %q not registered", arg)
+ }
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/internal/facts/facts.go b/vendor/golang.org/x/tools/go/analysis/internal/facts/facts.go
new file mode 100644
index 0000000000..1fb69c6159
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/internal/facts/facts.go
@@ -0,0 +1,323 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package facts defines a serializable set of analysis.Fact.
+//
+// It provides a partial implementation of the Fact-related parts of the
+// analysis.Pass interface for use in analysis drivers such as "go vet"
+// and other build systems.
+//
+// The serial format is unspecified and may change, so the same version
+// of this package must be used for reading and writing serialized facts.
+//
+// The handling of facts in the analysis system parallels the handling
+// of type information in the compiler: during compilation of package P,
+// the compiler emits an export data file that describes the type of
+// every object (named thing) defined in package P, plus every object
+// indirectly reachable from one of those objects. Thus the downstream
+// compiler of package Q need only load one export data file per direct
+// import of Q, and it will learn everything about the API of package P
+// and everything it needs to know about the API of P's dependencies.
+//
+// Similarly, analysis of package P emits a fact set containing facts
+// about all objects exported from P, plus additional facts about only
+// those objects of P's dependencies that are reachable from the API of
+// package P; the downstream analysis of Q need only load one fact set
+// per direct import of Q.
+//
+// The notion of "exportedness" that matters here is that of the
+// compiler. According to the language spec, a method pkg.T.f is
+// unexported simply because its name starts with lowercase. But the
+// compiler must nonetheless export f so that downstream compilations can
+// accurately ascertain whether pkg.T implements an interface pkg.I
+// defined as interface{f()}. Exported thus means "described in export
+// data".
+//
+package facts
+
+import (
+ "bytes"
+ "encoding/gob"
+ "fmt"
+ "go/types"
+ "io/ioutil"
+ "log"
+ "reflect"
+ "sort"
+ "sync"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/types/objectpath"
+)
+
+const debug = false
+
+// A Set is a set of analysis.Facts.
+//
+// Decode creates a Set of facts by reading from the imports of a given
+// package, and Encode writes out the set. Between these operation,
+// the Import and Export methods will query and update the set.
+//
+// All of Set's methods except String are safe to call concurrently.
+type Set struct {
+ pkg *types.Package
+ mu sync.Mutex
+ m map[key]analysis.Fact
+}
+
+type key struct {
+ pkg *types.Package
+ obj types.Object // (object facts only)
+ t reflect.Type
+}
+
+// ImportObjectFact implements analysis.Pass.ImportObjectFact.
+func (s *Set) ImportObjectFact(obj types.Object, ptr analysis.Fact) bool {
+ if obj == nil {
+ panic("nil object")
+ }
+ key := key{pkg: obj.Pkg(), obj: obj, t: reflect.TypeOf(ptr)}
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if v, ok := s.m[key]; ok {
+ reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())
+ return true
+ }
+ return false
+}
+
+// ExportObjectFact implements analysis.Pass.ExportObjectFact.
+func (s *Set) ExportObjectFact(obj types.Object, fact analysis.Fact) {
+ if obj.Pkg() != s.pkg {
+ log.Panicf("in package %s: ExportObjectFact(%s, %T): can't set fact on object belonging another package",
+ s.pkg, obj, fact)
+ }
+ key := key{pkg: obj.Pkg(), obj: obj, t: reflect.TypeOf(fact)}
+ s.mu.Lock()
+ s.m[key] = fact // clobber any existing entry
+ s.mu.Unlock()
+}
+
+func (s *Set) AllObjectFacts(filter map[reflect.Type]bool) []analysis.ObjectFact {
+ var facts []analysis.ObjectFact
+ s.mu.Lock()
+ for k, v := range s.m {
+ if k.obj != nil && filter[k.t] {
+ facts = append(facts, analysis.ObjectFact{Object: k.obj, Fact: v})
+ }
+ }
+ s.mu.Unlock()
+ return facts
+}
+
+// ImportPackageFact implements analysis.Pass.ImportPackageFact.
+func (s *Set) ImportPackageFact(pkg *types.Package, ptr analysis.Fact) bool {
+ if pkg == nil {
+ panic("nil package")
+ }
+ key := key{pkg: pkg, t: reflect.TypeOf(ptr)}
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if v, ok := s.m[key]; ok {
+ reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(v).Elem())
+ return true
+ }
+ return false
+}
+
+// ExportPackageFact implements analysis.Pass.ExportPackageFact.
+func (s *Set) ExportPackageFact(fact analysis.Fact) {
+ key := key{pkg: s.pkg, t: reflect.TypeOf(fact)}
+ s.mu.Lock()
+ s.m[key] = fact // clobber any existing entry
+ s.mu.Unlock()
+}
+
+func (s *Set) AllPackageFacts(filter map[reflect.Type]bool) []analysis.PackageFact {
+ var facts []analysis.PackageFact
+ s.mu.Lock()
+ for k, v := range s.m {
+ if k.obj == nil && filter[k.t] {
+ facts = append(facts, analysis.PackageFact{Package: k.pkg, Fact: v})
+ }
+ }
+ s.mu.Unlock()
+ return facts
+}
+
+// gobFact is the Gob declaration of a serialized fact.
+type gobFact struct {
+ PkgPath string // path of package
+ Object objectpath.Path // optional path of object relative to package itself
+ Fact analysis.Fact // type and value of user-defined Fact
+}
+
+// Decode decodes all the facts relevant to the analysis of package pkg.
+// The read function reads serialized fact data from an external source
+// for one of of pkg's direct imports. The empty file is a valid
+// encoding of an empty fact set.
+//
+// It is the caller's responsibility to call gob.Register on all
+// necessary fact types.
+func Decode(pkg *types.Package, read func(packagePath string) ([]byte, error)) (*Set, error) {
+ // Compute the import map for this package.
+ // See the package doc comment.
+ packages := importMap(pkg.Imports())
+
+ // Read facts from imported packages.
+ // Facts may describe indirectly imported packages, or their objects.
+ m := make(map[key]analysis.Fact) // one big bucket
+ for _, imp := range pkg.Imports() {
+ logf := func(format string, args ...interface{}) {
+ if debug {
+ prefix := fmt.Sprintf("in %s, importing %s: ",
+ pkg.Path(), imp.Path())
+ log.Print(prefix, fmt.Sprintf(format, args...))
+ }
+ }
+
+ // Read the gob-encoded facts.
+ data, err := read(imp.Path())
+ if err != nil {
+ return nil, fmt.Errorf("in %s, can't import facts for package %q: %v",
+ pkg.Path(), imp.Path(), err)
+ }
+ if len(data) == 0 {
+ continue // no facts
+ }
+ var gobFacts []gobFact
+ if err := gob.NewDecoder(bytes.NewReader(data)).Decode(&gobFacts); err != nil {
+ return nil, fmt.Errorf("decoding facts for %q: %v", imp.Path(), err)
+ }
+ if debug {
+ logf("decoded %d facts: %v", len(gobFacts), gobFacts)
+ }
+
+ // Parse each one into a key and a Fact.
+ for _, f := range gobFacts {
+ factPkg := packages[f.PkgPath]
+ if factPkg == nil {
+ // Fact relates to a dependency that was
+ // unused in this translation unit. Skip.
+ logf("no package %q; discarding %v", f.PkgPath, f.Fact)
+ continue
+ }
+ key := key{pkg: factPkg, t: reflect.TypeOf(f.Fact)}
+ if f.Object != "" {
+ // object fact
+ obj, err := objectpath.Object(factPkg, f.Object)
+ if err != nil {
+ // (most likely due to unexported object)
+ // TODO(adonovan): audit for other possibilities.
+ logf("no object for path: %v; discarding %s", err, f.Fact)
+ continue
+ }
+ key.obj = obj
+ logf("read %T fact %s for %v", f.Fact, f.Fact, key.obj)
+ } else {
+ // package fact
+ logf("read %T fact %s for %v", f.Fact, f.Fact, factPkg)
+ }
+ m[key] = f.Fact
+ }
+ }
+
+ return &Set{pkg: pkg, m: m}, nil
+}
+
+// Encode encodes a set of facts to a memory buffer.
+//
+// It may fail if one of the Facts could not be gob-encoded, but this is
+// a sign of a bug in an Analyzer.
+func (s *Set) Encode() []byte {
+
+ // TODO(adonovan): opt: use a more efficient encoding
+ // that avoids repeating PkgPath for each fact.
+
+ // Gather all facts, including those from imported packages.
+ var gobFacts []gobFact
+
+ s.mu.Lock()
+ for k, fact := range s.m {
+ if debug {
+ log.Printf("%v => %s\n", k, fact)
+ }
+ var object objectpath.Path
+ if k.obj != nil {
+ path, err := objectpath.For(k.obj)
+ if err != nil {
+ if debug {
+ log.Printf("discarding fact %s about %s\n", fact, k.obj)
+ }
+ continue // object not accessible from package API; discard fact
+ }
+ object = path
+ }
+ gobFacts = append(gobFacts, gobFact{
+ PkgPath: k.pkg.Path(),
+ Object: object,
+ Fact: fact,
+ })
+ }
+ s.mu.Unlock()
+
+ // Sort facts by (package, object, type) for determinism.
+ sort.Slice(gobFacts, func(i, j int) bool {
+ x, y := gobFacts[i], gobFacts[j]
+ if x.PkgPath != y.PkgPath {
+ return x.PkgPath < y.PkgPath
+ }
+ if x.Object != y.Object {
+ return x.Object < y.Object
+ }
+ tx := reflect.TypeOf(x.Fact)
+ ty := reflect.TypeOf(y.Fact)
+ if tx != ty {
+ return tx.String() < ty.String()
+ }
+ return false // equal
+ })
+
+ var buf bytes.Buffer
+ if len(gobFacts) > 0 {
+ if err := gob.NewEncoder(&buf).Encode(gobFacts); err != nil {
+ // Fact encoding should never fail. Identify the culprit.
+ for _, gf := range gobFacts {
+ if err := gob.NewEncoder(ioutil.Discard).Encode(gf); err != nil {
+ fact := gf.Fact
+ pkgpath := reflect.TypeOf(fact).Elem().PkgPath()
+ log.Panicf("internal error: gob encoding of analysis fact %s failed: %v; please report a bug against fact %T in package %q",
+ fact, err, fact, pkgpath)
+ }
+ }
+ }
+ }
+
+ if debug {
+ log.Printf("package %q: encode %d facts, %d bytes\n",
+ s.pkg.Path(), len(gobFacts), buf.Len())
+ }
+
+ return buf.Bytes()
+}
+
+// String is provided only for debugging, and must not be called
+// concurrent with any Import/Export method.
+func (s *Set) String() string {
+ var buf bytes.Buffer
+ buf.WriteString("{")
+ for k, f := range s.m {
+ if buf.Len() > 1 {
+ buf.WriteString(", ")
+ }
+ if k.obj != nil {
+ buf.WriteString(k.obj.String())
+ } else {
+ buf.WriteString(k.pkg.Path())
+ }
+ fmt.Fprintf(&buf, ": %v", f)
+ }
+ buf.WriteString("}")
+ return buf.String()
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go b/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go
new file mode 100644
index 0000000000..34740f48e0
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go
@@ -0,0 +1,88 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package facts
+
+import "go/types"
+
+// importMap computes the import map for a package by traversing the
+// entire exported API each of its imports.
+//
+// This is a workaround for the fact that we cannot access the map used
+// internally by the types.Importer returned by go/importer. The entries
+// in this map are the packages and objects that may be relevant to the
+// current analysis unit.
+//
+// Packages in the map that are only indirectly imported may be
+// incomplete (!pkg.Complete()).
+//
+func importMap(imports []*types.Package) map[string]*types.Package {
+ objects := make(map[types.Object]bool)
+ packages := make(map[string]*types.Package)
+
+ var addObj func(obj types.Object) bool
+ var addType func(T types.Type)
+
+ addObj = func(obj types.Object) bool {
+ if !objects[obj] {
+ objects[obj] = true
+ addType(obj.Type())
+ if pkg := obj.Pkg(); pkg != nil {
+ packages[pkg.Path()] = pkg
+ }
+ return true
+ }
+ return false
+ }
+
+ addType = func(T types.Type) {
+ switch T := T.(type) {
+ case *types.Basic:
+ // nop
+ case *types.Named:
+ if addObj(T.Obj()) {
+ for i := 0; i < T.NumMethods(); i++ {
+ addObj(T.Method(i))
+ }
+ }
+ case *types.Pointer:
+ addType(T.Elem())
+ case *types.Slice:
+ addType(T.Elem())
+ case *types.Array:
+ addType(T.Elem())
+ case *types.Chan:
+ addType(T.Elem())
+ case *types.Map:
+ addType(T.Key())
+ addType(T.Elem())
+ case *types.Signature:
+ addType(T.Params())
+ addType(T.Results())
+ case *types.Struct:
+ for i := 0; i < T.NumFields(); i++ {
+ addObj(T.Field(i))
+ }
+ case *types.Tuple:
+ for i := 0; i < T.Len(); i++ {
+ addObj(T.At(i))
+ }
+ case *types.Interface:
+ for i := 0; i < T.NumMethods(); i++ {
+ addObj(T.Method(i))
+ }
+ }
+ }
+
+ for _, imp := range imports {
+ packages[imp.Path()] = imp
+
+ scope := imp.Scope()
+ for _, name := range scope.Names() {
+ addObj(scope.Lookup(name))
+ }
+ }
+
+ return packages
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go b/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
new file mode 100644
index 0000000000..2ed274949b
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
@@ -0,0 +1,396 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The unitchecker package defines the main function for an analysis
+// driver that analyzes a single compilation unit during a build.
+// It is invoked by a build system such as "go vet":
+//
+// $ go vet -vettool=$(which vet)
+//
+// It supports the following command-line protocol:
+//
+// -V=full describe executable (to the build tool)
+// -flags describe flags (to the build tool)
+// foo.cfg description of compilation unit (from the build tool)
+//
+// This package does not depend on go/packages.
+// If you need a standalone tool, use multichecker,
+// which supports this mode but can also load packages
+// from source using go/packages.
+package unitchecker
+
+// TODO(adonovan):
+// - with gccgo, go build does not build standard library,
+// so we will not get to analyze it. Yet we must in order
+// to create base facts for, say, the fmt package for the
+// printf checker.
+
+import (
+ "encoding/gob"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/importer"
+ "go/parser"
+ "go/token"
+ "go/types"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/internal/analysisflags"
+ "golang.org/x/tools/go/analysis/internal/facts"
+)
+
+// A Config describes a compilation unit to be analyzed.
+// It is provided to the tool in a JSON-encoded file
+// whose name ends with ".cfg".
+type Config struct {
+ ID string // e.g. "fmt [fmt.test]"
+ Compiler string
+ Dir string
+ ImportPath string
+ GoFiles []string
+ NonGoFiles []string
+ ImportMap map[string]string
+ PackageFile map[string]string
+ Standard map[string]bool
+ PackageVetx map[string]string
+ VetxOnly bool
+ VetxOutput string
+ SucceedOnTypecheckFailure bool
+}
+
+// Main is the main function of a vet-like analysis tool that must be
+// invoked by a build system to analyze a single package.
+//
+// The protocol required by 'go vet -vettool=...' is that the tool must support:
+//
+// -flags describe flags in JSON
+// -V=full describe executable for build caching
+// foo.cfg perform separate modular analyze on the single
+// unit described by a JSON config file foo.cfg.
+//
+func Main(analyzers ...*analysis.Analyzer) {
+ progname := filepath.Base(os.Args[0])
+ log.SetFlags(0)
+ log.SetPrefix(progname + ": ")
+
+ if err := analysis.Validate(analyzers); err != nil {
+ log.Fatal(err)
+ }
+
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, `%[1]s is a tool for static analysis of Go programs.
+
+Usage of %[1]s:
+ %.16[1]s unit.cfg # execute analysis specified by config file
+ %.16[1]s help # general help
+ %.16[1]s help name # help on specific analyzer and its flags
+`, progname)
+ os.Exit(1)
+ }
+
+ analyzers = analysisflags.Parse(analyzers, true)
+
+ args := flag.Args()
+ if len(args) == 0 {
+ flag.Usage()
+ }
+ if args[0] == "help" {
+ analysisflags.Help(progname, analyzers, args[1:])
+ os.Exit(0)
+ }
+ if len(args) != 1 || !strings.HasSuffix(args[0], ".cfg") {
+ log.Fatalf(`invoking "go tool vet" directly is unsupported; use "go vet"`)
+ }
+ Run(args[0], analyzers)
+}
+
+// Run reads the *.cfg file, runs the analysis,
+// and calls os.Exit with an appropriate error code.
+// It assumes flags have already been set.
+func Run(configFile string, analyzers []*analysis.Analyzer) {
+ cfg, err := readConfig(configFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fset := token.NewFileSet()
+ results, err := run(fset, cfg, analyzers)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // In VetxOnly mode, the analysis is run only for facts.
+ if !cfg.VetxOnly {
+ if analysisflags.JSON {
+ // JSON output
+ tree := make(analysisflags.JSONTree)
+ for _, res := range results {
+ tree.Add(fset, cfg.ID, res.a.Name, res.diagnostics, res.err)
+ }
+ tree.Print()
+ } else {
+ // plain text
+ exit := 0
+ for _, res := range results {
+ if res.err != nil {
+ log.Println(res.err)
+ exit = 1
+ }
+ }
+ for _, res := range results {
+ for _, diag := range res.diagnostics {
+ analysisflags.PrintPlain(fset, diag)
+ exit = 1
+ }
+ }
+ os.Exit(exit)
+ }
+ }
+
+ os.Exit(0)
+}
+
+func readConfig(filename string) (*Config, error) {
+ data, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ cfg := new(Config)
+ if err := json.Unmarshal(data, cfg); err != nil {
+ return nil, fmt.Errorf("cannot decode JSON config file %s: %v", filename, err)
+ }
+ if len(cfg.GoFiles) == 0 {
+ // The go command disallows packages with no files.
+ // The only exception is unsafe, but the go command
+ // doesn't call vet on it.
+ return nil, fmt.Errorf("package has no files: %s", cfg.ImportPath)
+ }
+ return cfg, nil
+}
+
+var importerForCompiler = func(_ *token.FileSet, compiler string, lookup importer.Lookup) types.Importer {
+ // broken legacy implementation (https://golang.org/issue/28995)
+ return importer.For(compiler, lookup)
+}
+
+func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]result, error) {
+ // Load, parse, typecheck.
+ var files []*ast.File
+ for _, name := range cfg.GoFiles {
+ f, err := parser.ParseFile(fset, name, nil, parser.ParseComments)
+ if err != nil {
+ if cfg.SucceedOnTypecheckFailure {
+ // Silently succeed; let the compiler
+ // report parse errors.
+ err = nil
+ }
+ return nil, err
+ }
+ files = append(files, f)
+ }
+ compilerImporter := importerForCompiler(fset, cfg.Compiler, func(path string) (io.ReadCloser, error) {
+ // path is a resolved package path, not an import path.
+ file, ok := cfg.PackageFile[path]
+ if !ok {
+ if cfg.Compiler == "gccgo" && cfg.Standard[path] {
+ return nil, nil // fall back to default gccgo lookup
+ }
+ return nil, fmt.Errorf("no package file for %q", path)
+ }
+ return os.Open(file)
+ })
+ importer := importerFunc(func(importPath string) (*types.Package, error) {
+ path, ok := cfg.ImportMap[importPath] // resolve vendoring, etc
+ if !ok {
+ return nil, fmt.Errorf("can't resolve import %q", path)
+ }
+ return compilerImporter.Import(path)
+ })
+ tc := &types.Config{
+ Importer: importer,
+ Sizes: types.SizesFor("gc", build.Default.GOARCH), // assume gccgo ≡ gc?
+ }
+ info := &types.Info{
+ Types: make(map[ast.Expr]types.TypeAndValue),
+ Defs: make(map[*ast.Ident]types.Object),
+ Uses: make(map[*ast.Ident]types.Object),
+ Implicits: make(map[ast.Node]types.Object),
+ Scopes: make(map[ast.Node]*types.Scope),
+ Selections: make(map[*ast.SelectorExpr]*types.Selection),
+ }
+ pkg, err := tc.Check(cfg.ImportPath, fset, files, info)
+ if err != nil {
+ if cfg.SucceedOnTypecheckFailure {
+ // Silently succeed; let the compiler
+ // report type errors.
+ err = nil
+ }
+ return nil, err
+ }
+
+ // Register fact types with gob.
+ // In VetxOnly mode, analyzers are only for their facts,
+ // so we can skip any analysis that neither produces facts
+ // nor depends on any analysis that produces facts.
+ // Also build a map to hold working state and result.
+ type action struct {
+ once sync.Once
+ result interface{}
+ err error
+ usesFacts bool // (transitively uses)
+ diagnostics []analysis.Diagnostic
+ }
+ actions := make(map[*analysis.Analyzer]*action)
+ var registerFacts func(a *analysis.Analyzer) bool
+ registerFacts = func(a *analysis.Analyzer) bool {
+ act, ok := actions[a]
+ if !ok {
+ act = new(action)
+ var usesFacts bool
+ for _, f := range a.FactTypes {
+ usesFacts = true
+ gob.Register(f)
+ }
+ for _, req := range a.Requires {
+ if registerFacts(req) {
+ usesFacts = true
+ }
+ }
+ act.usesFacts = usesFacts
+ actions[a] = act
+ }
+ return act.usesFacts
+ }
+ var filtered []*analysis.Analyzer
+ for _, a := range analyzers {
+ if registerFacts(a) || !cfg.VetxOnly {
+ filtered = append(filtered, a)
+ }
+ }
+ analyzers = filtered
+
+ // Read facts from imported packages.
+ read := func(path string) ([]byte, error) {
+ if vetx, ok := cfg.PackageVetx[path]; ok {
+ return ioutil.ReadFile(vetx)
+ }
+ return nil, nil // no .vetx file, no facts
+ }
+ facts, err := facts.Decode(pkg, read)
+ if err != nil {
+ return nil, err
+ }
+
+ // In parallel, execute the DAG of analyzers.
+ var exec func(a *analysis.Analyzer) *action
+ var execAll func(analyzers []*analysis.Analyzer)
+ exec = func(a *analysis.Analyzer) *action {
+ act := actions[a]
+ act.once.Do(func() {
+ execAll(a.Requires) // prefetch dependencies in parallel
+
+ // The inputs to this analysis are the
+ // results of its prerequisites.
+ inputs := make(map[*analysis.Analyzer]interface{})
+ var failed []string
+ for _, req := range a.Requires {
+ reqact := exec(req)
+ if reqact.err != nil {
+ failed = append(failed, req.String())
+ continue
+ }
+ inputs[req] = reqact.result
+ }
+
+ // Report an error if any dependency failed.
+ if failed != nil {
+ sort.Strings(failed)
+ act.err = fmt.Errorf("failed prerequisites: %s", strings.Join(failed, ", "))
+ return
+ }
+
+ factFilter := make(map[reflect.Type]bool)
+ for _, f := range a.FactTypes {
+ factFilter[reflect.TypeOf(f)] = true
+ }
+
+ pass := &analysis.Pass{
+ Analyzer: a,
+ Fset: fset,
+ Files: files,
+ OtherFiles: cfg.NonGoFiles,
+ Pkg: pkg,
+ TypesInfo: info,
+ TypesSizes: tc.Sizes,
+ ResultOf: inputs,
+ Report: func(d analysis.Diagnostic) { act.diagnostics = append(act.diagnostics, d) },
+ ImportObjectFact: facts.ImportObjectFact,
+ ExportObjectFact: facts.ExportObjectFact,
+ AllObjectFacts: func() []analysis.ObjectFact { return facts.AllObjectFacts(factFilter) },
+ ImportPackageFact: facts.ImportPackageFact,
+ ExportPackageFact: facts.ExportPackageFact,
+ AllPackageFacts: func() []analysis.PackageFact { return facts.AllPackageFacts(factFilter) },
+ }
+
+ t0 := time.Now()
+ act.result, act.err = a.Run(pass)
+ if false {
+ log.Printf("analysis %s = %s", pass, time.Since(t0))
+ }
+ })
+ return act
+ }
+ execAll = func(analyzers []*analysis.Analyzer) {
+ var wg sync.WaitGroup
+ for _, a := range analyzers {
+ wg.Add(1)
+ go func(a *analysis.Analyzer) {
+ _ = exec(a)
+ wg.Done()
+ }(a)
+ }
+ wg.Wait()
+ }
+
+ execAll(analyzers)
+
+ // Return diagnostics and errors from root analyzers.
+ results := make([]result, len(analyzers))
+ for i, a := range analyzers {
+ act := actions[a]
+ results[i].a = a
+ results[i].err = act.err
+ results[i].diagnostics = act.diagnostics
+ }
+
+ data := facts.Encode()
+ if err := ioutil.WriteFile(cfg.VetxOutput, data, 0666); err != nil {
+ return nil, fmt.Errorf("failed to write analysis facts: %v", err)
+ }
+
+ return results, nil
+}
+
+type result struct {
+ a *analysis.Analyzer
+ diagnostics []analysis.Diagnostic
+ err error
+}
+
+type importerFunc func(path string) (*types.Package, error)
+
+func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
diff --git a/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go b/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go
new file mode 100644
index 0000000000..683b7e91d2
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go
@@ -0,0 +1,9 @@
+// +build go1.12
+
+package unitchecker
+
+import "go/importer"
+
+func init() {
+ importerForCompiler = importer.ForCompiler
+}
diff --git a/vendor/golang.org/x/tools/go/analysis/validate.go b/vendor/golang.org/x/tools/go/analysis/validate.go
new file mode 100644
index 0000000000..be98143461
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/analysis/validate.go
@@ -0,0 +1,97 @@
+package analysis
+
+import (
+ "fmt"
+ "reflect"
+ "unicode"
+)
+
+// Validate reports an error if any of the analyzers are misconfigured.
+// Checks include:
+// that the name is a valid identifier;
+// that the Requires graph is acyclic;
+// that analyzer fact types are unique;
+// that each fact type is a pointer.
+func Validate(analyzers []*Analyzer) error {
+ // Map each fact type to its sole generating analyzer.
+ factTypes := make(map[reflect.Type]*Analyzer)
+
+ // Traverse the Requires graph, depth first.
+ const (
+ white = iota
+ grey
+ black
+ finished
+ )
+ color := make(map[*Analyzer]uint8)
+ var visit func(a *Analyzer) error
+ visit = func(a *Analyzer) error {
+ if a == nil {
+ return fmt.Errorf("nil *Analyzer")
+ }
+ if color[a] == white {
+ color[a] = grey
+
+ // names
+ if !validIdent(a.Name) {
+ return fmt.Errorf("invalid analyzer name %q", a)
+ }
+
+ if a.Doc == "" {
+ return fmt.Errorf("analyzer %q is undocumented", a)
+ }
+
+ // fact types
+ for _, f := range a.FactTypes {
+ if f == nil {
+ return fmt.Errorf("analyzer %s has nil FactType", a)
+ }
+ t := reflect.TypeOf(f)
+ if prev := factTypes[t]; prev != nil {
+ return fmt.Errorf("fact type %s registered by two analyzers: %v, %v",
+ t, a, prev)
+ }
+ if t.Kind() != reflect.Ptr {
+ return fmt.Errorf("%s: fact type %s is not a pointer", a, t)
+ }
+ factTypes[t] = a
+ }
+
+ // recursion
+ for i, req := range a.Requires {
+ if err := visit(req); err != nil {
+ return fmt.Errorf("%s.Requires[%d]: %v", a.Name, i, err)
+ }
+ }
+ color[a] = black
+ }
+
+ return nil
+ }
+ for _, a := range analyzers {
+ if err := visit(a); err != nil {
+ return err
+ }
+ }
+
+ // Reject duplicates among analyzers.
+ // Precondition: color[a] == black.
+ // Postcondition: color[a] == finished.
+ for _, a := range analyzers {
+ if color[a] == finished {
+ return fmt.Errorf("duplicate analyzer: %s", a.Name)
+ }
+ color[a] = finished
+ }
+
+ return nil
+}
+
+func validIdent(name string) bool {
+ for i, r := range name {
+ if !(r == '_' || unicode.IsLetter(r) || i > 0 && unicode.IsDigit(r)) {
+ return false
+ }
+ }
+ return name != ""
+}
diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
new file mode 100644
index 0000000000..882e3b3d8a
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
@@ -0,0 +1,523 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package objectpath defines a naming scheme for types.Objects
+// (that is, named entities in Go programs) relative to their enclosing
+// package.
+//
+// Type-checker objects are canonical, so they are usually identified by
+// their address in memory (a pointer), but a pointer has meaning only
+// within one address space. By contrast, objectpath names allow the
+// identity of an object to be sent from one program to another,
+// establishing a correspondence between types.Object variables that are
+// distinct but logically equivalent.
+//
+// A single object may have multiple paths. In this example,
+// type A struct{ X int }
+// type B A
+// the field X has two paths due to its membership of both A and B.
+// The For(obj) function always returns one of these paths, arbitrarily
+// but consistently.
+package objectpath
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "go/types"
+)
+
+// A Path is an opaque name that identifies a types.Object
+// relative to its package. Conceptually, the name consists of a
+// sequence of destructuring operations applied to the package scope
+// to obtain the original object.
+// The name does not include the package itself.
+type Path string
+
+// Encoding
+//
+// An object path is a textual and (with training) human-readable encoding
+// of a sequence of destructuring operators, starting from a types.Package.
+// The sequences represent a path through the package/object/type graph.
+// We classify these operators by their type:
+//
+// PO package->object Package.Scope.Lookup
+// OT object->type Object.Type
+// TT type->type Type.{Elem,Key,Params,Results,Underlying} [EKPRU]
+// TO type->object Type.{At,Field,Method,Obj} [AFMO]
+//
+// All valid paths start with a package and end at an object
+// and thus may be defined by the regular language:
+//
+// objectpath = PO (OT TT* TO)*
+//
+// The concrete encoding follows directly:
+// - The only PO operator is Package.Scope.Lookup, which requires an identifier.
+// - The only OT operator is Object.Type,
+// which we encode as '.' because dot cannot appear in an identifier.
+// - The TT operators are encoded as [EKPRU].
+// - The OT operators are encoded as [AFMO];
+// three of these (At,Field,Method) require an integer operand,
+// which is encoded as a string of decimal digits.
+// These indices are stable across different representations
+// of the same package, even source and export data.
+//
+// In the example below,
+//
+// package p
+//
+// type T interface {
+// f() (a string, b struct{ X int })
+// }
+//
+// field X has the path "T.UM0.RA1.F0",
+// representing the following sequence of operations:
+//
+// p.Lookup("T") T
+// .Type().Underlying().Method(0). f
+// .Type().Results().At(1) b
+// .Type().Field(0) X
+//
+// The encoding is not maximally compact---every R or P is
+// followed by an A, for example---but this simplifies the
+// encoder and decoder.
+//
+const (
+ // object->type operators
+ opType = '.' // .Type() (Object)
+
+ // type->type operators
+ opElem = 'E' // .Elem() (Pointer, Slice, Array, Chan, Map)
+ opKey = 'K' // .Key() (Map)
+ opParams = 'P' // .Params() (Signature)
+ opResults = 'R' // .Results() (Signature)
+ opUnderlying = 'U' // .Underlying() (Named)
+
+ // type->object operators
+ opAt = 'A' // .At(i) (Tuple)
+ opField = 'F' // .Field(i) (Struct)
+ opMethod = 'M' // .Method(i) (Named or Interface; not Struct: "promoted" names are ignored)
+ opObj = 'O' // .Obj() (Named)
+)
+
+// The For function returns the path to an object relative to its package,
+// or an error if the object is not accessible from the package's Scope.
+//
+// The For function guarantees to return a path only for the following objects:
+// - package-level types
+// - exported package-level non-types
+// - methods
+// - parameter and result variables
+// - struct fields
+// These objects are sufficient to define the API of their package.
+// The objects described by a package's export data are drawn from this set.
+//
+// For does not return a path for predeclared names, imported package
+// names, local names, and unexported package-level names (except
+// types).
+//
+// Example: given this definition,
+//
+// package p
+//
+// type T interface {
+// f() (a string, b struct{ X int })
+// }
+//
+// For(X) would return a path that denotes the following sequence of operations:
+//
+// p.Scope().Lookup("T") (TypeName T)
+// .Type().Underlying().Method(0). (method Func f)
+// .Type().Results().At(1) (field Var b)
+// .Type().Field(0) (field Var X)
+//
+// where p is the package (*types.Package) to which X belongs.
+func For(obj types.Object) (Path, error) {
+ pkg := obj.Pkg()
+
+ // This table lists the cases of interest.
+ //
+ // Object Action
+ // ------ ------
+ // nil reject
+ // builtin reject
+ // pkgname reject
+ // label reject
+ // var
+ // package-level accept
+ // func param/result accept
+ // local reject
+ // struct field accept
+ // const
+ // package-level accept
+ // local reject
+ // func
+ // package-level accept
+ // init functions reject
+ // concrete method accept
+ // interface method accept
+ // type
+ // package-level accept
+ // local reject
+ //
+ // The only accessible package-level objects are members of pkg itself.
+ //
+ // The cases are handled in four steps:
+ //
+ // 1. reject nil and builtin
+ // 2. accept package-level objects
+ // 3. reject obviously invalid objects
+ // 4. search the API for the path to the param/result/field/method.
+
+ // 1. reference to nil or builtin?
+ if pkg == nil {
+ return "", fmt.Errorf("predeclared %s has no path", obj)
+ }
+ scope := pkg.Scope()
+
+ // 2. package-level object?
+ if scope.Lookup(obj.Name()) == obj {
+ // Only exported objects (and non-exported types) have a path.
+ // Non-exported types may be referenced by other objects.
+ if _, ok := obj.(*types.TypeName); !ok && !obj.Exported() {
+ return "", fmt.Errorf("no path for non-exported %v", obj)
+ }
+ return Path(obj.Name()), nil
+ }
+
+ // 3. Not a package-level object.
+ // Reject obviously non-viable cases.
+ switch obj := obj.(type) {
+ case *types.Const, // Only package-level constants have a path.
+ *types.TypeName, // Only package-level types have a path.
+ *types.Label, // Labels are function-local.
+ *types.PkgName: // PkgNames are file-local.
+ return "", fmt.Errorf("no path for %v", obj)
+
+ case *types.Var:
+ // Could be:
+ // - a field (obj.IsField())
+ // - a func parameter or result
+ // - a local var.
+ // Sadly there is no way to distinguish
+ // a param/result from a local
+ // so we must proceed to the find.
+
+ case *types.Func:
+ // A func, if not package-level, must be a method.
+ if recv := obj.Type().(*types.Signature).Recv(); recv == nil {
+ return "", fmt.Errorf("func is not a method: %v", obj)
+ }
+ // TODO(adonovan): opt: if the method is concrete,
+ // do a specialized version of the rest of this function so
+ // that it's O(1) not O(|scope|). Basically 'find' is needed
+ // only for struct fields and interface methods.
+
+ default:
+ panic(obj)
+ }
+
+ // 4. Search the API for the path to the var (field/param/result) or method.
+
+ // First inspect package-level named types.
+ // In the presence of path aliases, these give
+ // the best paths because non-types may
+ // refer to types, but not the reverse.
+ empty := make([]byte, 0, 48) // initial space
+ for _, name := range scope.Names() {
+ o := scope.Lookup(name)
+ tname, ok := o.(*types.TypeName)
+ if !ok {
+ continue // handle non-types in second pass
+ }
+
+ path := append(empty, name...)
+ path = append(path, opType)
+
+ T := o.Type()
+
+ if tname.IsAlias() {
+ // type alias
+ if r := find(obj, T, path); r != nil {
+ return Path(r), nil
+ }
+ } else {
+ // defined (named) type
+ if r := find(obj, T.Underlying(), append(path, opUnderlying)); r != nil {
+ return Path(r), nil
+ }
+ }
+ }
+
+ // Then inspect everything else:
+ // non-types, and declared methods of defined types.
+ for _, name := range scope.Names() {
+ o := scope.Lookup(name)
+ path := append(empty, name...)
+ if _, ok := o.(*types.TypeName); !ok {
+ if o.Exported() {
+ // exported non-type (const, var, func)
+ if r := find(obj, o.Type(), append(path, opType)); r != nil {
+ return Path(r), nil
+ }
+ }
+ continue
+ }
+
+ // Inspect declared methods of defined types.
+ if T, ok := o.Type().(*types.Named); ok {
+ path = append(path, opType)
+ for i := 0; i < T.NumMethods(); i++ {
+ m := T.Method(i)
+ path2 := appendOpArg(path, opMethod, i)
+ if m == obj {
+ return Path(path2), nil // found declared method
+ }
+ if r := find(obj, m.Type(), append(path2, opType)); r != nil {
+ return Path(r), nil
+ }
+ }
+ }
+ }
+
+ return "", fmt.Errorf("can't find path for %v in %s", obj, pkg.Path())
+}
+
+func appendOpArg(path []byte, op byte, arg int) []byte {
+ path = append(path, op)
+ path = strconv.AppendInt(path, int64(arg), 10)
+ return path
+}
+
+// find finds obj within type T, returning the path to it, or nil if not found.
+func find(obj types.Object, T types.Type, path []byte) []byte {
+ switch T := T.(type) {
+ case *types.Basic, *types.Named:
+ // Named types belonging to pkg were handled already,
+ // so T must belong to another package. No path.
+ return nil
+ case *types.Pointer:
+ return find(obj, T.Elem(), append(path, opElem))
+ case *types.Slice:
+ return find(obj, T.Elem(), append(path, opElem))
+ case *types.Array:
+ return find(obj, T.Elem(), append(path, opElem))
+ case *types.Chan:
+ return find(obj, T.Elem(), append(path, opElem))
+ case *types.Map:
+ if r := find(obj, T.Key(), append(path, opKey)); r != nil {
+ return r
+ }
+ return find(obj, T.Elem(), append(path, opElem))
+ case *types.Signature:
+ if r := find(obj, T.Params(), append(path, opParams)); r != nil {
+ return r
+ }
+ return find(obj, T.Results(), append(path, opResults))
+ case *types.Struct:
+ for i := 0; i < T.NumFields(); i++ {
+ f := T.Field(i)
+ path2 := appendOpArg(path, opField, i)
+ if f == obj {
+ return path2 // found field var
+ }
+ if r := find(obj, f.Type(), append(path2, opType)); r != nil {
+ return r
+ }
+ }
+ return nil
+ case *types.Tuple:
+ for i := 0; i < T.Len(); i++ {
+ v := T.At(i)
+ path2 := appendOpArg(path, opAt, i)
+ if v == obj {
+ return path2 // found param/result var
+ }
+ if r := find(obj, v.Type(), append(path2, opType)); r != nil {
+ return r
+ }
+ }
+ return nil
+ case *types.Interface:
+ for i := 0; i < T.NumMethods(); i++ {
+ m := T.Method(i)
+ path2 := appendOpArg(path, opMethod, i)
+ if m == obj {
+ return path2 // found interface method
+ }
+ if r := find(obj, m.Type(), append(path2, opType)); r != nil {
+ return r
+ }
+ }
+ return nil
+ }
+ panic(T)
+}
+
+// Object returns the object denoted by path p within the package pkg.
+func Object(pkg *types.Package, p Path) (types.Object, error) {
+ if p == "" {
+ return nil, fmt.Errorf("empty path")
+ }
+
+ pathstr := string(p)
+ var pkgobj, suffix string
+ if dot := strings.IndexByte(pathstr, opType); dot < 0 {
+ pkgobj = pathstr
+ } else {
+ pkgobj = pathstr[:dot]
+ suffix = pathstr[dot:] // suffix starts with "."
+ }
+
+ obj := pkg.Scope().Lookup(pkgobj)
+ if obj == nil {
+ return nil, fmt.Errorf("package %s does not contain %q", pkg.Path(), pkgobj)
+ }
+
+ // abstraction of *types.{Pointer,Slice,Array,Chan,Map}
+ type hasElem interface {
+ Elem() types.Type
+ }
+ // abstraction of *types.{Interface,Named}
+ type hasMethods interface {
+ Method(int) *types.Func
+ NumMethods() int
+ }
+
+ // The loop state is the pair (t, obj),
+ // exactly one of which is non-nil, initially obj.
+ // All suffixes start with '.' (the only object->type operation),
+ // followed by optional type->type operations,
+ // then a type->object operation.
+ // The cycle then repeats.
+ var t types.Type
+ for suffix != "" {
+ code := suffix[0]
+ suffix = suffix[1:]
+
+ // Codes [AFM] have an integer operand.
+ var index int
+ switch code {
+ case opAt, opField, opMethod:
+ rest := strings.TrimLeft(suffix, "0123456789")
+ numerals := suffix[:len(suffix)-len(rest)]
+ suffix = rest
+ i, err := strconv.Atoi(numerals)
+ if err != nil {
+ return nil, fmt.Errorf("invalid path: bad numeric operand %q for code %q", numerals, code)
+ }
+ index = int(i)
+ case opObj:
+ // no operand
+ default:
+ // The suffix must end with a type->object operation.
+ if suffix == "" {
+ return nil, fmt.Errorf("invalid path: ends with %q, want [AFMO]", code)
+ }
+ }
+
+ if code == opType {
+ if t != nil {
+ return nil, fmt.Errorf("invalid path: unexpected %q in type context", opType)
+ }
+ t = obj.Type()
+ obj = nil
+ continue
+ }
+
+ if t == nil {
+ return nil, fmt.Errorf("invalid path: code %q in object context", code)
+ }
+
+ // Inv: t != nil, obj == nil
+
+ switch code {
+ case opElem:
+ hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %T, want pointer, slice, array, chan or map)", code, t, t)
+ }
+ t = hasElem.Elem()
+
+ case opKey:
+ mapType, ok := t.(*types.Map)
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %T, want map)", code, t, t)
+ }
+ t = mapType.Key()
+
+ case opParams:
+ sig, ok := t.(*types.Signature)
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %T, want signature)", code, t, t)
+ }
+ t = sig.Params()
+
+ case opResults:
+ sig, ok := t.(*types.Signature)
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %T, want signature)", code, t, t)
+ }
+ t = sig.Results()
+
+ case opUnderlying:
+ named, ok := t.(*types.Named)
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %s, want named)", code, t, t)
+ }
+ t = named.Underlying()
+
+ case opAt:
+ tuple, ok := t.(*types.Tuple)
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %s, want tuple)", code, t, t)
+ }
+ if n := tuple.Len(); index >= n {
+ return nil, fmt.Errorf("tuple index %d out of range [0-%d)", index, n)
+ }
+ obj = tuple.At(index)
+ t = nil
+
+ case opField:
+ structType, ok := t.(*types.Struct)
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %T, want struct)", code, t, t)
+ }
+ if n := structType.NumFields(); index >= n {
+ return nil, fmt.Errorf("field index %d out of range [0-%d)", index, n)
+ }
+ obj = structType.Field(index)
+ t = nil
+
+ case opMethod:
+ hasMethods, ok := t.(hasMethods) // Interface or Named
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %s, want interface or named)", code, t, t)
+ }
+ if n := hasMethods.NumMethods(); index >= n {
+ return nil, fmt.Errorf("method index %d out of range [0-%d)", index, n)
+ }
+ obj = hasMethods.Method(index)
+ t = nil
+
+ case opObj:
+ named, ok := t.(*types.Named)
+ if !ok {
+ return nil, fmt.Errorf("cannot apply %q to %s (got %s, want named)", code, t, t)
+ }
+ obj = named.Obj()
+ t = nil
+
+ default:
+ return nil, fmt.Errorf("invalid path: unknown code %q", code)
+ }
+ }
+
+ if obj.Pkg() != pkg {
+ return nil, fmt.Errorf("path denotes %s, which belongs to a different package", obj)
+ }
+
+ return obj, nil // success
+}
diff --git a/vendor/golang.org/x/tools/imports/forward.go b/vendor/golang.org/x/tools/imports/forward.go
index b4f4287679..dbe5b49a9f 100644
--- a/vendor/golang.org/x/tools/imports/forward.go
+++ b/vendor/golang.org/x/tools/imports/forward.go
@@ -4,6 +4,7 @@ package imports // import "golang.org/x/tools/imports"
import (
"go/build"
+ "log"
"os"
intimp "golang.org/x/tools/internal/imports"
@@ -47,7 +48,6 @@ func Process(filename string, src []byte, opt *Options) ([]byte, error) {
GO111MODULE: os.Getenv("GO111MODULE"),
GOPROXY: os.Getenv("GOPROXY"),
GOSUMDB: os.Getenv("GOSUMDB"),
- Debug: Debug,
LocalPrefix: LocalPrefix,
},
AllErrors: opt.AllErrors,
@@ -57,6 +57,9 @@ func Process(filename string, src []byte, opt *Options) ([]byte, error) {
TabIndent: opt.TabIndent,
TabWidth: opt.TabWidth,
}
+ if Debug {
+ intopt.Env.Logf = log.Printf
+ }
return intimp.Process(filename, src, intopt)
}
diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go
index ce38fdcf83..5901a8f616 100644
--- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go
+++ b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go
@@ -76,8 +76,9 @@ func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) e
}
func parseDirEnt(buf []byte) (consumed int, name string, typ os.FileMode) {
- // golang.org/issue/15653
- dirent := (*syscall.Dirent)(unsafe.Pointer(&buf[0]))
+ // golang.org/issue/37269
+ dirent := &syscall.Dirent{}
+ copy((*[unsafe.Sizeof(syscall.Dirent{})]byte)(unsafe.Pointer(dirent))[:], buf)
if v := unsafe.Offsetof(dirent.Reclen) + unsafe.Sizeof(dirent.Reclen); uintptr(len(buf)) < v {
panic(fmt.Sprintf("buf size of %d smaller than dirent header size %d", len(buf), v))
}
diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
index 75d73e744f..468db40104 100644
--- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go
+++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
@@ -5,6 +5,7 @@ import (
"bytes"
"context"
"fmt"
+ "io"
"os"
"os/exec"
"strings"
@@ -28,9 +29,27 @@ func (i *Invocation) Run(ctx context.Context) (*bytes.Buffer, error) {
return stdout, friendly
}
-// RunRaw is like Run, but also returns the raw stderr and error for callers
+// RunRaw is like RunPiped, but also returns the raw stderr and error for callers
// that want to do low-level error handling/recovery.
func (i *Invocation) RunRaw(ctx context.Context) (stdout *bytes.Buffer, stderr *bytes.Buffer, friendlyError error, rawError error) {
+ stdout = &bytes.Buffer{}
+ stderr = &bytes.Buffer{}
+ rawError = i.RunPiped(ctx, stdout, stderr)
+ if rawError != nil {
+ // Check for 'go' executable not being found.
+ if ee, ok := rawError.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
+ friendlyError = fmt.Errorf("go command required, not found: %v", ee)
+ }
+ if ctx.Err() != nil {
+ friendlyError = ctx.Err()
+ }
+ friendlyError = fmt.Errorf("err: %v: stderr: %s", rawError, stderr)
+ }
+ return
+}
+
+// RunPiped is like Run, but relies on the given stdout/stderr
+func (i *Invocation) RunPiped(ctx context.Context, stdout, stderr io.Writer) error {
log := i.Logf
if log == nil {
log = func(string, ...interface{}) {}
@@ -51,8 +70,6 @@ func (i *Invocation) RunRaw(ctx context.Context) (stdout *bytes.Buffer, stderr *
goArgs = append(goArgs, i.Args...)
}
cmd := exec.Command("go", goArgs...)
- stdout = &bytes.Buffer{}
- stderr = &bytes.Buffer{}
cmd.Stdout = stdout
cmd.Stderr = stderr
// On darwin the cwd gets resolved to the real path, which breaks anything that
@@ -66,19 +83,7 @@ func (i *Invocation) RunRaw(ctx context.Context) (stdout *bytes.Buffer, stderr *
defer func(start time.Time) { log("%s for %v", time.Since(start), cmdDebugStr(cmd)) }(time.Now())
- rawError = runCmdContext(ctx, cmd)
- friendlyError = rawError
- if rawError != nil {
- // Check for 'go' executable not being found.
- if ee, ok := rawError.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
- friendlyError = fmt.Errorf("go command required, not found: %v", ee)
- }
- if ctx.Err() != nil {
- friendlyError = ctx.Err()
- }
- friendlyError = fmt.Errorf("err: %v: stderr: %s", rawError, stderr)
- }
- return
+ return runCmdContext(ctx, cmd)
}
// runCmdContext is like exec.CommandContext except it sends os.Interrupt
diff --git a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go
index 64309db74c..390cb9db79 100644
--- a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go
+++ b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go
@@ -23,8 +23,10 @@ import (
// Options controls the behavior of a Walk call.
type Options struct {
- Debug bool // Enable debug logging
- ModulesEnabled bool // Search module caches. Also disables legacy goimports ignore rules.
+ // If Logf is non-nil, debug logging is enabled through this function.
+ Logf func(format string, args ...interface{})
+ // Search module caches. Also disables legacy goimports ignore rules.
+ ModulesEnabled bool
}
// RootType indicates the type of a Root.
@@ -80,14 +82,14 @@ func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root
// walkDir creates a walker and starts fastwalk with this walker.
func walkDir(root Root, add func(Root, string), skip func(root Root, dir string) bool, opts Options) {
if _, err := os.Stat(root.Path); os.IsNotExist(err) {
- if opts.Debug {
- log.Printf("skipping nonexistent directory: %v", root.Path)
+ if opts.Logf != nil {
+ opts.Logf("skipping nonexistent directory: %v", root.Path)
}
return
}
start := time.Now()
- if opts.Debug {
- log.Printf("gopathwalk: scanning %s", root.Path)
+ if opts.Logf != nil {
+ opts.Logf("gopathwalk: scanning %s", root.Path)
}
w := &walker{
root: root,
@@ -100,8 +102,8 @@ func walkDir(root Root, add func(Root, string), skip func(root Root, dir string)
log.Printf("gopathwalk: scanning directory %v: %v", root.Path, err)
}
- if opts.Debug {
- log.Printf("gopathwalk: scanned %s in %v", root.Path, time.Since(start))
+ if opts.Logf != nil {
+ opts.Logf("gopathwalk: scanned %s in %v", root.Path, time.Since(start))
}
}
@@ -130,11 +132,11 @@ func (w *walker) init() {
full := filepath.Join(w.root.Path, p)
if fi, err := os.Stat(full); err == nil {
w.ignoredDirs = append(w.ignoredDirs, fi)
- if w.opts.Debug {
- log.Printf("Directory added to ignore list: %s", full)
+ if w.opts.Logf != nil {
+ w.opts.Logf("Directory added to ignore list: %s", full)
}
- } else if w.opts.Debug {
- log.Printf("Error statting ignored directory: %v", err)
+ } else if w.opts.Logf != nil {
+ w.opts.Logf("Error statting ignored directory: %v", err)
}
}
}
@@ -145,11 +147,11 @@ func (w *walker) init() {
func (w *walker) getIgnoredDirs(path string) []string {
file := filepath.Join(path, ".goimportsignore")
slurp, err := ioutil.ReadFile(file)
- if w.opts.Debug {
+ if w.opts.Logf != nil {
if err != nil {
- log.Print(err)
+ w.opts.Logf("%v", err)
} else {
- log.Printf("Read %s", file)
+ w.opts.Logf("Read %s", file)
}
}
if err != nil {
diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go
index 5e0c9dff03..92a23439ff 100644
--- a/vendor/golang.org/x/tools/internal/imports/fix.go
+++ b/vendor/golang.org/x/tools/internal/imports/fix.go
@@ -262,7 +262,7 @@ type pass struct {
// loadPackageNames saves the package names for everything referenced by imports.
func (p *pass) loadPackageNames(imports []*ImportInfo) error {
- if p.env.Debug {
+ if p.env.Logf != nil {
p.env.Logf("loading package names for %v packages", len(imports))
defer func() {
p.env.Logf("done loading package names for %v packages", len(imports))
@@ -334,7 +334,7 @@ func (p *pass) load() ([]*ImportFix, bool) {
if p.loadRealPackageNames {
err := p.loadPackageNames(append(imports, p.candidates...))
if err != nil {
- if p.env.Debug {
+ if p.env.Logf != nil {
p.env.Logf("loading package names: %v", err)
}
return nil, false
@@ -528,7 +528,7 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv
return nil, err
}
srcDir := filepath.Dir(abs)
- if env.Debug {
+ if env.Logf != nil {
env.Logf("fixImports(filename=%q), abs=%q, srcDir=%q ...", filename, abs, srcDir)
}
@@ -746,7 +746,6 @@ func getPackageExports(ctx context.Context, wrapped func(PackageExport), searchP
// the go command, the go/build package, etc.
type ProcessEnv struct {
LocalPrefix string
- Debug bool
BuildFlags []string
@@ -755,7 +754,7 @@ type ProcessEnv struct {
GOPATH, GOROOT, GO111MODULE, GOPROXY, GOFLAGS, GOSUMDB string
WorkingDir string
- // Logf is the default logger for the ProcessEnv.
+ // If Logf is non-nil, debug logging is enabled through this function.
Logf func(format string, args ...interface{})
resolver Resolver
@@ -1238,7 +1237,7 @@ func (r *gopathResolver) scan(ctx context.Context, callback *scanCallback) error
case <-r.scanSema:
}
defer func() { r.scanSema <- struct{}{} }()
- gopathwalk.Walk(roots, add, gopathwalk.Options{Debug: r.env.Debug, ModulesEnabled: false})
+ gopathwalk.Walk(roots, add, gopathwalk.Options{Logf: r.env.Logf, ModulesEnabled: false})
close(scanDone)
}()
select {
@@ -1342,7 +1341,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl
}
}
- if env.Debug {
+ if env.Logf != nil {
sortedExports := append([]string(nil), exports...)
sort.Strings(sortedExports)
env.Logf("loaded exports in dir %v (package %v): %v", dir, pkgName, strings.Join(sortedExports, ", "))
@@ -1358,7 +1357,7 @@ func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgNa
// ones. Note that this sorts by the de-vendored name, so
// there's no "penalty" for vendoring.
sort.Sort(byDistanceOrImportPathShortLength(candidates))
- if pass.env.Debug {
+ if pass.env.Logf != nil {
for i, c := range candidates {
pass.env.Logf("%s candidate %d/%d: %v in %v", pkgName, i+1, len(candidates), c.pkg.importPathShort, c.pkg.dir)
}
@@ -1396,14 +1395,14 @@ func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgNa
wg.Done()
}()
- if pass.env.Debug {
+ if pass.env.Logf != nil {
pass.env.Logf("loading exports in dir %s (seeking package %s)", c.pkg.dir, pkgName)
}
// If we're an x_test, load the package under test's test variant.
includeTest := strings.HasSuffix(pass.f.Name.Name, "_test") && c.pkg.dir == pass.srcDir
_, exports, err := pass.env.GetResolver().loadExports(ctx, c.pkg, includeTest)
if err != nil {
- if pass.env.Debug {
+ if pass.env.Logf != nil {
pass.env.Logf("loading exports in dir %s (seeking package %s): %v", c.pkg.dir, pkgName, err)
}
resc <- nil
diff --git a/vendor/golang.org/x/tools/internal/imports/imports.go b/vendor/golang.org/x/tools/internal/imports/imports.go
index 2e7a317e55..b18daea290 100644
--- a/vendor/golang.org/x/tools/internal/imports/imports.go
+++ b/vendor/golang.org/x/tools/internal/imports/imports.go
@@ -21,7 +21,6 @@ import (
"go/token"
"io"
"io/ioutil"
- "log"
"os"
"regexp"
"strconv"
@@ -155,12 +154,6 @@ func initialize(filename string, src []byte, opt *Options) ([]byte, *Options, er
GOSUMDB: os.Getenv("GOSUMDB"),
}
}
-
- // Set the logger if the user has not provided it.
- if opt.Env.Logf == nil {
- opt.Env.Logf = log.Printf
- }
-
if src == nil {
b, err := ioutil.ReadFile(filename)
if err != nil {
diff --git a/vendor/golang.org/x/tools/internal/imports/mod.go b/vendor/golang.org/x/tools/internal/imports/mod.go
index 28d4b1ff33..69e3eecc4c 100644
--- a/vendor/golang.org/x/tools/internal/imports/mod.go
+++ b/vendor/golang.org/x/tools/internal/imports/mod.go
@@ -156,7 +156,7 @@ func (r *ModuleResolver) initAllMods() error {
return err
}
if mod.Dir == "" {
- if r.env.Debug {
+ if r.env.Logf != nil {
r.env.Logf("module %v has not been downloaded and will be ignored", mod.Path)
}
// Can't do anything with a module that's not downloaded.
@@ -470,7 +470,7 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error
if r.scannedRoots[root] {
continue
}
- gopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Debug: r.env.Debug, ModulesEnabled: true})
+ gopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Logf: r.env.Logf, ModulesEnabled: true})
r.scannedRoots[root] = true
}
close(scanDone)
@@ -583,7 +583,7 @@ func (r *ModuleResolver) scanDirForPackage(root gopathwalk.Root, dir string) dir
}
modPath, err := module.UnescapePath(filepath.ToSlash(matches[1]))
if err != nil {
- if r.env.Debug {
+ if r.env.Logf != nil {
r.env.Logf("decoding module cache path %q: %v", subdir, err)
}
return directoryPackageInfo{
diff --git a/vendor/golang.org/x/xerrors/fmt.go b/vendor/golang.org/x/xerrors/fmt.go
index 74c1c93ec9..829862ddf6 100644
--- a/vendor/golang.org/x/xerrors/fmt.go
+++ b/vendor/golang.org/x/xerrors/fmt.go
@@ -7,10 +7,14 @@ package xerrors
import (
"fmt"
"strings"
+ "unicode"
+ "unicode/utf8"
"golang.org/x/xerrors/internal"
)
+const percentBangString = "%!"
+
// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
@@ -18,29 +22,71 @@ import (
// formatted with additional detail enabled. If the last argument is an error
// the returned error's Format method will return it if the format string ends
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
-// format string ends with ": %w", the returned error implements Wrapper
-// with an Unwrap method returning it.
+// format string ends with ": %w", the returned error implements an Unwrap
+// method returning it.
+//
+// If the format specifier includes a %w verb with an error operand in a
+// position other than at the end, the returned error will still implement an
+// Unwrap method returning the operand, but the error's Format method will not
+// return the wrapped error.
+//
+// It is invalid to include more than one %w verb or to supply it with an
+// operand that does not implement the error interface. The %w verb is otherwise
+// a synonym for %v.
func Errorf(format string, a ...interface{}) error {
- err, wrap := lastError(format, a)
format = formatPlusW(format)
- if err == nil {
- return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
+ // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.
+ wrap := strings.HasSuffix(format, ": %w")
+ idx, format2, ok := parsePercentW(format)
+ percentWElsewhere := !wrap && idx >= 0
+ if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) {
+ err := errorAt(a, len(a)-1)
+ if err == nil {
+ return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
+ }
+ // TODO: this is not entirely correct. The error value could be
+ // printed elsewhere in format if it mixes numbered with unnumbered
+ // substitutions. With relatively small changes to doPrintf we can
+ // have it optionally ignore extra arguments and pass the argument
+ // list in its entirety.
+ msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
+ frame := Frame{}
+ if internal.EnableTrace {
+ frame = Caller(1)
+ }
+ if wrap {
+ return &wrapError{msg, err, frame}
+ }
+ return &noWrapError{msg, err, frame}
+ }
+ // Support %w anywhere.
+ // TODO: don't repeat the wrapped error's message when %w occurs in the middle.
+ msg := fmt.Sprintf(format2, a...)
+ if idx < 0 {
+ return &noWrapError{msg, nil, Caller(1)}
+ }
+ err := errorAt(a, idx)
+ if !ok || err == nil {
+ // Too many %ws or argument of %w is not an error. Approximate the Go
+ // 1.13 fmt.Errorf message.
+ return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)}
}
-
- // TODO: this is not entirely correct. The error value could be
- // printed elsewhere in format if it mixes numbered with unnumbered
- // substitutions. With relatively small changes to doPrintf we can
- // have it optionally ignore extra arguments and pass the argument
- // list in its entirety.
- msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
frame := Frame{}
if internal.EnableTrace {
frame = Caller(1)
}
- if wrap {
- return &wrapError{msg, err, frame}
+ return &wrapError{msg, err, frame}
+}
+
+func errorAt(args []interface{}, i int) error {
+ if i < 0 || i >= len(args) {
+ return nil
}
- return &noWrapError{msg, err, frame}
+ err, ok := args[i].(error)
+ if !ok {
+ return nil
+ }
+ return err
}
// formatPlusW is used to avoid the vet check that will barf at %w.
@@ -48,24 +94,56 @@ func formatPlusW(s string) string {
return s
}
-func lastError(format string, a []interface{}) (err error, wrap bool) {
- wrap = strings.HasSuffix(format, ": %w")
- if !wrap &&
- !strings.HasSuffix(format, ": %s") &&
- !strings.HasSuffix(format, ": %v") {
- return nil, false
- }
-
- if len(a) == 0 {
- return nil, false
+// Return the index of the only %w in format, or -1 if none.
+// Also return a rewritten format string with %w replaced by %v, and
+// false if there is more than one %w.
+// TODO: handle "%[N]w".
+func parsePercentW(format string) (idx int, newFormat string, ok bool) {
+ // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.
+ idx = -1
+ ok = true
+ n := 0
+ sz := 0
+ var isW bool
+ for i := 0; i < len(format); i += sz {
+ if format[i] != '%' {
+ sz = 1
+ continue
+ }
+ // "%%" is not a format directive.
+ if i+1 < len(format) && format[i+1] == '%' {
+ sz = 2
+ continue
+ }
+ sz, isW = parsePrintfVerb(format[i:])
+ if isW {
+ if idx >= 0 {
+ ok = false
+ } else {
+ idx = n
+ }
+ // "Replace" the last character, the 'w', with a 'v'.
+ p := i + sz - 1
+ format = format[:p] + "v" + format[p+1:]
+ }
+ n++
}
+ return idx, format, ok
+}
- err, ok := a[len(a)-1].(error)
- if !ok {
- return nil, false
+// Parse the printf verb starting with a % at s[0].
+// Return how many bytes it occupies and whether the verb is 'w'.
+func parsePrintfVerb(s string) (int, bool) {
+ // Assume only that the directive is a sequence of non-letters followed by a single letter.
+ sz := 0
+ var r rune
+ for i := 1; i < len(s); i += sz {
+ r, sz = utf8.DecodeRuneInString(s[i:])
+ if unicode.IsLetter(r) {
+ return i + sz, r == 'w'
+ }
}
-
- return err, wrap
+ return len(s), false
}
type noWrapError struct {