diff options
author | techknowlogick <techknowlogick@gitea.io> | 2022-01-14 18:16:05 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-14 18:16:05 -0500 |
commit | 84145e45c50130922fae9055535ab5ea0378e1d4 (patch) | |
tree | fce077a5ae462840bb876ace79aca42abab29ed7 /vendor/golang.org/x/tools/go | |
parent | 2b16ca7c773de278ba01f122dc6f9f43d7534c52 (diff) | |
download | gitea-84145e45c50130922fae9055535ab5ea0378e1d4.tar.gz gitea-84145e45c50130922fae9055535ab5ea0378e1d4.zip |
Remove golang vendored directory (#18277)
* rm go vendor
* fix drone yaml
* add to gitignore
Diffstat (limited to 'vendor/golang.org/x/tools/go')
43 files changed, 0 insertions, 14608 deletions
diff --git a/vendor/golang.org/x/tools/go/analysis/analysis.go b/vendor/golang.org/x/tools/go/analysis/analysis.go deleted file mode 100644 index d11505a165..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/analysis.go +++ /dev/null @@ -1,242 +0,0 @@ -// 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 analysis - -import ( - "flag" - "fmt" - "go/ast" - "go/token" - "go/types" - "reflect" - - "golang.org/x/tools/internal/analysisinternal" -) - -// 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 } - -func init() { - // Set the analysisinternal functions to be able to pass type errors - // to the Pass type without modifying the go/analysis API. - analysisinternal.SetTypeErrors = func(p interface{}, errors []types.Error) { - p.(*Pass).typeErrors = errors - } - analysisinternal.GetTypeErrors = func(p interface{}) []types.Error { - return p.(*Pass).typeErrors - } -} - -// 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 - IgnoredFiles []string // names of ignored source files in 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 - - // typeErrors contains types.Errors that are associated with the pkg. - typeErrors []types.Error - - /* 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 deleted file mode 100644 index cd462a0cb5..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/diagnostic.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2019 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 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 deleted file mode 100644 index 94a3bd5d07..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/doc.go +++ /dev/null @@ -1,321 +0,0 @@ -// 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 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 - IgnoredFiles []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 IgnoredFiles field provides the names, but not the contents, -of ignored Go and non-Go source files that are not part of this package -with the current build configuration but may be part of other build -configurations. See the "buildtags" analyzer for an example of loading -and checking IgnoredFiles. - -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. - -Many analyses want to associate diagnostics with a severity level. -Because Diagnostic does not have a severity level field, an Analyzer's -diagnostics effectively all have the same severity level. To separate which -diagnostics are high severity and which are low severity, expose multiple -Analyzers instead. Analyzers should also be separated when their -diagnostics belong in different groups, or could be tagged differently -before being shown to the end user. Analyzers should document their severity -level to help downstream tools surface diagnostics properly. - -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 deleted file mode 100644 index 4b7be2d1f5..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go +++ /dev/null @@ -1,388 +0,0 @@ -// 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 marshaling 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 deleted file mode 100644 index ce92892c81..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go +++ /dev/null @@ -1,96 +0,0 @@ -// 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 - -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 deleted file mode 100644 index 1fb69c6159..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/internal/facts/facts.go +++ /dev/null @@ -1,323 +0,0 @@ -// 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 deleted file mode 100644 index 34740f48e0..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/internal/facts/imports.go +++ /dev/null @@ -1,88 +0,0 @@ -// 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 deleted file mode 100644 index 713e1380ef..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go +++ /dev/null @@ -1,398 +0,0 @@ -// 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 - IgnoredFiles []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, - IgnoredFiles: cfg.IgnoredFiles, - 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 deleted file mode 100644 index 9051456e39..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker112.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -// +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 deleted file mode 100644 index 23e57bf02b..0000000000 --- a/vendor/golang.org/x/tools/go/analysis/validate.go +++ /dev/null @@ -1,130 +0,0 @@ -// 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 analysis - -import ( - "fmt" - "reflect" - "strings" - "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 _, req := range a.Requires { - if err := visit(req); err != nil { - return err - } - } - color[a] = black - } - - if color[a] == grey { - stack := []*Analyzer{a} - inCycle := map[string]bool{} - for len(stack) > 0 { - current := stack[len(stack)-1] - stack = stack[:len(stack)-1] - if color[current] == grey && !inCycle[current.Name] { - inCycle[current.Name] = true - stack = append(stack, current.Requires...) - } - } - return &CycleInRequiresGraphError{AnalyzerNames: inCycle} - } - - 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 != "" -} - -type CycleInRequiresGraphError struct { - AnalyzerNames map[string]bool -} - -func (e *CycleInRequiresGraphError) Error() string { - var b strings.Builder - b.WriteString("cycle detected involving the following analyzers:") - for n := range e.AnalyzerNames { - b.WriteByte(' ') - b.WriteString(n) - } - return b.String() -} diff --git a/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go deleted file mode 100644 index 6b7052b892..0000000000 --- a/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ /dev/null @@ -1,627 +0,0 @@ -// Copyright 2013 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 astutil - -// This file defines utilities for working with source positions. - -import ( - "fmt" - "go/ast" - "go/token" - "sort" -) - -// PathEnclosingInterval returns the node that encloses the source -// interval [start, end), and all its ancestors up to the AST root. -// -// The definition of "enclosing" used by this function considers -// additional whitespace abutting a node to be enclosed by it. -// In this example: -// -// z := x + y // add them -// <-A-> -// <----B-----> -// -// the ast.BinaryExpr(+) node is considered to enclose interval B -// even though its [Pos()..End()) is actually only interval A. -// This behaviour makes user interfaces more tolerant of imperfect -// input. -// -// This function treats tokens as nodes, though they are not included -// in the result. e.g. PathEnclosingInterval("+") returns the -// enclosing ast.BinaryExpr("x + y"). -// -// If start==end, the 1-char interval following start is used instead. -// -// The 'exact' result is true if the interval contains only path[0] -// and perhaps some adjacent whitespace. It is false if the interval -// overlaps multiple children of path[0], or if it contains only -// interior whitespace of path[0]. -// In this example: -// -// z := x + y // add them -// <--C--> <---E--> -// ^ -// D -// -// intervals C, D and E are inexact. C is contained by the -// z-assignment statement, because it spans three of its children (:=, -// x, +). So too is the 1-char interval D, because it contains only -// interior whitespace of the assignment. E is considered interior -// whitespace of the BlockStmt containing the assignment. -// -// Precondition: [start, end) both lie within the same file as root. -// TODO(adonovan): return (nil, false) in this case and remove precond. -// Requires FileSet; see loader.tokenFileContainsPos. -// -// Postcondition: path is never nil; it always contains at least 'root'. -// -func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) { - // fmt.Printf("EnclosingInterval %d %d\n", start, end) // debugging - - // Precondition: node.[Pos..End) and adjoining whitespace contain [start, end). - var visit func(node ast.Node) bool - visit = func(node ast.Node) bool { - path = append(path, node) - - nodePos := node.Pos() - nodeEnd := node.End() - - // fmt.Printf("visit(%T, %d, %d)\n", node, nodePos, nodeEnd) // debugging - - // Intersect [start, end) with interval of node. - if start < nodePos { - start = nodePos - } - if end > nodeEnd { - end = nodeEnd - } - - // Find sole child that contains [start, end). - children := childrenOf(node) - l := len(children) - for i, child := range children { - // [childPos, childEnd) is unaugmented interval of child. - childPos := child.Pos() - childEnd := child.End() - - // [augPos, augEnd) is whitespace-augmented interval of child. - augPos := childPos - augEnd := childEnd - if i > 0 { - augPos = children[i-1].End() // start of preceding whitespace - } - if i < l-1 { - nextChildPos := children[i+1].Pos() - // Does [start, end) lie between child and next child? - if start >= augEnd && end <= nextChildPos { - return false // inexact match - } - augEnd = nextChildPos // end of following whitespace - } - - // fmt.Printf("\tchild %d: [%d..%d)\tcontains interval [%d..%d)?\n", - // i, augPos, augEnd, start, end) // debugging - - // Does augmented child strictly contain [start, end)? - if augPos <= start && end <= augEnd { - _, isToken := child.(tokenNode) - return isToken || visit(child) - } - - // Does [start, end) overlap multiple children? - // i.e. left-augmented child contains start - // but LR-augmented child does not contain end. - if start < childEnd && end > augEnd { - break - } - } - - // No single child contained [start, end), - // so node is the result. Is it exact? - - // (It's tempting to put this condition before the - // child loop, but it gives the wrong result in the - // case where a node (e.g. ExprStmt) and its sole - // child have equal intervals.) - if start == nodePos && end == nodeEnd { - return true // exact match - } - - return false // inexact: overlaps multiple children - } - - if start > end { - start, end = end, start - } - - if start < root.End() && end > root.Pos() { - if start == end { - end = start + 1 // empty interval => interval of size 1 - } - exact = visit(root) - - // Reverse the path: - for i, l := 0, len(path); i < l/2; i++ { - path[i], path[l-1-i] = path[l-1-i], path[i] - } - } else { - // Selection lies within whitespace preceding the - // first (or following the last) declaration in the file. - // The result nonetheless always includes the ast.File. - path = append(path, root) - } - - return -} - -// tokenNode is a dummy implementation of ast.Node for a single token. -// They are used transiently by PathEnclosingInterval but never escape -// this package. -// -type tokenNode struct { - pos token.Pos - end token.Pos -} - -func (n tokenNode) Pos() token.Pos { - return n.pos -} - -func (n tokenNode) End() token.Pos { - return n.end -} - -func tok(pos token.Pos, len int) ast.Node { - return tokenNode{pos, pos + token.Pos(len)} -} - -// childrenOf returns the direct non-nil children of ast.Node n. -// It may include fake ast.Node implementations for bare tokens. -// it is not safe to call (e.g.) ast.Walk on such nodes. -// -func childrenOf(n ast.Node) []ast.Node { - var children []ast.Node - - // First add nodes for all true subtrees. - ast.Inspect(n, func(node ast.Node) bool { - if node == n { // push n - return true // recur - } - if node != nil { // push child - children = append(children, node) - } - return false // no recursion - }) - - // Then add fake Nodes for bare tokens. - switch n := n.(type) { - case *ast.ArrayType: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Elt.End(), len("]"))) - - case *ast.AssignStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.BasicLit: - children = append(children, - tok(n.ValuePos, len(n.Value))) - - case *ast.BinaryExpr: - children = append(children, tok(n.OpPos, len(n.Op.String()))) - - case *ast.BlockStmt: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("}"))) - - case *ast.BranchStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.CallExpr: - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - if n.Ellipsis != 0 { - children = append(children, tok(n.Ellipsis, len("..."))) - } - - case *ast.CaseClause: - if n.List == nil { - children = append(children, - tok(n.Case, len("default"))) - } else { - children = append(children, - tok(n.Case, len("case"))) - } - children = append(children, tok(n.Colon, len(":"))) - - case *ast.ChanType: - switch n.Dir { - case ast.RECV: - children = append(children, tok(n.Begin, len("<-chan"))) - case ast.SEND: - children = append(children, tok(n.Begin, len("chan<-"))) - case ast.RECV | ast.SEND: - children = append(children, tok(n.Begin, len("chan"))) - } - - case *ast.CommClause: - if n.Comm == nil { - children = append(children, - tok(n.Case, len("default"))) - } else { - children = append(children, - tok(n.Case, len("case"))) - } - children = append(children, tok(n.Colon, len(":"))) - - case *ast.Comment: - // nop - - case *ast.CommentGroup: - // nop - - case *ast.CompositeLit: - children = append(children, - tok(n.Lbrace, len("{")), - tok(n.Rbrace, len("{"))) - - case *ast.DeclStmt: - // nop - - case *ast.DeferStmt: - children = append(children, - tok(n.Defer, len("defer"))) - - case *ast.Ellipsis: - children = append(children, - tok(n.Ellipsis, len("..."))) - - case *ast.EmptyStmt: - // nop - - case *ast.ExprStmt: - // nop - - case *ast.Field: - // TODO(adonovan): Field.{Doc,Comment,Tag}? - - case *ast.FieldList: - children = append(children, - tok(n.Opening, len("(")), - tok(n.Closing, len(")"))) - - case *ast.File: - // TODO test: Doc - children = append(children, - tok(n.Package, len("package"))) - - case *ast.ForStmt: - children = append(children, - tok(n.For, len("for"))) - - case *ast.FuncDecl: - // TODO(adonovan): FuncDecl.Comment? - - // Uniquely, FuncDecl breaks the invariant that - // preorder traversal yields tokens in lexical order: - // in fact, FuncDecl.Recv precedes FuncDecl.Type.Func. - // - // As a workaround, we inline the case for FuncType - // here and order things correctly. - // - children = nil // discard ast.Walk(FuncDecl) info subtrees - children = append(children, tok(n.Type.Func, len("func"))) - if n.Recv != nil { - children = append(children, n.Recv) - } - children = append(children, n.Name) - if n.Type.Params != nil { - children = append(children, n.Type.Params) - } - if n.Type.Results != nil { - children = append(children, n.Type.Results) - } - if n.Body != nil { - children = append(children, n.Body) - } - - case *ast.FuncLit: - // nop - - case *ast.FuncType: - if n.Func != 0 { - children = append(children, - tok(n.Func, len("func"))) - } - - case *ast.GenDecl: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - if n.Lparen != 0 { - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - } - - case *ast.GoStmt: - children = append(children, - tok(n.Go, len("go"))) - - case *ast.Ident: - children = append(children, - tok(n.NamePos, len(n.Name))) - - case *ast.IfStmt: - children = append(children, - tok(n.If, len("if"))) - - case *ast.ImportSpec: - // TODO(adonovan): ImportSpec.{Doc,EndPos}? - - case *ast.IncDecStmt: - children = append(children, - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.IndexExpr: - children = append(children, - tok(n.Lbrack, len("{")), - tok(n.Rbrack, len("}"))) - - case *ast.InterfaceType: - children = append(children, - tok(n.Interface, len("interface"))) - - case *ast.KeyValueExpr: - children = append(children, - tok(n.Colon, len(":"))) - - case *ast.LabeledStmt: - children = append(children, - tok(n.Colon, len(":"))) - - case *ast.MapType: - children = append(children, - tok(n.Map, len("map"))) - - case *ast.ParenExpr: - children = append(children, - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - - case *ast.RangeStmt: - children = append(children, - tok(n.For, len("for")), - tok(n.TokPos, len(n.Tok.String()))) - - case *ast.ReturnStmt: - children = append(children, - tok(n.Return, len("return"))) - - case *ast.SelectStmt: - children = append(children, - tok(n.Select, len("select"))) - - case *ast.SelectorExpr: - // nop - - case *ast.SendStmt: - children = append(children, - tok(n.Arrow, len("<-"))) - - case *ast.SliceExpr: - children = append(children, - tok(n.Lbrack, len("[")), - tok(n.Rbrack, len("]"))) - - case *ast.StarExpr: - children = append(children, tok(n.Star, len("*"))) - - case *ast.StructType: - children = append(children, tok(n.Struct, len("struct"))) - - case *ast.SwitchStmt: - children = append(children, tok(n.Switch, len("switch"))) - - case *ast.TypeAssertExpr: - children = append(children, - tok(n.Lparen-1, len(".")), - tok(n.Lparen, len("(")), - tok(n.Rparen, len(")"))) - - case *ast.TypeSpec: - // TODO(adonovan): TypeSpec.{Doc,Comment}? - - case *ast.TypeSwitchStmt: - children = append(children, tok(n.Switch, len("switch"))) - - case *ast.UnaryExpr: - children = append(children, tok(n.OpPos, len(n.Op.String()))) - - case *ast.ValueSpec: - // TODO(adonovan): ValueSpec.{Doc,Comment}? - - case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt: - // nop - } - - // TODO(adonovan): opt: merge the logic of ast.Inspect() into - // the switch above so we can make interleaved callbacks for - // both Nodes and Tokens in the right order and avoid the need - // to sort. - sort.Sort(byPos(children)) - - return children -} - -type byPos []ast.Node - -func (sl byPos) Len() int { - return len(sl) -} -func (sl byPos) Less(i, j int) bool { - return sl[i].Pos() < sl[j].Pos() -} -func (sl byPos) Swap(i, j int) { - sl[i], sl[j] = sl[j], sl[i] -} - -// NodeDescription returns a description of the concrete type of n suitable -// for a user interface. -// -// TODO(adonovan): in some cases (e.g. Field, FieldList, Ident, -// StarExpr) we could be much more specific given the path to the AST -// root. Perhaps we should do that. -// -func NodeDescription(n ast.Node) string { - switch n := n.(type) { - case *ast.ArrayType: - return "array type" - case *ast.AssignStmt: - return "assignment" - case *ast.BadDecl: - return "bad declaration" - case *ast.BadExpr: - return "bad expression" - case *ast.BadStmt: - return "bad statement" - case *ast.BasicLit: - return "basic literal" - case *ast.BinaryExpr: - return fmt.Sprintf("binary %s operation", n.Op) - case *ast.BlockStmt: - return "block" - case *ast.BranchStmt: - switch n.Tok { - case token.BREAK: - return "break statement" - case token.CONTINUE: - return "continue statement" - case token.GOTO: - return "goto statement" - case token.FALLTHROUGH: - return "fall-through statement" - } - case *ast.CallExpr: - if len(n.Args) == 1 && !n.Ellipsis.IsValid() { - return "function call (or conversion)" - } - return "function call" - case *ast.CaseClause: - return "case clause" - case *ast.ChanType: - return "channel type" - case *ast.CommClause: - return "communication clause" - case *ast.Comment: - return "comment" - case *ast.CommentGroup: - return "comment group" - case *ast.CompositeLit: - return "composite literal" - case *ast.DeclStmt: - return NodeDescription(n.Decl) + " statement" - case *ast.DeferStmt: - return "defer statement" - case *ast.Ellipsis: - return "ellipsis" - case *ast.EmptyStmt: - return "empty statement" - case *ast.ExprStmt: - return "expression statement" - case *ast.Field: - // Can be any of these: - // struct {x, y int} -- struct field(s) - // struct {T} -- anon struct field - // interface {I} -- interface embedding - // interface {f()} -- interface method - // func (A) func(B) C -- receiver, param(s), result(s) - return "field/method/parameter" - case *ast.FieldList: - return "field/method/parameter list" - case *ast.File: - return "source file" - case *ast.ForStmt: - return "for loop" - case *ast.FuncDecl: - return "function declaration" - case *ast.FuncLit: - return "function literal" - case *ast.FuncType: - return "function type" - case *ast.GenDecl: - switch n.Tok { - case token.IMPORT: - return "import declaration" - case token.CONST: - return "constant declaration" - case token.TYPE: - return "type declaration" - case token.VAR: - return "variable declaration" - } - case *ast.GoStmt: - return "go statement" - case *ast.Ident: - return "identifier" - case *ast.IfStmt: - return "if statement" - case *ast.ImportSpec: - return "import specification" - case *ast.IncDecStmt: - if n.Tok == token.INC { - return "increment statement" - } - return "decrement statement" - case *ast.IndexExpr: - return "index expression" - case *ast.InterfaceType: - return "interface type" - case *ast.KeyValueExpr: - return "key/value association" - case *ast.LabeledStmt: - return "statement label" - case *ast.MapType: - return "map type" - case *ast.Package: - return "package" - case *ast.ParenExpr: - return "parenthesized " + NodeDescription(n.X) - case *ast.RangeStmt: - return "range loop" - case *ast.ReturnStmt: - return "return statement" - case *ast.SelectStmt: - return "select statement" - case *ast.SelectorExpr: - return "selector" - case *ast.SendStmt: - return "channel send" - case *ast.SliceExpr: - return "slice expression" - case *ast.StarExpr: - return "*-operation" // load/store expr or pointer type - case *ast.StructType: - return "struct type" - case *ast.SwitchStmt: - return "switch statement" - case *ast.TypeAssertExpr: - return "type assertion" - case *ast.TypeSpec: - return "type specification" - case *ast.TypeSwitchStmt: - return "type switch" - case *ast.UnaryExpr: - return fmt.Sprintf("unary %s operation", n.Op) - case *ast.ValueSpec: - return "value specification" - - } - panic(fmt.Sprintf("unexpected node type: %T", n)) -} diff --git a/vendor/golang.org/x/tools/go/ast/astutil/imports.go b/vendor/golang.org/x/tools/go/ast/astutil/imports.go deleted file mode 100644 index 2087ceec9c..0000000000 --- a/vendor/golang.org/x/tools/go/ast/astutil/imports.go +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright 2013 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 astutil contains common utilities for working with the Go AST. -package astutil // import "golang.org/x/tools/go/ast/astutil" - -import ( - "fmt" - "go/ast" - "go/token" - "strconv" - "strings" -) - -// AddImport adds the import path to the file f, if absent. -func AddImport(fset *token.FileSet, f *ast.File, path string) (added bool) { - return AddNamedImport(fset, f, "", path) -} - -// AddNamedImport adds the import with the given name and path to the file f, if absent. -// If name is not empty, it is used to rename the import. -// -// For example, calling -// AddNamedImport(fset, f, "pathpkg", "path") -// adds -// import pathpkg "path" -func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added bool) { - if imports(f, name, path) { - return false - } - - newImport := &ast.ImportSpec{ - Path: &ast.BasicLit{ - Kind: token.STRING, - Value: strconv.Quote(path), - }, - } - if name != "" { - newImport.Name = &ast.Ident{Name: name} - } - - // Find an import decl to add to. - // The goal is to find an existing import - // whose import path has the longest shared - // prefix with path. - var ( - bestMatch = -1 // length of longest shared prefix - lastImport = -1 // index in f.Decls of the file's final import decl - impDecl *ast.GenDecl // import decl containing the best match - impIndex = -1 // spec index in impDecl containing the best match - - isThirdPartyPath = isThirdParty(path) - ) - for i, decl := range f.Decls { - gen, ok := decl.(*ast.GenDecl) - if ok && gen.Tok == token.IMPORT { - lastImport = i - // Do not add to import "C", to avoid disrupting the - // association with its doc comment, breaking cgo. - if declImports(gen, "C") { - continue - } - - // Match an empty import decl if that's all that is available. - if len(gen.Specs) == 0 && bestMatch == -1 { - impDecl = gen - } - - // Compute longest shared prefix with imports in this group and find best - // matched import spec. - // 1. Always prefer import spec with longest shared prefix. - // 2. While match length is 0, - // - for stdlib package: prefer first import spec. - // - for third party package: prefer first third party import spec. - // We cannot use last import spec as best match for third party package - // because grouped imports are usually placed last by goimports -local - // flag. - // See issue #19190. - seenAnyThirdParty := false - for j, spec := range gen.Specs { - impspec := spec.(*ast.ImportSpec) - p := importPath(impspec) - n := matchLen(p, path) - if n > bestMatch || (bestMatch == 0 && !seenAnyThirdParty && isThirdPartyPath) { - bestMatch = n - impDecl = gen - impIndex = j - } - seenAnyThirdParty = seenAnyThirdParty || isThirdParty(p) - } - } - } - - // If no import decl found, add one after the last import. - if impDecl == nil { - impDecl = &ast.GenDecl{ - Tok: token.IMPORT, - } - if lastImport >= 0 { - impDecl.TokPos = f.Decls[lastImport].End() - } else { - // There are no existing imports. - // Our new import, preceded by a blank line, goes after the package declaration - // and after the comment, if any, that starts on the same line as the - // package declaration. - impDecl.TokPos = f.Package - - file := fset.File(f.Package) - pkgLine := file.Line(f.Package) - for _, c := range f.Comments { - if file.Line(c.Pos()) > pkgLine { - break - } - // +2 for a blank line - impDecl.TokPos = c.End() + 2 - } - } - f.Decls = append(f.Decls, nil) - copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:]) - f.Decls[lastImport+1] = impDecl - } - - // Insert new import at insertAt. - insertAt := 0 - if impIndex >= 0 { - // insert after the found import - insertAt = impIndex + 1 - } - impDecl.Specs = append(impDecl.Specs, nil) - copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:]) - impDecl.Specs[insertAt] = newImport - pos := impDecl.Pos() - if insertAt > 0 { - // If there is a comment after an existing import, preserve the comment - // position by adding the new import after the comment. - if spec, ok := impDecl.Specs[insertAt-1].(*ast.ImportSpec); ok && spec.Comment != nil { - pos = spec.Comment.End() - } else { - // Assign same position as the previous import, - // so that the sorter sees it as being in the same block. - pos = impDecl.Specs[insertAt-1].Pos() - } - } - if newImport.Name != nil { - newImport.Name.NamePos = pos - } - newImport.Path.ValuePos = pos - newImport.EndPos = pos - - // Clean up parens. impDecl contains at least one spec. - if len(impDecl.Specs) == 1 { - // Remove unneeded parens. - impDecl.Lparen = token.NoPos - } else if !impDecl.Lparen.IsValid() { - // impDecl needs parens added. - impDecl.Lparen = impDecl.Specs[0].Pos() - } - - f.Imports = append(f.Imports, newImport) - - if len(f.Decls) <= 1 { - return true - } - - // Merge all the import declarations into the first one. - var first *ast.GenDecl - for i := 0; i < len(f.Decls); i++ { - decl := f.Decls[i] - gen, ok := decl.(*ast.GenDecl) - if !ok || gen.Tok != token.IMPORT || declImports(gen, "C") { - continue - } - if first == nil { - first = gen - continue // Don't touch the first one. - } - // We now know there is more than one package in this import - // declaration. Ensure that it ends up parenthesized. - first.Lparen = first.Pos() - // Move the imports of the other import declaration to the first one. - for _, spec := range gen.Specs { - spec.(*ast.ImportSpec).Path.ValuePos = first.Pos() - first.Specs = append(first.Specs, spec) - } - f.Decls = append(f.Decls[:i], f.Decls[i+1:]...) - i-- - } - - return true -} - -func isThirdParty(importPath string) bool { - // Third party package import path usually contains "." (".com", ".org", ...) - // This logic is taken from golang.org/x/tools/imports package. - return strings.Contains(importPath, ".") -} - -// DeleteImport deletes the import path from the file f, if present. -// If there are duplicate import declarations, all matching ones are deleted. -func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) { - return DeleteNamedImport(fset, f, "", path) -} - -// DeleteNamedImport deletes the import with the given name and path from the file f, if present. -// If there are duplicate import declarations, all matching ones are deleted. -func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) { - var delspecs []*ast.ImportSpec - var delcomments []*ast.CommentGroup - - // Find the import nodes that import path, if any. - for i := 0; i < len(f.Decls); i++ { - decl := f.Decls[i] - gen, ok := decl.(*ast.GenDecl) - if !ok || gen.Tok != token.IMPORT { - continue - } - for j := 0; j < len(gen.Specs); j++ { - spec := gen.Specs[j] - impspec := spec.(*ast.ImportSpec) - if importName(impspec) != name || importPath(impspec) != path { - continue - } - - // We found an import spec that imports path. - // Delete it. - delspecs = append(delspecs, impspec) - deleted = true - copy(gen.Specs[j:], gen.Specs[j+1:]) - gen.Specs = gen.Specs[:len(gen.Specs)-1] - - // If this was the last import spec in this decl, - // delete the decl, too. - if len(gen.Specs) == 0 { - copy(f.Decls[i:], f.Decls[i+1:]) - f.Decls = f.Decls[:len(f.Decls)-1] - i-- - break - } else if len(gen.Specs) == 1 { - if impspec.Doc != nil { - delcomments = append(delcomments, impspec.Doc) - } - if impspec.Comment != nil { - delcomments = append(delcomments, impspec.Comment) - } - for _, cg := range f.Comments { - // Found comment on the same line as the import spec. - if cg.End() < impspec.Pos() && fset.Position(cg.End()).Line == fset.Position(impspec.Pos()).Line { - delcomments = append(delcomments, cg) - break - } - } - - spec := gen.Specs[0].(*ast.ImportSpec) - - // Move the documentation right after the import decl. - if spec.Doc != nil { - for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Doc.Pos()).Line { - fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) - } - } - for _, cg := range f.Comments { - if cg.End() < spec.Pos() && fset.Position(cg.End()).Line == fset.Position(spec.Pos()).Line { - for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Pos()).Line { - fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) - } - break - } - } - } - if j > 0 { - lastImpspec := gen.Specs[j-1].(*ast.ImportSpec) - lastLine := fset.Position(lastImpspec.Path.ValuePos).Line - line := fset.Position(impspec.Path.ValuePos).Line - - // We deleted an entry but now there may be - // a blank line-sized hole where the import was. - if line-lastLine > 1 || !gen.Rparen.IsValid() { - // There was a blank line immediately preceding the deleted import, - // so there's no need to close the hole. The right parenthesis is - // invalid after AddImport to an import statement without parenthesis. - // Do nothing. - } else if line != fset.File(gen.Rparen).LineCount() { - // There was no blank line. Close the hole. - fset.File(gen.Rparen).MergeLine(line) - } - } - j-- - } - } - - // Delete imports from f.Imports. - for i := 0; i < len(f.Imports); i++ { - imp := f.Imports[i] - for j, del := range delspecs { - if imp == del { - copy(f.Imports[i:], f.Imports[i+1:]) - f.Imports = f.Imports[:len(f.Imports)-1] - copy(delspecs[j:], delspecs[j+1:]) - delspecs = delspecs[:len(delspecs)-1] - i-- - break - } - } - } - - // Delete comments from f.Comments. - for i := 0; i < len(f.Comments); i++ { - cg := f.Comments[i] - for j, del := range delcomments { - if cg == del { - copy(f.Comments[i:], f.Comments[i+1:]) - f.Comments = f.Comments[:len(f.Comments)-1] - copy(delcomments[j:], delcomments[j+1:]) - delcomments = delcomments[:len(delcomments)-1] - i-- - break - } - } - } - - if len(delspecs) > 0 { - panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs)) - } - - return -} - -// RewriteImport rewrites any import of path oldPath to path newPath. -func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) { - for _, imp := range f.Imports { - if importPath(imp) == oldPath { - rewrote = true - // record old End, because the default is to compute - // it using the length of imp.Path.Value. - imp.EndPos = imp.End() - imp.Path.Value = strconv.Quote(newPath) - } - } - return -} - -// UsesImport reports whether a given import is used. -func UsesImport(f *ast.File, path string) (used bool) { - spec := importSpec(f, path) - if spec == nil { - return - } - - name := spec.Name.String() - switch name { - case "<nil>": - // If the package name is not explicitly specified, - // make an educated guess. This is not guaranteed to be correct. - lastSlash := strings.LastIndex(path, "/") - if lastSlash == -1 { - name = path - } else { - name = path[lastSlash+1:] - } - case "_", ".": - // Not sure if this import is used - err on the side of caution. - return true - } - - ast.Walk(visitFn(func(n ast.Node) { - sel, ok := n.(*ast.SelectorExpr) - if ok && isTopName(sel.X, name) { - used = true - } - }), f) - - return -} - -type visitFn func(node ast.Node) - -func (fn visitFn) Visit(node ast.Node) ast.Visitor { - fn(node) - return fn -} - -// imports reports whether f has an import with the specified name and path. -func imports(f *ast.File, name, path string) bool { - for _, s := range f.Imports { - if importName(s) == name && importPath(s) == path { - return true - } - } - return false -} - -// importSpec returns the import spec if f imports path, -// or nil otherwise. -func importSpec(f *ast.File, path string) *ast.ImportSpec { - for _, s := range f.Imports { - if importPath(s) == path { - return s - } - } - return nil -} - -// importName returns the name of s, -// or "" if the import is not named. -func importName(s *ast.ImportSpec) string { - if s.Name == nil { - return "" - } - return s.Name.Name -} - -// importPath returns the unquoted import path of s, -// or "" if the path is not properly quoted. -func importPath(s *ast.ImportSpec) string { - t, err := strconv.Unquote(s.Path.Value) - if err != nil { - return "" - } - return t -} - -// declImports reports whether gen contains an import of path. -func declImports(gen *ast.GenDecl, path string) bool { - if gen.Tok != token.IMPORT { - return false - } - for _, spec := range gen.Specs { - impspec := spec.(*ast.ImportSpec) - if importPath(impspec) == path { - return true - } - } - return false -} - -// matchLen returns the length of the longest path segment prefix shared by x and y. -func matchLen(x, y string) int { - n := 0 - for i := 0; i < len(x) && i < len(y) && x[i] == y[i]; i++ { - if x[i] == '/' { - n++ - } - } - return n -} - -// isTopName returns true if n is a top-level unresolved identifier with the given name. -func isTopName(n ast.Expr, name string) bool { - id, ok := n.(*ast.Ident) - return ok && id.Name == name && id.Obj == nil -} - -// Imports returns the file imports grouped by paragraph. -func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec { - var groups [][]*ast.ImportSpec - - for _, decl := range f.Decls { - genDecl, ok := decl.(*ast.GenDecl) - if !ok || genDecl.Tok != token.IMPORT { - break - } - - group := []*ast.ImportSpec{} - - var lastLine int - for _, spec := range genDecl.Specs { - importSpec := spec.(*ast.ImportSpec) - pos := importSpec.Path.ValuePos - line := fset.Position(pos).Line - if lastLine > 0 && pos > 0 && line-lastLine > 1 { - groups = append(groups, group) - group = []*ast.ImportSpec{} - } - group = append(group, importSpec) - lastLine = line - } - groups = append(groups, group) - } - - return groups -} diff --git a/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go deleted file mode 100644 index cf72ea990b..0000000000 --- a/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ /dev/null @@ -1,477 +0,0 @@ -// Copyright 2017 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 astutil - -import ( - "fmt" - "go/ast" - "reflect" - "sort" -) - -// An ApplyFunc is invoked by Apply for each node n, even if n is nil, -// before and/or after the node's children, using a Cursor describing -// the current node and providing operations on it. -// -// The return value of ApplyFunc controls the syntax tree traversal. -// See Apply for details. -type ApplyFunc func(*Cursor) bool - -// Apply traverses a syntax tree recursively, starting with root, -// and calling pre and post for each node as described below. -// Apply returns the syntax tree, possibly modified. -// -// If pre is not nil, it is called for each node before the node's -// children are traversed (pre-order). If pre returns false, no -// children are traversed, and post is not called for that node. -// -// If post is not nil, and a prior call of pre didn't return false, -// post is called for each node after its children are traversed -// (post-order). If post returns false, traversal is terminated and -// Apply returns immediately. -// -// Only fields that refer to AST nodes are considered children; -// i.e., token.Pos, Scopes, Objects, and fields of basic types -// (strings, etc.) are ignored. -// -// Children are traversed in the order in which they appear in the -// respective node's struct definition. A package's files are -// traversed in the filenames' alphabetical order. -// -func Apply(root ast.Node, pre, post ApplyFunc) (result ast.Node) { - parent := &struct{ ast.Node }{root} - defer func() { - if r := recover(); r != nil && r != abort { - panic(r) - } - result = parent.Node - }() - a := &application{pre: pre, post: post} - a.apply(parent, "Node", nil, root) - return -} - -var abort = new(int) // singleton, to signal termination of Apply - -// A Cursor describes a node encountered during Apply. -// Information about the node and its parent is available -// from the Node, Parent, Name, and Index methods. -// -// If p is a variable of type and value of the current parent node -// c.Parent(), and f is the field identifier with name c.Name(), -// the following invariants hold: -// -// p.f == c.Node() if c.Index() < 0 -// p.f[c.Index()] == c.Node() if c.Index() >= 0 -// -// The methods Replace, Delete, InsertBefore, and InsertAfter -// can be used to change the AST without disrupting Apply. -type Cursor struct { - parent ast.Node - name string - iter *iterator // valid if non-nil - node ast.Node -} - -// Node returns the current Node. -func (c *Cursor) Node() ast.Node { return c.node } - -// Parent returns the parent of the current Node. -func (c *Cursor) Parent() ast.Node { return c.parent } - -// Name returns the name of the parent Node field that contains the current Node. -// If the parent is a *ast.Package and the current Node is a *ast.File, Name returns -// the filename for the current Node. -func (c *Cursor) Name() string { return c.name } - -// Index reports the index >= 0 of the current Node in the slice of Nodes that -// contains it, or a value < 0 if the current Node is not part of a slice. -// The index of the current node changes if InsertBefore is called while -// processing the current node. -func (c *Cursor) Index() int { - if c.iter != nil { - return c.iter.index - } - return -1 -} - -// field returns the current node's parent field value. -func (c *Cursor) field() reflect.Value { - return reflect.Indirect(reflect.ValueOf(c.parent)).FieldByName(c.name) -} - -// Replace replaces the current Node with n. -// The replacement node is not walked by Apply. -func (c *Cursor) Replace(n ast.Node) { - if _, ok := c.node.(*ast.File); ok { - file, ok := n.(*ast.File) - if !ok { - panic("attempt to replace *ast.File with non-*ast.File") - } - c.parent.(*ast.Package).Files[c.name] = file - return - } - - v := c.field() - if i := c.Index(); i >= 0 { - v = v.Index(i) - } - v.Set(reflect.ValueOf(n)) -} - -// Delete deletes the current Node from its containing slice. -// If the current Node is not part of a slice, Delete panics. -// As a special case, if the current node is a package file, -// Delete removes it from the package's Files map. -func (c *Cursor) Delete() { - if _, ok := c.node.(*ast.File); ok { - delete(c.parent.(*ast.Package).Files, c.name) - return - } - - i := c.Index() - if i < 0 { - panic("Delete node not contained in slice") - } - v := c.field() - l := v.Len() - reflect.Copy(v.Slice(i, l), v.Slice(i+1, l)) - v.Index(l - 1).Set(reflect.Zero(v.Type().Elem())) - v.SetLen(l - 1) - c.iter.step-- -} - -// InsertAfter inserts n after the current Node in its containing slice. -// If the current Node is not part of a slice, InsertAfter panics. -// Apply does not walk n. -func (c *Cursor) InsertAfter(n ast.Node) { - i := c.Index() - if i < 0 { - panic("InsertAfter node not contained in slice") - } - v := c.field() - v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) - l := v.Len() - reflect.Copy(v.Slice(i+2, l), v.Slice(i+1, l)) - v.Index(i + 1).Set(reflect.ValueOf(n)) - c.iter.step++ -} - -// InsertBefore inserts n before the current Node in its containing slice. -// If the current Node is not part of a slice, InsertBefore panics. -// Apply will not walk n. -func (c *Cursor) InsertBefore(n ast.Node) { - i := c.Index() - if i < 0 { - panic("InsertBefore node not contained in slice") - } - v := c.field() - v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) - l := v.Len() - reflect.Copy(v.Slice(i+1, l), v.Slice(i, l)) - v.Index(i).Set(reflect.ValueOf(n)) - c.iter.index++ -} - -// application carries all the shared data so we can pass it around cheaply. -type application struct { - pre, post ApplyFunc - cursor Cursor - iter iterator -} - -func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.Node) { - // convert typed nil into untyped nil - if v := reflect.ValueOf(n); v.Kind() == reflect.Ptr && v.IsNil() { - n = nil - } - - // avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead - saved := a.cursor - a.cursor.parent = parent - a.cursor.name = name - a.cursor.iter = iter - a.cursor.node = n - - if a.pre != nil && !a.pre(&a.cursor) { - a.cursor = saved - return - } - - // walk children - // (the order of the cases matches the order of the corresponding node types in go/ast) - switch n := n.(type) { - case nil: - // nothing to do - - // Comments and fields - case *ast.Comment: - // nothing to do - - case *ast.CommentGroup: - if n != nil { - a.applyList(n, "List") - } - - case *ast.Field: - a.apply(n, "Doc", nil, n.Doc) - a.applyList(n, "Names") - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Tag", nil, n.Tag) - a.apply(n, "Comment", nil, n.Comment) - - case *ast.FieldList: - a.applyList(n, "List") - - // Expressions - case *ast.BadExpr, *ast.Ident, *ast.BasicLit: - // nothing to do - - case *ast.Ellipsis: - a.apply(n, "Elt", nil, n.Elt) - - case *ast.FuncLit: - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Body", nil, n.Body) - - case *ast.CompositeLit: - a.apply(n, "Type", nil, n.Type) - a.applyList(n, "Elts") - - case *ast.ParenExpr: - a.apply(n, "X", nil, n.X) - - case *ast.SelectorExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Sel", nil, n.Sel) - - case *ast.IndexExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Index", nil, n.Index) - - case *ast.SliceExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Low", nil, n.Low) - a.apply(n, "High", nil, n.High) - a.apply(n, "Max", nil, n.Max) - - case *ast.TypeAssertExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Type", nil, n.Type) - - case *ast.CallExpr: - a.apply(n, "Fun", nil, n.Fun) - a.applyList(n, "Args") - - case *ast.StarExpr: - a.apply(n, "X", nil, n.X) - - case *ast.UnaryExpr: - a.apply(n, "X", nil, n.X) - - case *ast.BinaryExpr: - a.apply(n, "X", nil, n.X) - a.apply(n, "Y", nil, n.Y) - - case *ast.KeyValueExpr: - a.apply(n, "Key", nil, n.Key) - a.apply(n, "Value", nil, n.Value) - - // Types - case *ast.ArrayType: - a.apply(n, "Len", nil, n.Len) - a.apply(n, "Elt", nil, n.Elt) - - case *ast.StructType: - a.apply(n, "Fields", nil, n.Fields) - - case *ast.FuncType: - a.apply(n, "Params", nil, n.Params) - a.apply(n, "Results", nil, n.Results) - - case *ast.InterfaceType: - a.apply(n, "Methods", nil, n.Methods) - - case *ast.MapType: - a.apply(n, "Key", nil, n.Key) - a.apply(n, "Value", nil, n.Value) - - case *ast.ChanType: - a.apply(n, "Value", nil, n.Value) - - // Statements - case *ast.BadStmt: - // nothing to do - - case *ast.DeclStmt: - a.apply(n, "Decl", nil, n.Decl) - - case *ast.EmptyStmt: - // nothing to do - - case *ast.LabeledStmt: - a.apply(n, "Label", nil, n.Label) - a.apply(n, "Stmt", nil, n.Stmt) - - case *ast.ExprStmt: - a.apply(n, "X", nil, n.X) - - case *ast.SendStmt: - a.apply(n, "Chan", nil, n.Chan) - a.apply(n, "Value", nil, n.Value) - - case *ast.IncDecStmt: - a.apply(n, "X", nil, n.X) - - case *ast.AssignStmt: - a.applyList(n, "Lhs") - a.applyList(n, "Rhs") - - case *ast.GoStmt: - a.apply(n, "Call", nil, n.Call) - - case *ast.DeferStmt: - a.apply(n, "Call", nil, n.Call) - - case *ast.ReturnStmt: - a.applyList(n, "Results") - - case *ast.BranchStmt: - a.apply(n, "Label", nil, n.Label) - - case *ast.BlockStmt: - a.applyList(n, "List") - - case *ast.IfStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Cond", nil, n.Cond) - a.apply(n, "Body", nil, n.Body) - a.apply(n, "Else", nil, n.Else) - - case *ast.CaseClause: - a.applyList(n, "List") - a.applyList(n, "Body") - - case *ast.SwitchStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Tag", nil, n.Tag) - a.apply(n, "Body", nil, n.Body) - - case *ast.TypeSwitchStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Assign", nil, n.Assign) - a.apply(n, "Body", nil, n.Body) - - case *ast.CommClause: - a.apply(n, "Comm", nil, n.Comm) - a.applyList(n, "Body") - - case *ast.SelectStmt: - a.apply(n, "Body", nil, n.Body) - - case *ast.ForStmt: - a.apply(n, "Init", nil, n.Init) - a.apply(n, "Cond", nil, n.Cond) - a.apply(n, "Post", nil, n.Post) - a.apply(n, "Body", nil, n.Body) - - case *ast.RangeStmt: - a.apply(n, "Key", nil, n.Key) - a.apply(n, "Value", nil, n.Value) - a.apply(n, "X", nil, n.X) - a.apply(n, "Body", nil, n.Body) - - // Declarations - case *ast.ImportSpec: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Name", nil, n.Name) - a.apply(n, "Path", nil, n.Path) - a.apply(n, "Comment", nil, n.Comment) - - case *ast.ValueSpec: - a.apply(n, "Doc", nil, n.Doc) - a.applyList(n, "Names") - a.apply(n, "Type", nil, n.Type) - a.applyList(n, "Values") - a.apply(n, "Comment", nil, n.Comment) - - case *ast.TypeSpec: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Name", nil, n.Name) - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Comment", nil, n.Comment) - - case *ast.BadDecl: - // nothing to do - - case *ast.GenDecl: - a.apply(n, "Doc", nil, n.Doc) - a.applyList(n, "Specs") - - case *ast.FuncDecl: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Recv", nil, n.Recv) - a.apply(n, "Name", nil, n.Name) - a.apply(n, "Type", nil, n.Type) - a.apply(n, "Body", nil, n.Body) - - // Files and packages - case *ast.File: - a.apply(n, "Doc", nil, n.Doc) - a.apply(n, "Name", nil, n.Name) - a.applyList(n, "Decls") - // Don't walk n.Comments; they have either been walked already if - // they are Doc comments, or they can be easily walked explicitly. - - case *ast.Package: - // collect and sort names for reproducible behavior - var names []string - for name := range n.Files { - names = append(names, name) - } - sort.Strings(names) - for _, name := range names { - a.apply(n, name, nil, n.Files[name]) - } - - default: - panic(fmt.Sprintf("Apply: unexpected node type %T", n)) - } - - if a.post != nil && !a.post(&a.cursor) { - panic(abort) - } - - a.cursor = saved -} - -// An iterator controls iteration over a slice of nodes. -type iterator struct { - index, step int -} - -func (a *application) applyList(parent ast.Node, name string) { - // avoid heap-allocating a new iterator for each applyList call; reuse a.iter instead - saved := a.iter - a.iter.index = 0 - for { - // must reload parent.name each time, since cursor modifications might change it - v := reflect.Indirect(reflect.ValueOf(parent)).FieldByName(name) - if a.iter.index >= v.Len() { - break - } - - // element x may be nil in a bad AST - be cautious - var x ast.Node - if e := v.Index(a.iter.index); e.IsValid() { - x = e.Interface().(ast.Node) - } - - a.iter.step = 1 - a.apply(parent, name, &a.iter, x) - a.iter.index += a.iter.step - } - a.iter = saved -} diff --git a/vendor/golang.org/x/tools/go/ast/astutil/util.go b/vendor/golang.org/x/tools/go/ast/astutil/util.go deleted file mode 100644 index 919d5305ab..0000000000 --- a/vendor/golang.org/x/tools/go/ast/astutil/util.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 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 astutil - -import "go/ast" - -// Unparen returns e with any enclosing parentheses stripped. -func Unparen(e ast.Expr) ast.Expr { - for { - p, ok := e.(*ast.ParenExpr) - if !ok { - return e - } - e = p.X - } -} diff --git a/vendor/golang.org/x/tools/go/buildutil/allpackages.go b/vendor/golang.org/x/tools/go/buildutil/allpackages.go deleted file mode 100644 index c0cb03e7be..0000000000 --- a/vendor/golang.org/x/tools/go/buildutil/allpackages.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2014 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 buildutil provides utilities related to the go/build -// package in the standard library. -// -// All I/O is done via the build.Context file system interface, which must -// be concurrency-safe. -package buildutil // import "golang.org/x/tools/go/buildutil" - -import ( - "go/build" - "os" - "path/filepath" - "sort" - "strings" - "sync" -) - -// AllPackages returns the package path of each Go package in any source -// directory of the specified build context (e.g. $GOROOT or an element -// of $GOPATH). Errors are ignored. The results are sorted. -// All package paths are canonical, and thus may contain "/vendor/". -// -// The result may include import paths for directories that contain no -// *.go files, such as "archive" (in $GOROOT/src). -// -// All I/O is done via the build.Context file system interface, -// which must be concurrency-safe. -// -func AllPackages(ctxt *build.Context) []string { - var list []string - ForEachPackage(ctxt, func(pkg string, _ error) { - list = append(list, pkg) - }) - sort.Strings(list) - return list -} - -// ForEachPackage calls the found function with the package path of -// each Go package it finds in any source directory of the specified -// build context (e.g. $GOROOT or an element of $GOPATH). -// All package paths are canonical, and thus may contain "/vendor/". -// -// If the package directory exists but could not be read, the second -// argument to the found function provides the error. -// -// All I/O is done via the build.Context file system interface, -// which must be concurrency-safe. -// -func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) { - ch := make(chan item) - - var wg sync.WaitGroup - for _, root := range ctxt.SrcDirs() { - root := root - wg.Add(1) - go func() { - allPackages(ctxt, root, ch) - wg.Done() - }() - } - go func() { - wg.Wait() - close(ch) - }() - - // All calls to found occur in the caller's goroutine. - for i := range ch { - found(i.importPath, i.err) - } -} - -type item struct { - importPath string - err error // (optional) -} - -// We use a process-wide counting semaphore to limit -// the number of parallel calls to ReadDir. -var ioLimit = make(chan bool, 20) - -func allPackages(ctxt *build.Context, root string, ch chan<- item) { - root = filepath.Clean(root) + string(os.PathSeparator) - - var wg sync.WaitGroup - - var walkDir func(dir string) - walkDir = func(dir string) { - // Avoid .foo, _foo, and testdata directory trees. - base := filepath.Base(dir) - if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" { - return - } - - pkg := filepath.ToSlash(strings.TrimPrefix(dir, root)) - - // Prune search if we encounter any of these import paths. - switch pkg { - case "builtin": - return - } - - ioLimit <- true - files, err := ReadDir(ctxt, dir) - <-ioLimit - if pkg != "" || err != nil { - ch <- item{pkg, err} - } - for _, fi := range files { - fi := fi - if fi.IsDir() { - wg.Add(1) - go func() { - walkDir(filepath.Join(dir, fi.Name())) - wg.Done() - }() - } - } - } - - walkDir(root) - wg.Wait() -} - -// ExpandPatterns returns the set of packages matched by patterns, -// which may have the following forms: -// -// golang.org/x/tools/cmd/guru # a single package -// golang.org/x/tools/... # all packages beneath dir -// ... # the entire workspace. -// -// Order is significant: a pattern preceded by '-' removes matching -// packages from the set. For example, these patterns match all encoding -// packages except encoding/xml: -// -// encoding/... -encoding/xml -// -// A trailing slash in a pattern is ignored. (Path components of Go -// package names are separated by slash, not the platform's path separator.) -// -func ExpandPatterns(ctxt *build.Context, patterns []string) map[string]bool { - // TODO(adonovan): support other features of 'go list': - // - "std"/"cmd"/"all" meta-packages - // - "..." not at the end of a pattern - // - relative patterns using "./" or "../" prefix - - pkgs := make(map[string]bool) - doPkg := func(pkg string, neg bool) { - if neg { - delete(pkgs, pkg) - } else { - pkgs[pkg] = true - } - } - - // Scan entire workspace if wildcards are present. - // TODO(adonovan): opt: scan only the necessary subtrees of the workspace. - var all []string - for _, arg := range patterns { - if strings.HasSuffix(arg, "...") { - all = AllPackages(ctxt) - break - } - } - - for _, arg := range patterns { - if arg == "" { - continue - } - - neg := arg[0] == '-' - if neg { - arg = arg[1:] - } - - if arg == "..." { - // ... matches all packages - for _, pkg := range all { - doPkg(pkg, neg) - } - } else if dir := strings.TrimSuffix(arg, "/..."); dir != arg { - // dir/... matches all packages beneath dir - for _, pkg := range all { - if strings.HasPrefix(pkg, dir) && - (len(pkg) == len(dir) || pkg[len(dir)] == '/') { - doPkg(pkg, neg) - } - } - } else { - // single package - doPkg(strings.TrimSuffix(arg, "/"), neg) - } - } - - return pkgs -} diff --git a/vendor/golang.org/x/tools/go/buildutil/fakecontext.go b/vendor/golang.org/x/tools/go/buildutil/fakecontext.go deleted file mode 100644 index 5fc672fd51..0000000000 --- a/vendor/golang.org/x/tools/go/buildutil/fakecontext.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2015 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 buildutil - -import ( - "fmt" - "go/build" - "io" - "io/ioutil" - "os" - "path" - "path/filepath" - "sort" - "strings" - "time" -) - -// FakeContext returns a build.Context for the fake file tree specified -// by pkgs, which maps package import paths to a mapping from file base -// names to contents. -// -// The fake Context has a GOROOT of "/go" and no GOPATH, and overrides -// the necessary file access methods to read from memory instead of the -// real file system. -// -// Unlike a real file tree, the fake one has only two levels---packages -// and files---so ReadDir("/go/src/") returns all packages under -// /go/src/ including, for instance, "math" and "math/big". -// ReadDir("/go/src/math/big") would return all the files in the -// "math/big" package. -// -func FakeContext(pkgs map[string]map[string]string) *build.Context { - clean := func(filename string) string { - f := path.Clean(filepath.ToSlash(filename)) - // Removing "/go/src" while respecting segment - // boundaries has this unfortunate corner case: - if f == "/go/src" { - return "" - } - return strings.TrimPrefix(f, "/go/src/") - } - - ctxt := build.Default // copy - ctxt.GOROOT = "/go" - ctxt.GOPATH = "" - ctxt.Compiler = "gc" - ctxt.IsDir = func(dir string) bool { - dir = clean(dir) - if dir == "" { - return true // needed by (*build.Context).SrcDirs - } - return pkgs[dir] != nil - } - ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) { - dir = clean(dir) - var fis []os.FileInfo - if dir == "" { - // enumerate packages - for importPath := range pkgs { - fis = append(fis, fakeDirInfo(importPath)) - } - } else { - // enumerate files of package - for basename := range pkgs[dir] { - fis = append(fis, fakeFileInfo(basename)) - } - } - sort.Sort(byName(fis)) - return fis, nil - } - ctxt.OpenFile = func(filename string) (io.ReadCloser, error) { - filename = clean(filename) - dir, base := path.Split(filename) - content, ok := pkgs[path.Clean(dir)][base] - if !ok { - return nil, fmt.Errorf("file not found: %s", filename) - } - return ioutil.NopCloser(strings.NewReader(content)), nil - } - ctxt.IsAbsPath = func(path string) bool { - path = filepath.ToSlash(path) - // Don't rely on the default (filepath.Path) since on - // Windows, it reports virtual paths as non-absolute. - return strings.HasPrefix(path, "/") - } - return &ctxt -} - -type byName []os.FileInfo - -func (s byName) Len() int { return len(s) } -func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } - -type fakeFileInfo string - -func (fi fakeFileInfo) Name() string { return string(fi) } -func (fakeFileInfo) Sys() interface{} { return nil } -func (fakeFileInfo) ModTime() time.Time { return time.Time{} } -func (fakeFileInfo) IsDir() bool { return false } -func (fakeFileInfo) Size() int64 { return 0 } -func (fakeFileInfo) Mode() os.FileMode { return 0644 } - -type fakeDirInfo string - -func (fd fakeDirInfo) Name() string { return string(fd) } -func (fakeDirInfo) Sys() interface{} { return nil } -func (fakeDirInfo) ModTime() time.Time { return time.Time{} } -func (fakeDirInfo) IsDir() bool { return true } -func (fakeDirInfo) Size() int64 { return 0 } -func (fakeDirInfo) Mode() os.FileMode { return 0755 } diff --git a/vendor/golang.org/x/tools/go/buildutil/overlay.go b/vendor/golang.org/x/tools/go/buildutil/overlay.go deleted file mode 100644 index 8e239086bd..0000000000 --- a/vendor/golang.org/x/tools/go/buildutil/overlay.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2016 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 buildutil - -import ( - "bufio" - "bytes" - "fmt" - "go/build" - "io" - "io/ioutil" - "path/filepath" - "strconv" - "strings" -) - -// OverlayContext overlays a build.Context with additional files from -// a map. Files in the map take precedence over other files. -// -// In addition to plain string comparison, two file names are -// considered equal if their base names match and their directory -// components point at the same directory on the file system. That is, -// symbolic links are followed for directories, but not files. -// -// A common use case for OverlayContext is to allow editors to pass in -// a set of unsaved, modified files. -// -// Currently, only the Context.OpenFile function will respect the -// overlay. This may change in the future. -func OverlayContext(orig *build.Context, overlay map[string][]byte) *build.Context { - // TODO(dominikh): Implement IsDir, HasSubdir and ReadDir - - rc := func(data []byte) (io.ReadCloser, error) { - return ioutil.NopCloser(bytes.NewBuffer(data)), nil - } - - copy := *orig // make a copy - ctxt := © - ctxt.OpenFile = func(path string) (io.ReadCloser, error) { - // Fast path: names match exactly. - if content, ok := overlay[path]; ok { - return rc(content) - } - - // Slow path: check for same file under a different - // alias, perhaps due to a symbolic link. - for filename, content := range overlay { - if sameFile(path, filename) { - return rc(content) - } - } - - return OpenFile(orig, path) - } - return ctxt -} - -// ParseOverlayArchive parses an archive containing Go files and their -// contents. The result is intended to be used with OverlayContext. -// -// -// Archive format -// -// The archive consists of a series of files. Each file consists of a -// name, a decimal file size and the file contents, separated by -// newlines. No newline follows after the file contents. -func ParseOverlayArchive(archive io.Reader) (map[string][]byte, error) { - overlay := make(map[string][]byte) - r := bufio.NewReader(archive) - for { - // Read file name. - filename, err := r.ReadString('\n') - if err != nil { - if err == io.EOF { - break // OK - } - return nil, fmt.Errorf("reading archive file name: %v", err) - } - filename = filepath.Clean(strings.TrimSpace(filename)) - - // Read file size. - sz, err := r.ReadString('\n') - if err != nil { - return nil, fmt.Errorf("reading size of archive file %s: %v", filename, err) - } - sz = strings.TrimSpace(sz) - size, err := strconv.ParseUint(sz, 10, 32) - if err != nil { - return nil, fmt.Errorf("parsing size of archive file %s: %v", filename, err) - } - - // Read file content. - content := make([]byte, size) - if _, err := io.ReadFull(r, content); err != nil { - return nil, fmt.Errorf("reading archive file %s: %v", filename, err) - } - overlay[filename] = content - } - - return overlay, nil -} diff --git a/vendor/golang.org/x/tools/go/buildutil/tags.go b/vendor/golang.org/x/tools/go/buildutil/tags.go deleted file mode 100644 index 6da0ce4848..0000000000 --- a/vendor/golang.org/x/tools/go/buildutil/tags.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2015 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 buildutil - -// This logic was copied from stringsFlag from $GOROOT/src/cmd/go/build.go. - -import "fmt" - -const TagsFlagDoc = "a list of `build tags` to consider satisfied during the build. " + - "For more information about build tags, see the description of " + - "build constraints in the documentation for the go/build package" - -// TagsFlag is an implementation of the flag.Value and flag.Getter interfaces that parses -// a flag value in the same manner as go build's -tags flag and -// populates a []string slice. -// -// See $GOROOT/src/go/build/doc.go for description of build tags. -// See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag. -// -// Example: -// flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc) -type TagsFlag []string - -func (v *TagsFlag) Set(s string) error { - var err error - *v, err = splitQuotedFields(s) - if *v == nil { - *v = []string{} - } - return err -} - -func (v *TagsFlag) Get() interface{} { return *v } - -func splitQuotedFields(s string) ([]string, error) { - // Split fields allowing '' or "" around elements. - // Quotes further inside the string do not count. - var f []string - for len(s) > 0 { - for len(s) > 0 && isSpaceByte(s[0]) { - s = s[1:] - } - if len(s) == 0 { - break - } - // Accepted quoted string. No unescaping inside. - if s[0] == '"' || s[0] == '\'' { - quote := s[0] - s = s[1:] - i := 0 - for i < len(s) && s[i] != quote { - i++ - } - if i >= len(s) { - return nil, fmt.Errorf("unterminated %c string", quote) - } - f = append(f, s[:i]) - s = s[i+1:] - continue - } - i := 0 - for i < len(s) && !isSpaceByte(s[i]) { - i++ - } - f = append(f, s[:i]) - s = s[i:] - } - return f, nil -} - -func (v *TagsFlag) String() string { - return "<tagsFlag>" -} - -func isSpaceByte(c byte) bool { - return c == ' ' || c == '\t' || c == '\n' || c == '\r' -} diff --git a/vendor/golang.org/x/tools/go/buildutil/util.go b/vendor/golang.org/x/tools/go/buildutil/util.go deleted file mode 100644 index fc923d7a70..0000000000 --- a/vendor/golang.org/x/tools/go/buildutil/util.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2014 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 buildutil - -import ( - "fmt" - "go/ast" - "go/build" - "go/parser" - "go/token" - "io" - "io/ioutil" - "os" - "path" - "path/filepath" - "strings" -) - -// ParseFile behaves like parser.ParseFile, -// but uses the build context's file system interface, if any. -// -// If file is not absolute (as defined by IsAbsPath), the (dir, file) -// components are joined using JoinPath; dir must be absolute. -// -// The displayPath function, if provided, is used to transform the -// filename that will be attached to the ASTs. -// -// TODO(adonovan): call this from go/loader.parseFiles when the tree thaws. -// -func ParseFile(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, file string, mode parser.Mode) (*ast.File, error) { - if !IsAbsPath(ctxt, file) { - file = JoinPath(ctxt, dir, file) - } - rd, err := OpenFile(ctxt, file) - if err != nil { - return nil, err - } - defer rd.Close() // ignore error - if displayPath != nil { - file = displayPath(file) - } - return parser.ParseFile(fset, file, rd, mode) -} - -// ContainingPackage returns the package containing filename. -// -// If filename is not absolute, it is interpreted relative to working directory dir. -// All I/O is via the build context's file system interface, if any. -// -// The '...Files []string' fields of the resulting build.Package are not -// populated (build.FindOnly mode). -// -func ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Package, error) { - if !IsAbsPath(ctxt, filename) { - filename = JoinPath(ctxt, dir, filename) - } - - // We must not assume the file tree uses - // "/" always, - // `\` always, - // or os.PathSeparator (which varies by platform), - // but to make any progress, we are forced to assume that - // paths will not use `\` unless the PathSeparator - // is also `\`, thus we can rely on filepath.ToSlash for some sanity. - - dirSlash := path.Dir(filepath.ToSlash(filename)) + "/" - - // We assume that no source root (GOPATH[i] or GOROOT) contains any other. - for _, srcdir := range ctxt.SrcDirs() { - srcdirSlash := filepath.ToSlash(srcdir) + "/" - if importPath, ok := HasSubdir(ctxt, srcdirSlash, dirSlash); ok { - return ctxt.Import(importPath, dir, build.FindOnly) - } - } - - return nil, fmt.Errorf("can't find package containing %s", filename) -} - -// -- Effective methods of file system interface ------------------------- - -// (go/build.Context defines these as methods, but does not export them.) - -// hasSubdir calls ctxt.HasSubdir (if not nil) or else uses -// the local file system to answer the question. -func HasSubdir(ctxt *build.Context, root, dir string) (rel string, ok bool) { - if f := ctxt.HasSubdir; f != nil { - return f(root, dir) - } - - // Try using paths we received. - if rel, ok = hasSubdir(root, dir); ok { - return - } - - // Try expanding symlinks and comparing - // expanded against unexpanded and - // expanded against expanded. - rootSym, _ := filepath.EvalSymlinks(root) - dirSym, _ := filepath.EvalSymlinks(dir) - - if rel, ok = hasSubdir(rootSym, dir); ok { - return - } - if rel, ok = hasSubdir(root, dirSym); ok { - return - } - return hasSubdir(rootSym, dirSym) -} - -func hasSubdir(root, dir string) (rel string, ok bool) { - const sep = string(filepath.Separator) - root = filepath.Clean(root) - if !strings.HasSuffix(root, sep) { - root += sep - } - - dir = filepath.Clean(dir) - if !strings.HasPrefix(dir, root) { - return "", false - } - - return filepath.ToSlash(dir[len(root):]), true -} - -// FileExists returns true if the specified file exists, -// using the build context's file system interface. -func FileExists(ctxt *build.Context, path string) bool { - if ctxt.OpenFile != nil { - r, err := ctxt.OpenFile(path) - if err != nil { - return false - } - r.Close() // ignore error - return true - } - _, err := os.Stat(path) - return err == nil -} - -// OpenFile behaves like os.Open, -// but uses the build context's file system interface, if any. -func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) { - if ctxt.OpenFile != nil { - return ctxt.OpenFile(path) - } - return os.Open(path) -} - -// IsAbsPath behaves like filepath.IsAbs, -// but uses the build context's file system interface, if any. -func IsAbsPath(ctxt *build.Context, path string) bool { - if ctxt.IsAbsPath != nil { - return ctxt.IsAbsPath(path) - } - return filepath.IsAbs(path) -} - -// JoinPath behaves like filepath.Join, -// but uses the build context's file system interface, if any. -func JoinPath(ctxt *build.Context, path ...string) string { - if ctxt.JoinPath != nil { - return ctxt.JoinPath(path...) - } - return filepath.Join(path...) -} - -// IsDir behaves like os.Stat plus IsDir, -// but uses the build context's file system interface, if any. -func IsDir(ctxt *build.Context, path string) bool { - if ctxt.IsDir != nil { - return ctxt.IsDir(path) - } - fi, err := os.Stat(path) - return err == nil && fi.IsDir() -} - -// ReadDir behaves like ioutil.ReadDir, -// but uses the build context's file system interface, if any. -func ReadDir(ctxt *build.Context, path string) ([]os.FileInfo, error) { - if ctxt.ReadDir != nil { - return ctxt.ReadDir(path) - } - return ioutil.ReadDir(path) -} - -// SplitPathList behaves like filepath.SplitList, -// but uses the build context's file system interface, if any. -func SplitPathList(ctxt *build.Context, s string) []string { - if ctxt.SplitPathList != nil { - return ctxt.SplitPathList(s) - } - return filepath.SplitList(s) -} - -// sameFile returns true if x and y have the same basename and denote -// the same file. -// -func sameFile(x, y string) bool { - if path.Clean(x) == path.Clean(y) { - return true - } - if filepath.Base(x) == filepath.Base(y) { // (optimisation) - if xi, err := os.Stat(x); err == nil { - if yi, err := os.Stat(y); err == nil { - return os.SameFile(xi, yi) - } - } - } - return false -} diff --git a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go deleted file mode 100644 index f8363d8faa..0000000000 --- a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 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 gcexportdata provides functions for locating, reading, and -// writing export data files containing type information produced by the -// gc compiler. This package supports go1.7 export data format and all -// later versions. -// -// Although it might seem convenient for this package to live alongside -// go/types in the standard library, this would cause version skew -// problems for developer tools that use it, since they must be able to -// consume the outputs of the gc compiler both before and after a Go -// update such as from Go 1.7 to Go 1.8. Because this package lives in -// golang.org/x/tools, sites can update their version of this repo some -// time before the Go 1.8 release and rebuild and redeploy their -// developer tools, which will then be able to consume both Go 1.7 and -// Go 1.8 export data files, so they will work before and after the -// Go update. (See discussion at https://golang.org/issue/15651.) -// -package gcexportdata // import "golang.org/x/tools/go/gcexportdata" - -import ( - "bufio" - "bytes" - "fmt" - "go/token" - "go/types" - "io" - "io/ioutil" - - "golang.org/x/tools/go/internal/gcimporter" -) - -// Find returns the name of an object (.o) or archive (.a) file -// containing type information for the specified import path, -// using the workspace layout conventions of go/build. -// If no file was found, an empty filename is returned. -// -// A relative srcDir is interpreted relative to the current working directory. -// -// Find also returns the package's resolved (canonical) import path, -// reflecting the effects of srcDir and vendoring on importPath. -func Find(importPath, srcDir string) (filename, path string) { - return gcimporter.FindPkg(importPath, srcDir) -} - -// NewReader returns a reader for the export data section of an object -// (.o) or archive (.a) file read from r. The new reader may provide -// additional trailing data beyond the end of the export data. -func NewReader(r io.Reader) (io.Reader, error) { - buf := bufio.NewReader(r) - _, err := gcimporter.FindExportData(buf) - // If we ever switch to a zip-like archive format with the ToC - // at the end, we can return the correct portion of export data, - // but for now we must return the entire rest of the file. - return buf, err -} - -// Read reads export data from in, decodes it, and returns type -// information for the package. -// The package name is specified by path. -// File position information is added to fset. -// -// Read may inspect and add to the imports map to ensure that references -// within the export data to other packages are consistent. The caller -// must ensure that imports[path] does not exist, or exists but is -// incomplete (see types.Package.Complete), and Read inserts the -// resulting package into this map entry. -// -// On return, the state of the reader is undefined. -func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package, path string) (*types.Package, error) { - data, err := ioutil.ReadAll(in) - if err != nil { - return nil, fmt.Errorf("reading export data for %q: %v", path, err) - } - - if bytes.HasPrefix(data, []byte("!<arch>")) { - return nil, fmt.Errorf("can't read export data for %q directly from an archive file (call gcexportdata.NewReader first to extract export data)", path) - } - - // The App Engine Go runtime v1.6 uses the old export data format. - // TODO(adonovan): delete once v1.7 has been around for a while. - if bytes.HasPrefix(data, []byte("package ")) { - return gcimporter.ImportData(imports, path, path, bytes.NewReader(data)) - } - - // The indexed export format starts with an 'i'; the older - // binary export format starts with a 'c', 'd', or 'v' - // (from "version"). Select appropriate importer. - if len(data) > 0 && data[0] == 'i' { - _, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path) - return pkg, err - } - - _, pkg, err := gcimporter.BImportData(fset, imports, data, path) - return pkg, err -} - -// Write writes encoded type information for the specified package to out. -// The FileSet provides file position information for named objects. -func Write(out io.Writer, fset *token.FileSet, pkg *types.Package) error { - b, err := gcimporter.IExportData(fset, pkg) - if err != nil { - return err - } - _, err = out.Write(b) - return err -} diff --git a/vendor/golang.org/x/tools/go/gcexportdata/importer.go b/vendor/golang.org/x/tools/go/gcexportdata/importer.go deleted file mode 100644 index efe221e7e1..0000000000 --- a/vendor/golang.org/x/tools/go/gcexportdata/importer.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2016 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 gcexportdata - -import ( - "fmt" - "go/token" - "go/types" - "os" -) - -// NewImporter returns a new instance of the types.Importer interface -// that reads type information from export data files written by gc. -// The Importer also satisfies types.ImporterFrom. -// -// Export data files are located using "go build" workspace conventions -// and the build.Default context. -// -// Use this importer instead of go/importer.For("gc", ...) to avoid the -// version-skew problems described in the documentation of this package, -// or to control the FileSet or access the imports map populated during -// package loading. -// -func NewImporter(fset *token.FileSet, imports map[string]*types.Package) types.ImporterFrom { - return importer{fset, imports} -} - -type importer struct { - fset *token.FileSet - imports map[string]*types.Package -} - -func (imp importer) Import(importPath string) (*types.Package, error) { - return imp.ImportFrom(importPath, "", 0) -} - -func (imp importer) ImportFrom(importPath, srcDir string, mode types.ImportMode) (_ *types.Package, err error) { - filename, path := Find(importPath, srcDir) - if filename == "" { - if importPath == "unsafe" { - // Even for unsafe, call Find first in case - // the package was vendored. - return types.Unsafe, nil - } - return nil, fmt.Errorf("can't find import: %s", importPath) - } - - if pkg, ok := imp.imports[path]; ok && pkg.Complete() { - return pkg, nil // cache hit - } - - // open file - f, err := os.Open(filename) - if err != nil { - return nil, err - } - defer func() { - f.Close() - if err != nil { - // add file name to error - err = fmt.Errorf("reading export data: %s: %v", filename, err) - } - }() - - r, err := NewReader(f) - if err != nil { - return nil, err - } - - return Read(r, imp.fset, imp.imports, path) -} diff --git a/vendor/golang.org/x/tools/go/internal/cgo/cgo.go b/vendor/golang.org/x/tools/go/internal/cgo/cgo.go deleted file mode 100644 index 9772504c97..0000000000 --- a/vendor/golang.org/x/tools/go/internal/cgo/cgo.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2013 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 cgo handles cgo preprocessing of files containing `import "C"`. -// -// DESIGN -// -// The approach taken is to run the cgo processor on the package's -// CgoFiles and parse the output, faking the filenames of the -// resulting ASTs so that the synthetic file containing the C types is -// called "C" (e.g. "~/go/src/net/C") and the preprocessed files -// have their original names (e.g. "~/go/src/net/cgo_unix.go"), -// not the names of the actual temporary files. -// -// The advantage of this approach is its fidelity to 'go build'. The -// downside is that the token.Position.Offset for each AST node is -// incorrect, being an offset within the temporary file. Line numbers -// should still be correct because of the //line comments. -// -// The logic of this file is mostly plundered from the 'go build' -// tool, which also invokes the cgo preprocessor. -// -// -// REJECTED ALTERNATIVE -// -// An alternative approach that we explored is to extend go/types' -// Importer mechanism to provide the identity of the importing package -// so that each time `import "C"` appears it resolves to a different -// synthetic package containing just the objects needed in that case. -// The loader would invoke cgo but parse only the cgo_types.go file -// defining the package-level objects, discarding the other files -// resulting from preprocessing. -// -// The benefit of this approach would have been that source-level -// syntax information would correspond exactly to the original cgo -// file, with no preprocessing involved, making source tools like -// godoc, guru, and eg happy. However, the approach was rejected -// due to the additional complexity it would impose on go/types. (It -// made for a beautiful demo, though.) -// -// cgo files, despite their *.go extension, are not legal Go source -// files per the specification since they may refer to unexported -// members of package "C" such as C.int. Also, a function such as -// C.getpwent has in effect two types, one matching its C type and one -// which additionally returns (errno C.int). The cgo preprocessor -// uses name mangling to distinguish these two functions in the -// processed code, but go/types would need to duplicate this logic in -// its handling of function calls, analogous to the treatment of map -// lookups in which y=m[k] and y,ok=m[k] are both legal. - -package cgo - -import ( - "fmt" - "go/ast" - "go/build" - "go/parser" - "go/token" - exec "golang.org/x/sys/execabs" - "io/ioutil" - "log" - "os" - "path/filepath" - "regexp" - "strings" -) - -// ProcessFiles invokes the cgo preprocessor on bp.CgoFiles, parses -// the output and returns the resulting ASTs. -// -func ProcessFiles(bp *build.Package, fset *token.FileSet, DisplayPath func(path string) string, mode parser.Mode) ([]*ast.File, error) { - tmpdir, err := ioutil.TempDir("", strings.Replace(bp.ImportPath, "/", "_", -1)+"_C") - if err != nil { - return nil, err - } - defer os.RemoveAll(tmpdir) - - pkgdir := bp.Dir - if DisplayPath != nil { - pkgdir = DisplayPath(pkgdir) - } - - cgoFiles, cgoDisplayFiles, err := Run(bp, pkgdir, tmpdir, false) - if err != nil { - return nil, err - } - var files []*ast.File - for i := range cgoFiles { - rd, err := os.Open(cgoFiles[i]) - if err != nil { - return nil, err - } - display := filepath.Join(bp.Dir, cgoDisplayFiles[i]) - f, err := parser.ParseFile(fset, display, rd, mode) - rd.Close() - if err != nil { - return nil, err - } - files = append(files, f) - } - return files, nil -} - -var cgoRe = regexp.MustCompile(`[/\\:]`) - -// Run invokes the cgo preprocessor on bp.CgoFiles and returns two -// lists of files: the resulting processed files (in temporary -// directory tmpdir) and the corresponding names of the unprocessed files. -// -// Run is adapted from (*builder).cgo in -// $GOROOT/src/cmd/go/build.go, but these features are unsupported: -// Objective C, CGOPKGPATH, CGO_FLAGS. -// -// If useabs is set to true, absolute paths of the bp.CgoFiles will be passed in -// to the cgo preprocessor. This in turn will set the // line comments -// referring to those files to use absolute paths. This is needed for -// go/packages using the legacy go list support so it is able to find -// the original files. -func Run(bp *build.Package, pkgdir, tmpdir string, useabs bool) (files, displayFiles []string, err error) { - cgoCPPFLAGS, _, _, _ := cflags(bp, true) - _, cgoexeCFLAGS, _, _ := cflags(bp, false) - - if len(bp.CgoPkgConfig) > 0 { - pcCFLAGS, err := pkgConfigFlags(bp) - if err != nil { - return nil, nil, err - } - cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) - } - - // Allows including _cgo_export.h from .[ch] files in the package. - cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", tmpdir) - - // _cgo_gotypes.go (displayed "C") contains the type definitions. - files = append(files, filepath.Join(tmpdir, "_cgo_gotypes.go")) - displayFiles = append(displayFiles, "C") - for _, fn := range bp.CgoFiles { - // "foo.cgo1.go" (displayed "foo.go") is the processed Go source. - f := cgoRe.ReplaceAllString(fn[:len(fn)-len("go")], "_") - files = append(files, filepath.Join(tmpdir, f+"cgo1.go")) - displayFiles = append(displayFiles, fn) - } - - var cgoflags []string - if bp.Goroot && bp.ImportPath == "runtime/cgo" { - cgoflags = append(cgoflags, "-import_runtime_cgo=false") - } - if bp.Goroot && bp.ImportPath == "runtime/race" || bp.ImportPath == "runtime/cgo" { - cgoflags = append(cgoflags, "-import_syscall=false") - } - - var cgoFiles []string = bp.CgoFiles - if useabs { - cgoFiles = make([]string, len(bp.CgoFiles)) - for i := range cgoFiles { - cgoFiles[i] = filepath.Join(pkgdir, bp.CgoFiles[i]) - } - } - - args := stringList( - "go", "tool", "cgo", "-objdir", tmpdir, cgoflags, "--", - cgoCPPFLAGS, cgoexeCFLAGS, cgoFiles, - ) - if false { - log.Printf("Running cgo for package %q: %s (dir=%s)", bp.ImportPath, args, pkgdir) - } - cmd := exec.Command(args[0], args[1:]...) - cmd.Dir = pkgdir - cmd.Stdout = os.Stderr - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return nil, nil, fmt.Errorf("cgo failed: %s: %s", args, err) - } - - return files, displayFiles, nil -} - -// -- unmodified from 'go build' --------------------------------------- - -// Return the flags to use when invoking the C or C++ compilers, or cgo. -func cflags(p *build.Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) { - var defaults string - if def { - defaults = "-g -O2" - } - - cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS) - cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS) - cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS) - ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS) - return -} - -// envList returns the value of the given environment variable broken -// into fields, using the default value when the variable is empty. -func envList(key, def string) []string { - v := os.Getenv(key) - if v == "" { - v = def - } - return strings.Fields(v) -} - -// stringList's arguments should be a sequence of string or []string values. -// stringList flattens them into a single []string. -func stringList(args ...interface{}) []string { - var x []string - for _, arg := range args { - switch arg := arg.(type) { - case []string: - x = append(x, arg...) - case string: - x = append(x, arg) - default: - panic("stringList: invalid argument") - } - } - return x -} diff --git a/vendor/golang.org/x/tools/go/internal/cgo/cgo_pkgconfig.go b/vendor/golang.org/x/tools/go/internal/cgo/cgo_pkgconfig.go deleted file mode 100644 index 7d94bbc1e5..0000000000 --- a/vendor/golang.org/x/tools/go/internal/cgo/cgo_pkgconfig.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 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 cgo - -import ( - "errors" - "fmt" - "go/build" - exec "golang.org/x/sys/execabs" - "strings" -) - -// pkgConfig runs pkg-config with the specified arguments and returns the flags it prints. -func pkgConfig(mode string, pkgs []string) (flags []string, err error) { - cmd := exec.Command("pkg-config", append([]string{mode}, pkgs...)...) - out, err := cmd.CombinedOutput() - if err != nil { - s := fmt.Sprintf("%s failed: %v", strings.Join(cmd.Args, " "), err) - if len(out) > 0 { - s = fmt.Sprintf("%s: %s", s, out) - } - return nil, errors.New(s) - } - if len(out) > 0 { - flags = strings.Fields(string(out)) - } - return -} - -// pkgConfigFlags calls pkg-config if needed and returns the cflags -// needed to build the package. -func pkgConfigFlags(p *build.Package) (cflags []string, err error) { - if len(p.CgoPkgConfig) == 0 { - return nil, nil - } - return pkgConfig("--cflags", p.CgoPkgConfig) -} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go deleted file mode 100644 index a807d0aaa2..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go +++ /dev/null @@ -1,852 +0,0 @@ -// Copyright 2016 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. - -// Binary package export. -// This file was derived from $GOROOT/src/cmd/compile/internal/gc/bexport.go; -// see that file for specification of the format. - -package gcimporter - -import ( - "bytes" - "encoding/binary" - "fmt" - "go/ast" - "go/constant" - "go/token" - "go/types" - "math" - "math/big" - "sort" - "strings" -) - -// If debugFormat is set, each integer and string value is preceded by a marker -// and position information in the encoding. This mechanism permits an importer -// to recognize immediately when it is out of sync. The importer recognizes this -// mode automatically (i.e., it can import export data produced with debugging -// support even if debugFormat is not set at the time of import). This mode will -// lead to massively larger export data (by a factor of 2 to 3) and should only -// be enabled during development and debugging. -// -// NOTE: This flag is the first flag to enable if importing dies because of -// (suspected) format errors, and whenever a change is made to the format. -const debugFormat = false // default: false - -// If trace is set, debugging output is printed to std out. -const trace = false // default: false - -// Current export format version. Increase with each format change. -// Note: The latest binary (non-indexed) export format is at version 6. -// This exporter is still at level 4, but it doesn't matter since -// the binary importer can handle older versions just fine. -// 6: package height (CL 105038) -- NOT IMPLEMENTED HERE -// 5: improved position encoding efficiency (issue 20080, CL 41619) -- NOT IMPLEMEMTED HERE -// 4: type name objects support type aliases, uses aliasTag -// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used) -// 2: removed unused bool in ODCL export (compiler only) -// 1: header format change (more regular), export package for _ struct fields -// 0: Go1.7 encoding -const exportVersion = 4 - -// trackAllTypes enables cycle tracking for all types, not just named -// types. The existing compiler invariants assume that unnamed types -// that are not completely set up are not used, or else there are spurious -// errors. -// If disabled, only named types are tracked, possibly leading to slightly -// less efficient encoding in rare cases. It also prevents the export of -// some corner-case type declarations (but those are not handled correctly -// with with the textual export format either). -// TODO(gri) enable and remove once issues caused by it are fixed -const trackAllTypes = false - -type exporter struct { - fset *token.FileSet - out bytes.Buffer - - // object -> index maps, indexed in order of serialization - strIndex map[string]int - pkgIndex map[*types.Package]int - typIndex map[types.Type]int - - // position encoding - posInfoFormat bool - prevFile string - prevLine int - - // debugging support - written int // bytes written - indent int // for trace -} - -// internalError represents an error generated inside this package. -type internalError string - -func (e internalError) Error() string { return "gcimporter: " + string(e) } - -func internalErrorf(format string, args ...interface{}) error { - return internalError(fmt.Sprintf(format, args...)) -} - -// BExportData returns binary export data for pkg. -// If no file set is provided, position info will be missing. -func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) { - defer func() { - if e := recover(); e != nil { - if ierr, ok := e.(internalError); ok { - err = ierr - return - } - // Not an internal error; panic again. - panic(e) - } - }() - - p := exporter{ - fset: fset, - strIndex: map[string]int{"": 0}, // empty string is mapped to 0 - pkgIndex: make(map[*types.Package]int), - typIndex: make(map[types.Type]int), - posInfoFormat: true, // TODO(gri) might become a flag, eventually - } - - // write version info - // The version string must start with "version %d" where %d is the version - // number. Additional debugging information may follow after a blank; that - // text is ignored by the importer. - p.rawStringln(fmt.Sprintf("version %d", exportVersion)) - var debug string - if debugFormat { - debug = "debug" - } - p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly - p.bool(trackAllTypes) - p.bool(p.posInfoFormat) - - // --- generic export data --- - - // populate type map with predeclared "known" types - for index, typ := range predeclared() { - p.typIndex[typ] = index - } - if len(p.typIndex) != len(predeclared()) { - return nil, internalError("duplicate entries in type map?") - } - - // write package data - p.pkg(pkg, true) - if trace { - p.tracef("\n") - } - - // write objects - objcount := 0 - scope := pkg.Scope() - for _, name := range scope.Names() { - if !ast.IsExported(name) { - continue - } - if trace { - p.tracef("\n") - } - p.obj(scope.Lookup(name)) - objcount++ - } - - // indicate end of list - if trace { - p.tracef("\n") - } - p.tag(endTag) - - // for self-verification only (redundant) - p.int(objcount) - - if trace { - p.tracef("\n") - } - - // --- end of export data --- - - return p.out.Bytes(), nil -} - -func (p *exporter) pkg(pkg *types.Package, emptypath bool) { - if pkg == nil { - panic(internalError("unexpected nil pkg")) - } - - // if we saw the package before, write its index (>= 0) - if i, ok := p.pkgIndex[pkg]; ok { - p.index('P', i) - return - } - - // otherwise, remember the package, write the package tag (< 0) and package data - if trace { - p.tracef("P%d = { ", len(p.pkgIndex)) - defer p.tracef("} ") - } - p.pkgIndex[pkg] = len(p.pkgIndex) - - p.tag(packageTag) - p.string(pkg.Name()) - if emptypath { - p.string("") - } else { - p.string(pkg.Path()) - } -} - -func (p *exporter) obj(obj types.Object) { - switch obj := obj.(type) { - case *types.Const: - p.tag(constTag) - p.pos(obj) - p.qualifiedName(obj) - p.typ(obj.Type()) - p.value(obj.Val()) - - case *types.TypeName: - if obj.IsAlias() { - p.tag(aliasTag) - p.pos(obj) - p.qualifiedName(obj) - } else { - p.tag(typeTag) - } - p.typ(obj.Type()) - - case *types.Var: - p.tag(varTag) - p.pos(obj) - p.qualifiedName(obj) - p.typ(obj.Type()) - - case *types.Func: - p.tag(funcTag) - p.pos(obj) - p.qualifiedName(obj) - sig := obj.Type().(*types.Signature) - p.paramList(sig.Params(), sig.Variadic()) - p.paramList(sig.Results(), false) - - default: - panic(internalErrorf("unexpected object %v (%T)", obj, obj)) - } -} - -func (p *exporter) pos(obj types.Object) { - if !p.posInfoFormat { - return - } - - file, line := p.fileLine(obj) - if file == p.prevFile { - // common case: write line delta - // delta == 0 means different file or no line change - delta := line - p.prevLine - p.int(delta) - if delta == 0 { - p.int(-1) // -1 means no file change - } - } else { - // different file - p.int(0) - // Encode filename as length of common prefix with previous - // filename, followed by (possibly empty) suffix. Filenames - // frequently share path prefixes, so this can save a lot - // of space and make export data size less dependent on file - // path length. The suffix is unlikely to be empty because - // file names tend to end in ".go". - n := commonPrefixLen(p.prevFile, file) - p.int(n) // n >= 0 - p.string(file[n:]) // write suffix only - p.prevFile = file - p.int(line) - } - p.prevLine = line -} - -func (p *exporter) fileLine(obj types.Object) (file string, line int) { - if p.fset != nil { - pos := p.fset.Position(obj.Pos()) - file = pos.Filename - line = pos.Line - } - return -} - -func commonPrefixLen(a, b string) int { - if len(a) > len(b) { - a, b = b, a - } - // len(a) <= len(b) - i := 0 - for i < len(a) && a[i] == b[i] { - i++ - } - return i -} - -func (p *exporter) qualifiedName(obj types.Object) { - p.string(obj.Name()) - p.pkg(obj.Pkg(), false) -} - -func (p *exporter) typ(t types.Type) { - if t == nil { - panic(internalError("nil type")) - } - - // Possible optimization: Anonymous pointer types *T where - // T is a named type are common. We could canonicalize all - // such types *T to a single type PT = *T. This would lead - // to at most one *T entry in typIndex, and all future *T's - // would be encoded as the respective index directly. Would - // save 1 byte (pointerTag) per *T and reduce the typIndex - // size (at the cost of a canonicalization map). We can do - // this later, without encoding format change. - - // if we saw the type before, write its index (>= 0) - if i, ok := p.typIndex[t]; ok { - p.index('T', i) - return - } - - // otherwise, remember the type, write the type tag (< 0) and type data - if trackAllTypes { - if trace { - p.tracef("T%d = {>\n", len(p.typIndex)) - defer p.tracef("<\n} ") - } - p.typIndex[t] = len(p.typIndex) - } - - switch t := t.(type) { - case *types.Named: - if !trackAllTypes { - // if we don't track all types, track named types now - p.typIndex[t] = len(p.typIndex) - } - - p.tag(namedTag) - p.pos(t.Obj()) - p.qualifiedName(t.Obj()) - p.typ(t.Underlying()) - if !types.IsInterface(t) { - p.assocMethods(t) - } - - case *types.Array: - p.tag(arrayTag) - p.int64(t.Len()) - p.typ(t.Elem()) - - case *types.Slice: - p.tag(sliceTag) - p.typ(t.Elem()) - - case *dddSlice: - p.tag(dddTag) - p.typ(t.elem) - - case *types.Struct: - p.tag(structTag) - p.fieldList(t) - - case *types.Pointer: - p.tag(pointerTag) - p.typ(t.Elem()) - - case *types.Signature: - p.tag(signatureTag) - p.paramList(t.Params(), t.Variadic()) - p.paramList(t.Results(), false) - - case *types.Interface: - p.tag(interfaceTag) - p.iface(t) - - case *types.Map: - p.tag(mapTag) - p.typ(t.Key()) - p.typ(t.Elem()) - - case *types.Chan: - p.tag(chanTag) - p.int(int(3 - t.Dir())) // hack - p.typ(t.Elem()) - - default: - panic(internalErrorf("unexpected type %T: %s", t, t)) - } -} - -func (p *exporter) assocMethods(named *types.Named) { - // Sort methods (for determinism). - var methods []*types.Func - for i := 0; i < named.NumMethods(); i++ { - methods = append(methods, named.Method(i)) - } - sort.Sort(methodsByName(methods)) - - p.int(len(methods)) - - if trace && methods != nil { - p.tracef("associated methods {>\n") - } - - for i, m := range methods { - if trace && i > 0 { - p.tracef("\n") - } - - p.pos(m) - name := m.Name() - p.string(name) - if !exported(name) { - p.pkg(m.Pkg(), false) - } - - sig := m.Type().(*types.Signature) - p.paramList(types.NewTuple(sig.Recv()), false) - p.paramList(sig.Params(), sig.Variadic()) - p.paramList(sig.Results(), false) - p.int(0) // dummy value for go:nointerface pragma - ignored by importer - } - - if trace && methods != nil { - p.tracef("<\n} ") - } -} - -type methodsByName []*types.Func - -func (x methodsByName) Len() int { return len(x) } -func (x methodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x methodsByName) Less(i, j int) bool { return x[i].Name() < x[j].Name() } - -func (p *exporter) fieldList(t *types.Struct) { - if trace && t.NumFields() > 0 { - p.tracef("fields {>\n") - defer p.tracef("<\n} ") - } - - p.int(t.NumFields()) - for i := 0; i < t.NumFields(); i++ { - if trace && i > 0 { - p.tracef("\n") - } - p.field(t.Field(i)) - p.string(t.Tag(i)) - } -} - -func (p *exporter) field(f *types.Var) { - if !f.IsField() { - panic(internalError("field expected")) - } - - p.pos(f) - p.fieldName(f) - p.typ(f.Type()) -} - -func (p *exporter) iface(t *types.Interface) { - // TODO(gri): enable importer to load embedded interfaces, - // then emit Embeddeds and ExplicitMethods separately here. - p.int(0) - - n := t.NumMethods() - if trace && n > 0 { - p.tracef("methods {>\n") - defer p.tracef("<\n} ") - } - p.int(n) - for i := 0; i < n; i++ { - if trace && i > 0 { - p.tracef("\n") - } - p.method(t.Method(i)) - } -} - -func (p *exporter) method(m *types.Func) { - sig := m.Type().(*types.Signature) - if sig.Recv() == nil { - panic(internalError("method expected")) - } - - p.pos(m) - p.string(m.Name()) - if m.Name() != "_" && !ast.IsExported(m.Name()) { - p.pkg(m.Pkg(), false) - } - - // interface method; no need to encode receiver. - p.paramList(sig.Params(), sig.Variadic()) - p.paramList(sig.Results(), false) -} - -func (p *exporter) fieldName(f *types.Var) { - name := f.Name() - - if f.Anonymous() { - // anonymous field - we distinguish between 3 cases: - // 1) field name matches base type name and is exported - // 2) field name matches base type name and is not exported - // 3) field name doesn't match base type name (alias name) - bname := basetypeName(f.Type()) - if name == bname { - if ast.IsExported(name) { - name = "" // 1) we don't need to know the field name or package - } else { - name = "?" // 2) use unexported name "?" to force package export - } - } else { - // 3) indicate alias and export name as is - // (this requires an extra "@" but this is a rare case) - p.string("@") - } - } - - p.string(name) - if name != "" && !ast.IsExported(name) { - p.pkg(f.Pkg(), false) - } -} - -func basetypeName(typ types.Type) string { - switch typ := deref(typ).(type) { - case *types.Basic: - return typ.Name() - case *types.Named: - return typ.Obj().Name() - default: - return "" // unnamed type - } -} - -func (p *exporter) paramList(params *types.Tuple, variadic bool) { - // use negative length to indicate unnamed parameters - // (look at the first parameter only since either all - // names are present or all are absent) - n := params.Len() - if n > 0 && params.At(0).Name() == "" { - n = -n - } - p.int(n) - for i := 0; i < params.Len(); i++ { - q := params.At(i) - t := q.Type() - if variadic && i == params.Len()-1 { - t = &dddSlice{t.(*types.Slice).Elem()} - } - p.typ(t) - if n > 0 { - name := q.Name() - p.string(name) - if name != "_" { - p.pkg(q.Pkg(), false) - } - } - p.string("") // no compiler-specific info - } -} - -func (p *exporter) value(x constant.Value) { - if trace { - p.tracef("= ") - } - - switch x.Kind() { - case constant.Bool: - tag := falseTag - if constant.BoolVal(x) { - tag = trueTag - } - p.tag(tag) - - case constant.Int: - if v, exact := constant.Int64Val(x); exact { - // common case: x fits into an int64 - use compact encoding - p.tag(int64Tag) - p.int64(v) - return - } - // uncommon case: large x - use float encoding - // (powers of 2 will be encoded efficiently with exponent) - p.tag(floatTag) - p.float(constant.ToFloat(x)) - - case constant.Float: - p.tag(floatTag) - p.float(x) - - case constant.Complex: - p.tag(complexTag) - p.float(constant.Real(x)) - p.float(constant.Imag(x)) - - case constant.String: - p.tag(stringTag) - p.string(constant.StringVal(x)) - - case constant.Unknown: - // package contains type errors - p.tag(unknownTag) - - default: - panic(internalErrorf("unexpected value %v (%T)", x, x)) - } -} - -func (p *exporter) float(x constant.Value) { - if x.Kind() != constant.Float { - panic(internalErrorf("unexpected constant %v, want float", x)) - } - // extract sign (there is no -0) - sign := constant.Sign(x) - if sign == 0 { - // x == 0 - p.int(0) - return - } - // x != 0 - - var f big.Float - if v, exact := constant.Float64Val(x); exact { - // float64 - f.SetFloat64(v) - } else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int { - // TODO(gri): add big.Rat accessor to constant.Value. - r := valueToRat(num) - f.SetRat(r.Quo(r, valueToRat(denom))) - } else { - // Value too large to represent as a fraction => inaccessible. - // TODO(gri): add big.Float accessor to constant.Value. - f.SetFloat64(math.MaxFloat64) // FIXME - } - - // extract exponent such that 0.5 <= m < 1.0 - var m big.Float - exp := f.MantExp(&m) - - // extract mantissa as *big.Int - // - set exponent large enough so mant satisfies mant.IsInt() - // - get *big.Int from mant - m.SetMantExp(&m, int(m.MinPrec())) - mant, acc := m.Int(nil) - if acc != big.Exact { - panic(internalError("internal error")) - } - - p.int(sign) - p.int(exp) - p.string(string(mant.Bytes())) -} - -func valueToRat(x constant.Value) *big.Rat { - // Convert little-endian to big-endian. - // I can't believe this is necessary. - bytes := constant.Bytes(x) - for i := 0; i < len(bytes)/2; i++ { - bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i] - } - return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes)) -} - -func (p *exporter) bool(b bool) bool { - if trace { - p.tracef("[") - defer p.tracef("= %v] ", b) - } - - x := 0 - if b { - x = 1 - } - p.int(x) - return b -} - -// ---------------------------------------------------------------------------- -// Low-level encoders - -func (p *exporter) index(marker byte, index int) { - if index < 0 { - panic(internalError("invalid index < 0")) - } - if debugFormat { - p.marker('t') - } - if trace { - p.tracef("%c%d ", marker, index) - } - p.rawInt64(int64(index)) -} - -func (p *exporter) tag(tag int) { - if tag >= 0 { - panic(internalError("invalid tag >= 0")) - } - if debugFormat { - p.marker('t') - } - if trace { - p.tracef("%s ", tagString[-tag]) - } - p.rawInt64(int64(tag)) -} - -func (p *exporter) int(x int) { - p.int64(int64(x)) -} - -func (p *exporter) int64(x int64) { - if debugFormat { - p.marker('i') - } - if trace { - p.tracef("%d ", x) - } - p.rawInt64(x) -} - -func (p *exporter) string(s string) { - if debugFormat { - p.marker('s') - } - if trace { - p.tracef("%q ", s) - } - // if we saw the string before, write its index (>= 0) - // (the empty string is mapped to 0) - if i, ok := p.strIndex[s]; ok { - p.rawInt64(int64(i)) - return - } - // otherwise, remember string and write its negative length and bytes - p.strIndex[s] = len(p.strIndex) - p.rawInt64(-int64(len(s))) - for i := 0; i < len(s); i++ { - p.rawByte(s[i]) - } -} - -// marker emits a marker byte and position information which makes -// it easy for a reader to detect if it is "out of sync". Used for -// debugFormat format only. -func (p *exporter) marker(m byte) { - p.rawByte(m) - // Enable this for help tracking down the location - // of an incorrect marker when running in debugFormat. - if false && trace { - p.tracef("#%d ", p.written) - } - p.rawInt64(int64(p.written)) -} - -// rawInt64 should only be used by low-level encoders. -func (p *exporter) rawInt64(x int64) { - var tmp [binary.MaxVarintLen64]byte - n := binary.PutVarint(tmp[:], x) - for i := 0; i < n; i++ { - p.rawByte(tmp[i]) - } -} - -// rawStringln should only be used to emit the initial version string. -func (p *exporter) rawStringln(s string) { - for i := 0; i < len(s); i++ { - p.rawByte(s[i]) - } - p.rawByte('\n') -} - -// rawByte is the bottleneck interface to write to p.out. -// rawByte escapes b as follows (any encoding does that -// hides '$'): -// -// '$' => '|' 'S' -// '|' => '|' '|' -// -// Necessary so other tools can find the end of the -// export data by searching for "$$". -// rawByte should only be used by low-level encoders. -func (p *exporter) rawByte(b byte) { - switch b { - case '$': - // write '$' as '|' 'S' - b = 'S' - fallthrough - case '|': - // write '|' as '|' '|' - p.out.WriteByte('|') - p.written++ - } - p.out.WriteByte(b) - p.written++ -} - -// tracef is like fmt.Printf but it rewrites the format string -// to take care of indentation. -func (p *exporter) tracef(format string, args ...interface{}) { - if strings.ContainsAny(format, "<>\n") { - var buf bytes.Buffer - for i := 0; i < len(format); i++ { - // no need to deal with runes - ch := format[i] - switch ch { - case '>': - p.indent++ - continue - case '<': - p.indent-- - continue - } - buf.WriteByte(ch) - if ch == '\n' { - for j := p.indent; j > 0; j-- { - buf.WriteString(". ") - } - } - } - format = buf.String() - } - fmt.Printf(format, args...) -} - -// Debugging support. -// (tagString is only used when tracing is enabled) -var tagString = [...]string{ - // Packages - -packageTag: "package", - - // Types - -namedTag: "named type", - -arrayTag: "array", - -sliceTag: "slice", - -dddTag: "ddd", - -structTag: "struct", - -pointerTag: "pointer", - -signatureTag: "signature", - -interfaceTag: "interface", - -mapTag: "map", - -chanTag: "chan", - - // Values - -falseTag: "false", - -trueTag: "true", - -int64Tag: "int64", - -floatTag: "float", - -fractionTag: "fraction", - -complexTag: "complex", - -stringTag: "string", - -unknownTag: "unknown", - - // Type aliases - -aliasTag: "alias", -} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go deleted file mode 100644 index e9f73d14a1..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go +++ /dev/null @@ -1,1039 +0,0 @@ -// Copyright 2015 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. - -// This file is a copy of $GOROOT/src/go/internal/gcimporter/bimport.go. - -package gcimporter - -import ( - "encoding/binary" - "fmt" - "go/constant" - "go/token" - "go/types" - "sort" - "strconv" - "strings" - "sync" - "unicode" - "unicode/utf8" -) - -type importer struct { - imports map[string]*types.Package - data []byte - importpath string - buf []byte // for reading strings - version int // export format version - - // object lists - strList []string // in order of appearance - pathList []string // in order of appearance - pkgList []*types.Package // in order of appearance - typList []types.Type // in order of appearance - interfaceList []*types.Interface // for delayed completion only - trackAllTypes bool - - // position encoding - posInfoFormat bool - prevFile string - prevLine int - fake fakeFileSet - - // debugging support - debugFormat bool - read int // bytes read -} - -// BImportData imports a package from the serialized package data -// and returns the number of bytes consumed and a reference to the package. -// If the export data version is not recognized or the format is otherwise -// compromised, an error is returned. -func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { - // catch panics and return them as errors - const currentVersion = 6 - version := -1 // unknown version - defer func() { - if e := recover(); e != nil { - // Return a (possibly nil or incomplete) package unchanged (see #16088). - if version > currentVersion { - err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) - } else { - err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) - } - } - }() - - p := importer{ - imports: imports, - data: data, - importpath: path, - version: version, - strList: []string{""}, // empty string is mapped to 0 - pathList: []string{""}, // empty string is mapped to 0 - fake: fakeFileSet{ - fset: fset, - files: make(map[string]*token.File), - }, - } - - // read version info - var versionstr string - if b := p.rawByte(); b == 'c' || b == 'd' { - // Go1.7 encoding; first byte encodes low-level - // encoding format (compact vs debug). - // For backward-compatibility only (avoid problems with - // old installed packages). Newly compiled packages use - // the extensible format string. - // TODO(gri) Remove this support eventually; after Go1.8. - if b == 'd' { - p.debugFormat = true - } - p.trackAllTypes = p.rawByte() == 'a' - p.posInfoFormat = p.int() != 0 - versionstr = p.string() - if versionstr == "v1" { - version = 0 - } - } else { - // Go1.8 extensible encoding - // read version string and extract version number (ignore anything after the version number) - versionstr = p.rawStringln(b) - if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" { - if v, err := strconv.Atoi(s[1]); err == nil && v > 0 { - version = v - } - } - } - p.version = version - - // read version specific flags - extend as necessary - switch p.version { - // case currentVersion: - // ... - // fallthrough - case currentVersion, 5, 4, 3, 2, 1: - p.debugFormat = p.rawStringln(p.rawByte()) == "debug" - p.trackAllTypes = p.int() != 0 - p.posInfoFormat = p.int() != 0 - case 0: - // Go1.7 encoding format - nothing to do here - default: - errorf("unknown bexport format version %d (%q)", p.version, versionstr) - } - - // --- generic export data --- - - // populate typList with predeclared "known" types - p.typList = append(p.typList, predeclared()...) - - // read package data - pkg = p.pkg() - - // read objects of phase 1 only (see cmd/compile/internal/gc/bexport.go) - objcount := 0 - for { - tag := p.tagOrIndex() - if tag == endTag { - break - } - p.obj(tag) - objcount++ - } - - // self-verification - if count := p.int(); count != objcount { - errorf("got %d objects; want %d", objcount, count) - } - - // ignore compiler-specific import data - - // complete interfaces - // TODO(gri) re-investigate if we still need to do this in a delayed fashion - for _, typ := range p.interfaceList { - typ.Complete() - } - - // record all referenced packages as imports - list := append(([]*types.Package)(nil), p.pkgList[1:]...) - sort.Sort(byPath(list)) - pkg.SetImports(list) - - // package was imported completely and without errors - pkg.MarkComplete() - - return p.read, pkg, nil -} - -func errorf(format string, args ...interface{}) { - panic(fmt.Sprintf(format, args...)) -} - -func (p *importer) pkg() *types.Package { - // if the package was seen before, i is its index (>= 0) - i := p.tagOrIndex() - if i >= 0 { - return p.pkgList[i] - } - - // otherwise, i is the package tag (< 0) - if i != packageTag { - errorf("unexpected package tag %d version %d", i, p.version) - } - - // read package data - name := p.string() - var path string - if p.version >= 5 { - path = p.path() - } else { - path = p.string() - } - if p.version >= 6 { - p.int() // package height; unused by go/types - } - - // we should never see an empty package name - if name == "" { - errorf("empty package name in import") - } - - // an empty path denotes the package we are currently importing; - // it must be the first package we see - if (path == "") != (len(p.pkgList) == 0) { - errorf("package path %q for pkg index %d", path, len(p.pkgList)) - } - - // if the package was imported before, use that one; otherwise create a new one - if path == "" { - path = p.importpath - } - pkg := p.imports[path] - if pkg == nil { - pkg = types.NewPackage(path, name) - p.imports[path] = pkg - } else if pkg.Name() != name { - errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path) - } - p.pkgList = append(p.pkgList, pkg) - - return pkg -} - -// objTag returns the tag value for each object kind. -func objTag(obj types.Object) int { - switch obj.(type) { - case *types.Const: - return constTag - case *types.TypeName: - return typeTag - case *types.Var: - return varTag - case *types.Func: - return funcTag - default: - errorf("unexpected object: %v (%T)", obj, obj) // panics - panic("unreachable") - } -} - -func sameObj(a, b types.Object) bool { - // Because unnamed types are not canonicalized, we cannot simply compare types for - // (pointer) identity. - // Ideally we'd check equality of constant values as well, but this is good enough. - return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type()) -} - -func (p *importer) declare(obj types.Object) { - pkg := obj.Pkg() - if alt := pkg.Scope().Insert(obj); alt != nil { - // This can only trigger if we import a (non-type) object a second time. - // Excluding type aliases, this cannot happen because 1) we only import a package - // once; and b) we ignore compiler-specific export data which may contain - // functions whose inlined function bodies refer to other functions that - // were already imported. - // However, type aliases require reexporting the original type, so we need - // to allow it (see also the comment in cmd/compile/internal/gc/bimport.go, - // method importer.obj, switch case importing functions). - // TODO(gri) review/update this comment once the gc compiler handles type aliases. - if !sameObj(obj, alt) { - errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt) - } - } -} - -func (p *importer) obj(tag int) { - switch tag { - case constTag: - pos := p.pos() - pkg, name := p.qualifiedName() - typ := p.typ(nil, nil) - val := p.value() - p.declare(types.NewConst(pos, pkg, name, typ, val)) - - case aliasTag: - // TODO(gri) verify type alias hookup is correct - pos := p.pos() - pkg, name := p.qualifiedName() - typ := p.typ(nil, nil) - p.declare(types.NewTypeName(pos, pkg, name, typ)) - - case typeTag: - p.typ(nil, nil) - - case varTag: - pos := p.pos() - pkg, name := p.qualifiedName() - typ := p.typ(nil, nil) - p.declare(types.NewVar(pos, pkg, name, typ)) - - case funcTag: - pos := p.pos() - pkg, name := p.qualifiedName() - params, isddd := p.paramList() - result, _ := p.paramList() - sig := types.NewSignature(nil, params, result, isddd) - p.declare(types.NewFunc(pos, pkg, name, sig)) - - default: - errorf("unexpected object tag %d", tag) - } -} - -const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go - -func (p *importer) pos() token.Pos { - if !p.posInfoFormat { - return token.NoPos - } - - file := p.prevFile - line := p.prevLine - delta := p.int() - line += delta - if p.version >= 5 { - if delta == deltaNewFile { - if n := p.int(); n >= 0 { - // file changed - file = p.path() - line = n - } - } - } else { - if delta == 0 { - if n := p.int(); n >= 0 { - // file changed - file = p.prevFile[:n] + p.string() - line = p.int() - } - } - } - p.prevFile = file - p.prevLine = line - - return p.fake.pos(file, line, 0) -} - -// Synthesize a token.Pos -type fakeFileSet struct { - fset *token.FileSet - files map[string]*token.File -} - -func (s *fakeFileSet) pos(file string, line, column int) token.Pos { - // TODO(mdempsky): Make use of column. - - // Since we don't know the set of needed file positions, we - // reserve maxlines positions per file. - const maxlines = 64 * 1024 - f := s.files[file] - if f == nil { - f = s.fset.AddFile(file, -1, maxlines) - s.files[file] = f - // Allocate the fake linebreak indices on first use. - // TODO(adonovan): opt: save ~512KB using a more complex scheme? - fakeLinesOnce.Do(func() { - fakeLines = make([]int, maxlines) - for i := range fakeLines { - fakeLines[i] = i - } - }) - f.SetLines(fakeLines) - } - - if line > maxlines { - line = 1 - } - - // Treat the file as if it contained only newlines - // and column=1: use the line number as the offset. - return f.Pos(line - 1) -} - -var ( - fakeLines []int - fakeLinesOnce sync.Once -) - -func (p *importer) qualifiedName() (pkg *types.Package, name string) { - name = p.string() - pkg = p.pkg() - return -} - -func (p *importer) record(t types.Type) { - p.typList = append(p.typList, t) -} - -// A dddSlice is a types.Type representing ...T parameters. -// It only appears for parameter types and does not escape -// the importer. -type dddSlice struct { - elem types.Type -} - -func (t *dddSlice) Underlying() types.Type { return t } -func (t *dddSlice) String() string { return "..." + t.elem.String() } - -// parent is the package which declared the type; parent == nil means -// the package currently imported. The parent package is needed for -// exported struct fields and interface methods which don't contain -// explicit package information in the export data. -// -// A non-nil tname is used as the "owner" of the result type; i.e., -// the result type is the underlying type of tname. tname is used -// to give interface methods a named receiver type where possible. -func (p *importer) typ(parent *types.Package, tname *types.Named) types.Type { - // if the type was seen before, i is its index (>= 0) - i := p.tagOrIndex() - if i >= 0 { - return p.typList[i] - } - - // otherwise, i is the type tag (< 0) - switch i { - case namedTag: - // read type object - pos := p.pos() - parent, name := p.qualifiedName() - scope := parent.Scope() - obj := scope.Lookup(name) - - // if the object doesn't exist yet, create and insert it - if obj == nil { - obj = types.NewTypeName(pos, parent, name, nil) - scope.Insert(obj) - } - - if _, ok := obj.(*types.TypeName); !ok { - errorf("pkg = %s, name = %s => %s", parent, name, obj) - } - - // associate new named type with obj if it doesn't exist yet - t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) - - // but record the existing type, if any - tname := obj.Type().(*types.Named) // tname is either t0 or the existing type - p.record(tname) - - // read underlying type - t0.SetUnderlying(p.typ(parent, t0)) - - // interfaces don't have associated methods - if types.IsInterface(t0) { - return tname - } - - // read associated methods - for i := p.int(); i > 0; i-- { - // TODO(gri) replace this with something closer to fieldName - pos := p.pos() - name := p.string() - if !exported(name) { - p.pkg() - } - - recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver? - params, isddd := p.paramList() - result, _ := p.paramList() - p.int() // go:nointerface pragma - discarded - - sig := types.NewSignature(recv.At(0), params, result, isddd) - t0.AddMethod(types.NewFunc(pos, parent, name, sig)) - } - - return tname - - case arrayTag: - t := new(types.Array) - if p.trackAllTypes { - p.record(t) - } - - n := p.int64() - *t = *types.NewArray(p.typ(parent, nil), n) - return t - - case sliceTag: - t := new(types.Slice) - if p.trackAllTypes { - p.record(t) - } - - *t = *types.NewSlice(p.typ(parent, nil)) - return t - - case dddTag: - t := new(dddSlice) - if p.trackAllTypes { - p.record(t) - } - - t.elem = p.typ(parent, nil) - return t - - case structTag: - t := new(types.Struct) - if p.trackAllTypes { - p.record(t) - } - - *t = *types.NewStruct(p.fieldList(parent)) - return t - - case pointerTag: - t := new(types.Pointer) - if p.trackAllTypes { - p.record(t) - } - - *t = *types.NewPointer(p.typ(parent, nil)) - return t - - case signatureTag: - t := new(types.Signature) - if p.trackAllTypes { - p.record(t) - } - - params, isddd := p.paramList() - result, _ := p.paramList() - *t = *types.NewSignature(nil, params, result, isddd) - return t - - case interfaceTag: - // Create a dummy entry in the type list. This is safe because we - // cannot expect the interface type to appear in a cycle, as any - // such cycle must contain a named type which would have been - // first defined earlier. - // TODO(gri) Is this still true now that we have type aliases? - // See issue #23225. - n := len(p.typList) - if p.trackAllTypes { - p.record(nil) - } - - var embeddeds []types.Type - for n := p.int(); n > 0; n-- { - p.pos() - embeddeds = append(embeddeds, p.typ(parent, nil)) - } - - t := newInterface(p.methodList(parent, tname), embeddeds) - p.interfaceList = append(p.interfaceList, t) - if p.trackAllTypes { - p.typList[n] = t - } - return t - - case mapTag: - t := new(types.Map) - if p.trackAllTypes { - p.record(t) - } - - key := p.typ(parent, nil) - val := p.typ(parent, nil) - *t = *types.NewMap(key, val) - return t - - case chanTag: - t := new(types.Chan) - if p.trackAllTypes { - p.record(t) - } - - dir := chanDir(p.int()) - val := p.typ(parent, nil) - *t = *types.NewChan(dir, val) - return t - - default: - errorf("unexpected type tag %d", i) // panics - panic("unreachable") - } -} - -func chanDir(d int) types.ChanDir { - // tag values must match the constants in cmd/compile/internal/gc/go.go - switch d { - case 1 /* Crecv */ : - return types.RecvOnly - case 2 /* Csend */ : - return types.SendOnly - case 3 /* Cboth */ : - return types.SendRecv - default: - errorf("unexpected channel dir %d", d) - return 0 - } -} - -func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) { - if n := p.int(); n > 0 { - fields = make([]*types.Var, n) - tags = make([]string, n) - for i := range fields { - fields[i], tags[i] = p.field(parent) - } - } - return -} - -func (p *importer) field(parent *types.Package) (*types.Var, string) { - pos := p.pos() - pkg, name, alias := p.fieldName(parent) - typ := p.typ(parent, nil) - tag := p.string() - - anonymous := false - if name == "" { - // anonymous field - typ must be T or *T and T must be a type name - switch typ := deref(typ).(type) { - case *types.Basic: // basic types are named types - pkg = nil // // objects defined in Universe scope have no package - name = typ.Name() - case *types.Named: - name = typ.Obj().Name() - default: - errorf("named base type expected") - } - anonymous = true - } else if alias { - // anonymous field: we have an explicit name because it's an alias - anonymous = true - } - - return types.NewField(pos, pkg, name, typ, anonymous), tag -} - -func (p *importer) methodList(parent *types.Package, baseType *types.Named) (methods []*types.Func) { - if n := p.int(); n > 0 { - methods = make([]*types.Func, n) - for i := range methods { - methods[i] = p.method(parent, baseType) - } - } - return -} - -func (p *importer) method(parent *types.Package, baseType *types.Named) *types.Func { - pos := p.pos() - pkg, name, _ := p.fieldName(parent) - // If we don't have a baseType, use a nil receiver. - // A receiver using the actual interface type (which - // we don't know yet) will be filled in when we call - // types.Interface.Complete. - var recv *types.Var - if baseType != nil { - recv = types.NewVar(token.NoPos, parent, "", baseType) - } - params, isddd := p.paramList() - result, _ := p.paramList() - sig := types.NewSignature(recv, params, result, isddd) - return types.NewFunc(pos, pkg, name, sig) -} - -func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) { - name = p.string() - pkg = parent - if pkg == nil { - // use the imported package instead - pkg = p.pkgList[0] - } - if p.version == 0 && name == "_" { - // version 0 didn't export a package for _ fields - return - } - switch name { - case "": - // 1) field name matches base type name and is exported: nothing to do - case "?": - // 2) field name matches base type name and is not exported: need package - name = "" - pkg = p.pkg() - case "@": - // 3) field name doesn't match type name (alias) - name = p.string() - alias = true - fallthrough - default: - if !exported(name) { - pkg = p.pkg() - } - } - return -} - -func (p *importer) paramList() (*types.Tuple, bool) { - n := p.int() - if n == 0 { - return nil, false - } - // negative length indicates unnamed parameters - named := true - if n < 0 { - n = -n - named = false - } - // n > 0 - params := make([]*types.Var, n) - isddd := false - for i := range params { - params[i], isddd = p.param(named) - } - return types.NewTuple(params...), isddd -} - -func (p *importer) param(named bool) (*types.Var, bool) { - t := p.typ(nil, nil) - td, isddd := t.(*dddSlice) - if isddd { - t = types.NewSlice(td.elem) - } - - var pkg *types.Package - var name string - if named { - name = p.string() - if name == "" { - errorf("expected named parameter") - } - if name != "_" { - pkg = p.pkg() - } - if i := strings.Index(name, "·"); i > 0 { - name = name[:i] // cut off gc-specific parameter numbering - } - } - - // read and discard compiler-specific info - p.string() - - return types.NewVar(token.NoPos, pkg, name, t), isddd -} - -func exported(name string) bool { - ch, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(ch) -} - -func (p *importer) value() constant.Value { - switch tag := p.tagOrIndex(); tag { - case falseTag: - return constant.MakeBool(false) - case trueTag: - return constant.MakeBool(true) - case int64Tag: - return constant.MakeInt64(p.int64()) - case floatTag: - return p.float() - case complexTag: - re := p.float() - im := p.float() - return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) - case stringTag: - return constant.MakeString(p.string()) - case unknownTag: - return constant.MakeUnknown() - default: - errorf("unexpected value tag %d", tag) // panics - panic("unreachable") - } -} - -func (p *importer) float() constant.Value { - sign := p.int() - if sign == 0 { - return constant.MakeInt64(0) - } - - exp := p.int() - mant := []byte(p.string()) // big endian - - // remove leading 0's if any - for len(mant) > 0 && mant[0] == 0 { - mant = mant[1:] - } - - // convert to little endian - // TODO(gri) go/constant should have a more direct conversion function - // (e.g., once it supports a big.Float based implementation) - for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 { - mant[i], mant[j] = mant[j], mant[i] - } - - // adjust exponent (constant.MakeFromBytes creates an integer value, - // but mant represents the mantissa bits such that 0.5 <= mant < 1.0) - exp -= len(mant) << 3 - if len(mant) > 0 { - for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 { - exp++ - } - } - - x := constant.MakeFromBytes(mant) - switch { - case exp < 0: - d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) - x = constant.BinaryOp(x, token.QUO, d) - case exp > 0: - x = constant.Shift(x, token.SHL, uint(exp)) - } - - if sign < 0 { - x = constant.UnaryOp(token.SUB, x, 0) - } - return x -} - -// ---------------------------------------------------------------------------- -// Low-level decoders - -func (p *importer) tagOrIndex() int { - if p.debugFormat { - p.marker('t') - } - - return int(p.rawInt64()) -} - -func (p *importer) int() int { - x := p.int64() - if int64(int(x)) != x { - errorf("exported integer too large") - } - return int(x) -} - -func (p *importer) int64() int64 { - if p.debugFormat { - p.marker('i') - } - - return p.rawInt64() -} - -func (p *importer) path() string { - if p.debugFormat { - p.marker('p') - } - // if the path was seen before, i is its index (>= 0) - // (the empty string is at index 0) - i := p.rawInt64() - if i >= 0 { - return p.pathList[i] - } - // otherwise, i is the negative path length (< 0) - a := make([]string, -i) - for n := range a { - a[n] = p.string() - } - s := strings.Join(a, "/") - p.pathList = append(p.pathList, s) - return s -} - -func (p *importer) string() string { - if p.debugFormat { - p.marker('s') - } - // if the string was seen before, i is its index (>= 0) - // (the empty string is at index 0) - i := p.rawInt64() - if i >= 0 { - return p.strList[i] - } - // otherwise, i is the negative string length (< 0) - if n := int(-i); n <= cap(p.buf) { - p.buf = p.buf[:n] - } else { - p.buf = make([]byte, n) - } - for i := range p.buf { - p.buf[i] = p.rawByte() - } - s := string(p.buf) - p.strList = append(p.strList, s) - return s -} - -func (p *importer) marker(want byte) { - if got := p.rawByte(); got != want { - errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read) - } - - pos := p.read - if n := int(p.rawInt64()); n != pos { - errorf("incorrect position: got %d; want %d", n, pos) - } -} - -// rawInt64 should only be used by low-level decoders. -func (p *importer) rawInt64() int64 { - i, err := binary.ReadVarint(p) - if err != nil { - errorf("read error: %v", err) - } - return i -} - -// rawStringln should only be used to read the initial version string. -func (p *importer) rawStringln(b byte) string { - p.buf = p.buf[:0] - for b != '\n' { - p.buf = append(p.buf, b) - b = p.rawByte() - } - return string(p.buf) -} - -// needed for binary.ReadVarint in rawInt64 -func (p *importer) ReadByte() (byte, error) { - return p.rawByte(), nil -} - -// byte is the bottleneck interface for reading p.data. -// It unescapes '|' 'S' to '$' and '|' '|' to '|'. -// rawByte should only be used by low-level decoders. -func (p *importer) rawByte() byte { - b := p.data[0] - r := 1 - if b == '|' { - b = p.data[1] - r = 2 - switch b { - case 'S': - b = '$' - case '|': - // nothing to do - default: - errorf("unexpected escape sequence in export data") - } - } - p.data = p.data[r:] - p.read += r - return b - -} - -// ---------------------------------------------------------------------------- -// Export format - -// Tags. Must be < 0. -const ( - // Objects - packageTag = -(iota + 1) - constTag - typeTag - varTag - funcTag - endTag - - // Types - namedTag - arrayTag - sliceTag - dddTag - structTag - pointerTag - signatureTag - interfaceTag - mapTag - chanTag - - // Values - falseTag - trueTag - int64Tag - floatTag - fractionTag // not used by gc - complexTag - stringTag - nilTag // only used by gc (appears in exported inlined function bodies) - unknownTag // not used by gc (only appears in packages with errors) - - // Type aliases - aliasTag -) - -var predeclOnce sync.Once -var predecl []types.Type // initialized lazily - -func predeclared() []types.Type { - predeclOnce.Do(func() { - // initialize lazily to be sure that all - // elements have been initialized before - predecl = []types.Type{ // basic types - types.Typ[types.Bool], - types.Typ[types.Int], - types.Typ[types.Int8], - types.Typ[types.Int16], - types.Typ[types.Int32], - types.Typ[types.Int64], - types.Typ[types.Uint], - types.Typ[types.Uint8], - types.Typ[types.Uint16], - types.Typ[types.Uint32], - types.Typ[types.Uint64], - types.Typ[types.Uintptr], - types.Typ[types.Float32], - types.Typ[types.Float64], - types.Typ[types.Complex64], - types.Typ[types.Complex128], - types.Typ[types.String], - - // basic type aliases - types.Universe.Lookup("byte").Type(), - types.Universe.Lookup("rune").Type(), - - // error - types.Universe.Lookup("error").Type(), - - // untyped types - types.Typ[types.UntypedBool], - types.Typ[types.UntypedInt], - types.Typ[types.UntypedRune], - types.Typ[types.UntypedFloat], - types.Typ[types.UntypedComplex], - types.Typ[types.UntypedString], - types.Typ[types.UntypedNil], - - // package unsafe - types.Typ[types.UnsafePointer], - - // invalid type - types.Typ[types.Invalid], // only appears in packages with errors - - // used internally by gc; never used by this package or in .a files - anyType{}, - } - }) - return predecl -} - -type anyType struct{} - -func (t anyType) Underlying() types.Type { return t } -func (t anyType) String() string { return "any" } diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go b/vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go deleted file mode 100644 index f33dc5613e..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/exportdata.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2011 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. - -// This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go. - -// This file implements FindExportData. - -package gcimporter - -import ( - "bufio" - "fmt" - "io" - "strconv" - "strings" -) - -func readGopackHeader(r *bufio.Reader) (name string, size int, err error) { - // See $GOROOT/include/ar.h. - hdr := make([]byte, 16+12+6+6+8+10+2) - _, err = io.ReadFull(r, hdr) - if err != nil { - return - } - // leave for debugging - if false { - fmt.Printf("header: %s", hdr) - } - s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10])) - size, err = strconv.Atoi(s) - if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' { - err = fmt.Errorf("invalid archive header") - return - } - name = strings.TrimSpace(string(hdr[:16])) - return -} - -// FindExportData positions the reader r at the beginning of the -// export data section of an underlying GC-created object/archive -// file by reading from it. The reader must be positioned at the -// start of the file before calling this function. The hdr result -// is the string before the export data, either "$$" or "$$B". -// -func FindExportData(r *bufio.Reader) (hdr string, err error) { - // Read first line to make sure this is an object file. - line, err := r.ReadSlice('\n') - if err != nil { - err = fmt.Errorf("can't find export data (%v)", err) - return - } - - if string(line) == "!<arch>\n" { - // Archive file. Scan to __.PKGDEF. - var name string - if name, _, err = readGopackHeader(r); err != nil { - return - } - - // First entry should be __.PKGDEF. - if name != "__.PKGDEF" { - err = fmt.Errorf("go archive is missing __.PKGDEF") - return - } - - // Read first line of __.PKGDEF data, so that line - // is once again the first line of the input. - if line, err = r.ReadSlice('\n'); err != nil { - err = fmt.Errorf("can't find export data (%v)", err) - return - } - } - - // Now at __.PKGDEF in archive or still at beginning of file. - // Either way, line should begin with "go object ". - if !strings.HasPrefix(string(line), "go object ") { - err = fmt.Errorf("not a Go object file") - return - } - - // Skip over object header to export data. - // Begins after first line starting with $$. - for line[0] != '$' { - if line, err = r.ReadSlice('\n'); err != nil { - err = fmt.Errorf("can't find export data (%v)", err) - return - } - } - hdr = string(line) - - return -} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go b/vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go deleted file mode 100644 index e8cba6b237..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/gcimporter.go +++ /dev/null @@ -1,1078 +0,0 @@ -// Copyright 2011 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. - -// This file is a modified copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go, -// but it also contains the original source-based importer code for Go1.6. -// Once we stop supporting 1.6, we can remove that code. - -// Package gcimporter provides various functions for reading -// gc-generated object files that can be used to implement the -// Importer interface defined by the Go 1.5 standard library package. -package gcimporter // import "golang.org/x/tools/go/internal/gcimporter" - -import ( - "bufio" - "errors" - "fmt" - "go/build" - "go/constant" - "go/token" - "go/types" - "io" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strconv" - "strings" - "text/scanner" -) - -// debugging/development support -const debug = false - -var pkgExts = [...]string{".a", ".o"} - -// FindPkg returns the filename and unique package id for an import -// path based on package information provided by build.Import (using -// the build.Default build.Context). A relative srcDir is interpreted -// relative to the current working directory. -// If no file was found, an empty filename is returned. -// -func FindPkg(path, srcDir string) (filename, id string) { - if path == "" { - return - } - - var noext string - switch { - default: - // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" - // Don't require the source files to be present. - if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 - srcDir = abs - } - bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) - if bp.PkgObj == "" { - id = path // make sure we have an id to print in error message - return - } - noext = strings.TrimSuffix(bp.PkgObj, ".a") - id = bp.ImportPath - - case build.IsLocalImport(path): - // "./x" -> "/this/directory/x.ext", "/this/directory/x" - noext = filepath.Join(srcDir, path) - id = noext - - case filepath.IsAbs(path): - // for completeness only - go/build.Import - // does not support absolute imports - // "/x" -> "/x.ext", "/x" - noext = path - id = path - } - - if false { // for debugging - if path != id { - fmt.Printf("%s -> %s\n", path, id) - } - } - - // try extensions - for _, ext := range pkgExts { - filename = noext + ext - if f, err := os.Stat(filename); err == nil && !f.IsDir() { - return - } - } - - filename = "" // not found - return -} - -// ImportData imports a package by reading the gc-generated export data, -// adds the corresponding package object to the packages map indexed by id, -// and returns the object. -// -// The packages map must contains all packages already imported. The data -// reader position must be the beginning of the export data section. The -// filename is only used in error messages. -// -// If packages[id] contains the completely imported package, that package -// can be used directly, and there is no need to call this function (but -// there is also no harm but for extra time used). -// -func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) { - // support for parser error handling - defer func() { - switch r := recover().(type) { - case nil: - // nothing to do - case importError: - err = r - default: - panic(r) // internal error - } - }() - - var p parser - p.init(filename, id, data, packages) - pkg = p.parseExport() - - return -} - -// Import imports a gc-generated package given its import path and srcDir, adds -// the corresponding package object to the packages map, and returns the object. -// The packages map must contain all packages already imported. -// -func Import(packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) { - var rc io.ReadCloser - var filename, id string - if lookup != nil { - // With custom lookup specified, assume that caller has - // converted path to a canonical import path for use in the map. - if path == "unsafe" { - return types.Unsafe, nil - } - id = path - - // No need to re-import if the package was imported completely before. - if pkg = packages[id]; pkg != nil && pkg.Complete() { - return - } - f, err := lookup(path) - if err != nil { - return nil, err - } - rc = f - } else { - filename, id = FindPkg(path, srcDir) - if filename == "" { - if path == "unsafe" { - return types.Unsafe, nil - } - return nil, fmt.Errorf("can't find import: %q", id) - } - - // no need to re-import if the package was imported completely before - if pkg = packages[id]; pkg != nil && pkg.Complete() { - return - } - - // open file - f, err := os.Open(filename) - if err != nil { - return nil, err - } - defer func() { - if err != nil { - // add file name to error - err = fmt.Errorf("%s: %v", filename, err) - } - }() - rc = f - } - defer rc.Close() - - var hdr string - buf := bufio.NewReader(rc) - if hdr, err = FindExportData(buf); err != nil { - return - } - - switch hdr { - case "$$\n": - // Work-around if we don't have a filename; happens only if lookup != nil. - // Either way, the filename is only needed for importer error messages, so - // this is fine. - if filename == "" { - filename = path - } - return ImportData(packages, filename, id, buf) - - case "$$B\n": - var data []byte - data, err = ioutil.ReadAll(buf) - if err != nil { - break - } - - // TODO(gri): allow clients of go/importer to provide a FileSet. - // Or, define a new standard go/types/gcexportdata package. - fset := token.NewFileSet() - - // The indexed export format starts with an 'i'; the older - // binary export format starts with a 'c', 'd', or 'v' - // (from "version"). Select appropriate importer. - if len(data) > 0 && data[0] == 'i' { - _, pkg, err = IImportData(fset, packages, data[1:], id) - } else { - _, pkg, err = BImportData(fset, packages, data, id) - } - - default: - err = fmt.Errorf("unknown export data header: %q", hdr) - } - - return -} - -// ---------------------------------------------------------------------------- -// Parser - -// TODO(gri) Imported objects don't have position information. -// Ideally use the debug table line info; alternatively -// create some fake position (or the position of the -// import). That way error messages referring to imported -// objects can print meaningful information. - -// parser parses the exports inside a gc compiler-produced -// object/archive file and populates its scope with the results. -type parser struct { - scanner scanner.Scanner - tok rune // current token - lit string // literal string; only valid for Ident, Int, String tokens - id string // package id of imported package - sharedPkgs map[string]*types.Package // package id -> package object (across importer) - localPkgs map[string]*types.Package // package id -> package object (just this package) -} - -func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) { - p.scanner.Init(src) - p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } - p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments - p.scanner.Whitespace = 1<<'\t' | 1<<' ' - p.scanner.Filename = filename // for good error messages - p.next() - p.id = id - p.sharedPkgs = packages - if debug { - // check consistency of packages map - for _, pkg := range packages { - if pkg.Name() == "" { - fmt.Printf("no package name for %s\n", pkg.Path()) - } - } - } -} - -func (p *parser) next() { - p.tok = p.scanner.Scan() - switch p.tok { - case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·': - p.lit = p.scanner.TokenText() - default: - p.lit = "" - } - if debug { - fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit) - } -} - -func declTypeName(pkg *types.Package, name string) *types.TypeName { - scope := pkg.Scope() - if obj := scope.Lookup(name); obj != nil { - return obj.(*types.TypeName) - } - obj := types.NewTypeName(token.NoPos, pkg, name, nil) - // a named type may be referred to before the underlying type - // is known - set it up - types.NewNamed(obj, nil, nil) - scope.Insert(obj) - return obj -} - -// ---------------------------------------------------------------------------- -// Error handling - -// Internal errors are boxed as importErrors. -type importError struct { - pos scanner.Position - err error -} - -func (e importError) Error() string { - return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err) -} - -func (p *parser) error(err interface{}) { - if s, ok := err.(string); ok { - err = errors.New(s) - } - // panic with a runtime.Error if err is not an error - panic(importError{p.scanner.Pos(), err.(error)}) -} - -func (p *parser) errorf(format string, args ...interface{}) { - p.error(fmt.Sprintf(format, args...)) -} - -func (p *parser) expect(tok rune) string { - lit := p.lit - if p.tok != tok { - p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) - } - p.next() - return lit -} - -func (p *parser) expectSpecial(tok string) { - sep := 'x' // not white space - i := 0 - for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' { - sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token - p.next() - i++ - } - if i < len(tok) { - p.errorf("expected %q, got %q", tok, tok[0:i]) - } -} - -func (p *parser) expectKeyword(keyword string) { - lit := p.expect(scanner.Ident) - if lit != keyword { - p.errorf("expected keyword %s, got %q", keyword, lit) - } -} - -// ---------------------------------------------------------------------------- -// Qualified and unqualified names - -// PackageId = string_lit . -// -func (p *parser) parsePackageID() string { - id, err := strconv.Unquote(p.expect(scanner.String)) - if err != nil { - p.error(err) - } - // id == "" stands for the imported package id - // (only known at time of package installation) - if id == "" { - id = p.id - } - return id -} - -// PackageName = ident . -// -func (p *parser) parsePackageName() string { - return p.expect(scanner.Ident) -} - -// dotIdentifier = ( ident | '·' ) { ident | int | '·' } . -func (p *parser) parseDotIdent() string { - ident := "" - if p.tok != scanner.Int { - sep := 'x' // not white space - for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' { - ident += p.lit - sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token - p.next() - } - } - if ident == "" { - p.expect(scanner.Ident) // use expect() for error handling - } - return ident -} - -// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) . -// -func (p *parser) parseQualifiedName() (id, name string) { - p.expect('@') - id = p.parsePackageID() - p.expect('.') - // Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields. - if p.tok == '?' { - p.next() - } else { - name = p.parseDotIdent() - } - return -} - -// getPkg returns the package for a given id. If the package is -// not found, create the package and add it to the p.localPkgs -// and p.sharedPkgs maps. name is the (expected) name of the -// package. If name == "", the package name is expected to be -// set later via an import clause in the export data. -// -// id identifies a package, usually by a canonical package path like -// "encoding/json" but possibly by a non-canonical import path like -// "./json". -// -func (p *parser) getPkg(id, name string) *types.Package { - // package unsafe is not in the packages maps - handle explicitly - if id == "unsafe" { - return types.Unsafe - } - - pkg := p.localPkgs[id] - if pkg == nil { - // first import of id from this package - pkg = p.sharedPkgs[id] - if pkg == nil { - // first import of id by this importer; - // add (possibly unnamed) pkg to shared packages - pkg = types.NewPackage(id, name) - p.sharedPkgs[id] = pkg - } - // add (possibly unnamed) pkg to local packages - if p.localPkgs == nil { - p.localPkgs = make(map[string]*types.Package) - } - p.localPkgs[id] = pkg - } else if name != "" { - // package exists already and we have an expected package name; - // make sure names match or set package name if necessary - if pname := pkg.Name(); pname == "" { - pkg.SetName(name) - } else if pname != name { - p.errorf("%s package name mismatch: %s (given) vs %s (expected)", id, pname, name) - } - } - return pkg -} - -// parseExportedName is like parseQualifiedName, but -// the package id is resolved to an imported *types.Package. -// -func (p *parser) parseExportedName() (pkg *types.Package, name string) { - id, name := p.parseQualifiedName() - pkg = p.getPkg(id, "") - return -} - -// ---------------------------------------------------------------------------- -// Types - -// BasicType = identifier . -// -func (p *parser) parseBasicType() types.Type { - id := p.expect(scanner.Ident) - obj := types.Universe.Lookup(id) - if obj, ok := obj.(*types.TypeName); ok { - return obj.Type() - } - p.errorf("not a basic type: %s", id) - return nil -} - -// ArrayType = "[" int_lit "]" Type . -// -func (p *parser) parseArrayType(parent *types.Package) types.Type { - // "[" already consumed and lookahead known not to be "]" - lit := p.expect(scanner.Int) - p.expect(']') - elem := p.parseType(parent) - n, err := strconv.ParseInt(lit, 10, 64) - if err != nil { - p.error(err) - } - return types.NewArray(elem, n) -} - -// MapType = "map" "[" Type "]" Type . -// -func (p *parser) parseMapType(parent *types.Package) types.Type { - p.expectKeyword("map") - p.expect('[') - key := p.parseType(parent) - p.expect(']') - elem := p.parseType(parent) - return types.NewMap(key, elem) -} - -// Name = identifier | "?" | QualifiedName . -// -// For unqualified and anonymous names, the returned package is the parent -// package unless parent == nil, in which case the returned package is the -// package being imported. (The parent package is not nil if the name -// is an unqualified struct field or interface method name belonging to a -// type declared in another package.) -// -// For qualified names, the returned package is nil (and not created if -// it doesn't exist yet) unless materializePkg is set (which creates an -// unnamed package with valid package path). In the latter case, a -// subsequent import clause is expected to provide a name for the package. -// -func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) { - pkg = parent - if pkg == nil { - pkg = p.sharedPkgs[p.id] - } - switch p.tok { - case scanner.Ident: - name = p.lit - p.next() - case '?': - // anonymous - p.next() - case '@': - // exported name prefixed with package path - pkg = nil - var id string - id, name = p.parseQualifiedName() - if materializePkg { - pkg = p.getPkg(id, "") - } - default: - p.error("name expected") - } - return -} - -func deref(typ types.Type) types.Type { - if p, _ := typ.(*types.Pointer); p != nil { - return p.Elem() - } - return typ -} - -// Field = Name Type [ string_lit ] . -// -func (p *parser) parseField(parent *types.Package) (*types.Var, string) { - pkg, name := p.parseName(parent, true) - - if name == "_" { - // Blank fields should be package-qualified because they - // are unexported identifiers, but gc does not qualify them. - // Assuming that the ident belongs to the current package - // causes types to change during re-exporting, leading - // to spurious "can't assign A to B" errors from go/types. - // As a workaround, pretend all blank fields belong - // to the same unique dummy package. - const blankpkg = "<_>" - pkg = p.getPkg(blankpkg, blankpkg) - } - - typ := p.parseType(parent) - anonymous := false - if name == "" { - // anonymous field - typ must be T or *T and T must be a type name - switch typ := deref(typ).(type) { - case *types.Basic: // basic types are named types - pkg = nil // objects defined in Universe scope have no package - name = typ.Name() - case *types.Named: - name = typ.Obj().Name() - default: - p.errorf("anonymous field expected") - } - anonymous = true - } - tag := "" - if p.tok == scanner.String { - s := p.expect(scanner.String) - var err error - tag, err = strconv.Unquote(s) - if err != nil { - p.errorf("invalid struct tag %s: %s", s, err) - } - } - return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag -} - -// StructType = "struct" "{" [ FieldList ] "}" . -// FieldList = Field { ";" Field } . -// -func (p *parser) parseStructType(parent *types.Package) types.Type { - var fields []*types.Var - var tags []string - - p.expectKeyword("struct") - p.expect('{') - for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { - if i > 0 { - p.expect(';') - } - fld, tag := p.parseField(parent) - if tag != "" && tags == nil { - tags = make([]string, i) - } - if tags != nil { - tags = append(tags, tag) - } - fields = append(fields, fld) - } - p.expect('}') - - return types.NewStruct(fields, tags) -} - -// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] . -// -func (p *parser) parseParameter() (par *types.Var, isVariadic bool) { - _, name := p.parseName(nil, false) - // remove gc-specific parameter numbering - if i := strings.Index(name, "·"); i >= 0 { - name = name[:i] - } - if p.tok == '.' { - p.expectSpecial("...") - isVariadic = true - } - typ := p.parseType(nil) - if isVariadic { - typ = types.NewSlice(typ) - } - // ignore argument tag (e.g. "noescape") - if p.tok == scanner.String { - p.next() - } - // TODO(gri) should we provide a package? - par = types.NewVar(token.NoPos, nil, name, typ) - return -} - -// Parameters = "(" [ ParameterList ] ")" . -// ParameterList = { Parameter "," } Parameter . -// -func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) { - p.expect('(') - for p.tok != ')' && p.tok != scanner.EOF { - if len(list) > 0 { - p.expect(',') - } - par, variadic := p.parseParameter() - list = append(list, par) - if variadic { - if isVariadic { - p.error("... not on final argument") - } - isVariadic = true - } - } - p.expect(')') - - return -} - -// Signature = Parameters [ Result ] . -// Result = Type | Parameters . -// -func (p *parser) parseSignature(recv *types.Var) *types.Signature { - params, isVariadic := p.parseParameters() - - // optional result type - var results []*types.Var - if p.tok == '(' { - var variadic bool - results, variadic = p.parseParameters() - if variadic { - p.error("... not permitted on result type") - } - } - - return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic) -} - -// InterfaceType = "interface" "{" [ MethodList ] "}" . -// MethodList = Method { ";" Method } . -// Method = Name Signature . -// -// The methods of embedded interfaces are always "inlined" -// by the compiler and thus embedded interfaces are never -// visible in the export data. -// -func (p *parser) parseInterfaceType(parent *types.Package) types.Type { - var methods []*types.Func - - p.expectKeyword("interface") - p.expect('{') - for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { - if i > 0 { - p.expect(';') - } - pkg, name := p.parseName(parent, true) - sig := p.parseSignature(nil) - methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig)) - } - p.expect('}') - - // Complete requires the type's embedded interfaces to be fully defined, - // but we do not define any - return newInterface(methods, nil).Complete() -} - -// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type . -// -func (p *parser) parseChanType(parent *types.Package) types.Type { - dir := types.SendRecv - if p.tok == scanner.Ident { - p.expectKeyword("chan") - if p.tok == '<' { - p.expectSpecial("<-") - dir = types.SendOnly - } - } else { - p.expectSpecial("<-") - p.expectKeyword("chan") - dir = types.RecvOnly - } - elem := p.parseType(parent) - return types.NewChan(dir, elem) -} - -// Type = -// BasicType | TypeName | ArrayType | SliceType | StructType | -// PointerType | FuncType | InterfaceType | MapType | ChanType | -// "(" Type ")" . -// -// BasicType = ident . -// TypeName = ExportedName . -// SliceType = "[" "]" Type . -// PointerType = "*" Type . -// FuncType = "func" Signature . -// -func (p *parser) parseType(parent *types.Package) types.Type { - switch p.tok { - case scanner.Ident: - switch p.lit { - default: - return p.parseBasicType() - case "struct": - return p.parseStructType(parent) - case "func": - // FuncType - p.next() - return p.parseSignature(nil) - case "interface": - return p.parseInterfaceType(parent) - case "map": - return p.parseMapType(parent) - case "chan": - return p.parseChanType(parent) - } - case '@': - // TypeName - pkg, name := p.parseExportedName() - return declTypeName(pkg, name).Type() - case '[': - p.next() // look ahead - if p.tok == ']' { - // SliceType - p.next() - return types.NewSlice(p.parseType(parent)) - } - return p.parseArrayType(parent) - case '*': - // PointerType - p.next() - return types.NewPointer(p.parseType(parent)) - case '<': - return p.parseChanType(parent) - case '(': - // "(" Type ")" - p.next() - typ := p.parseType(parent) - p.expect(')') - return typ - } - p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit) - return nil -} - -// ---------------------------------------------------------------------------- -// Declarations - -// ImportDecl = "import" PackageName PackageId . -// -func (p *parser) parseImportDecl() { - p.expectKeyword("import") - name := p.parsePackageName() - p.getPkg(p.parsePackageID(), name) -} - -// int_lit = [ "+" | "-" ] { "0" ... "9" } . -// -func (p *parser) parseInt() string { - s := "" - switch p.tok { - case '-': - s = "-" - p.next() - case '+': - p.next() - } - return s + p.expect(scanner.Int) -} - -// number = int_lit [ "p" int_lit ] . -// -func (p *parser) parseNumber() (typ *types.Basic, val constant.Value) { - // mantissa - mant := constant.MakeFromLiteral(p.parseInt(), token.INT, 0) - if mant == nil { - panic("invalid mantissa") - } - - if p.lit == "p" { - // exponent (base 2) - p.next() - exp, err := strconv.ParseInt(p.parseInt(), 10, 0) - if err != nil { - p.error(err) - } - if exp < 0 { - denom := constant.MakeInt64(1) - denom = constant.Shift(denom, token.SHL, uint(-exp)) - typ = types.Typ[types.UntypedFloat] - val = constant.BinaryOp(mant, token.QUO, denom) - return - } - if exp > 0 { - mant = constant.Shift(mant, token.SHL, uint(exp)) - } - typ = types.Typ[types.UntypedFloat] - val = mant - return - } - - typ = types.Typ[types.UntypedInt] - val = mant - return -} - -// ConstDecl = "const" ExportedName [ Type ] "=" Literal . -// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit . -// bool_lit = "true" | "false" . -// complex_lit = "(" float_lit "+" float_lit "i" ")" . -// rune_lit = "(" int_lit "+" int_lit ")" . -// string_lit = `"` { unicode_char } `"` . -// -func (p *parser) parseConstDecl() { - p.expectKeyword("const") - pkg, name := p.parseExportedName() - - var typ0 types.Type - if p.tok != '=' { - // constant types are never structured - no need for parent type - typ0 = p.parseType(nil) - } - - p.expect('=') - var typ types.Type - var val constant.Value - switch p.tok { - case scanner.Ident: - // bool_lit - if p.lit != "true" && p.lit != "false" { - p.error("expected true or false") - } - typ = types.Typ[types.UntypedBool] - val = constant.MakeBool(p.lit == "true") - p.next() - - case '-', scanner.Int: - // int_lit - typ, val = p.parseNumber() - - case '(': - // complex_lit or rune_lit - p.next() - if p.tok == scanner.Char { - p.next() - p.expect('+') - typ = types.Typ[types.UntypedRune] - _, val = p.parseNumber() - p.expect(')') - break - } - _, re := p.parseNumber() - p.expect('+') - _, im := p.parseNumber() - p.expectKeyword("i") - p.expect(')') - typ = types.Typ[types.UntypedComplex] - val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) - - case scanner.Char: - // rune_lit - typ = types.Typ[types.UntypedRune] - val = constant.MakeFromLiteral(p.lit, token.CHAR, 0) - p.next() - - case scanner.String: - // string_lit - typ = types.Typ[types.UntypedString] - val = constant.MakeFromLiteral(p.lit, token.STRING, 0) - p.next() - - default: - p.errorf("expected literal got %s", scanner.TokenString(p.tok)) - } - - if typ0 == nil { - typ0 = typ - } - - pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val)) -} - -// TypeDecl = "type" ExportedName Type . -// -func (p *parser) parseTypeDecl() { - p.expectKeyword("type") - pkg, name := p.parseExportedName() - obj := declTypeName(pkg, name) - - // The type object may have been imported before and thus already - // have a type associated with it. We still need to parse the type - // structure, but throw it away if the object already has a type. - // This ensures that all imports refer to the same type object for - // a given type declaration. - typ := p.parseType(pkg) - - if name := obj.Type().(*types.Named); name.Underlying() == nil { - name.SetUnderlying(typ) - } -} - -// VarDecl = "var" ExportedName Type . -// -func (p *parser) parseVarDecl() { - p.expectKeyword("var") - pkg, name := p.parseExportedName() - typ := p.parseType(pkg) - pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ)) -} - -// Func = Signature [ Body ] . -// Body = "{" ... "}" . -// -func (p *parser) parseFunc(recv *types.Var) *types.Signature { - sig := p.parseSignature(recv) - if p.tok == '{' { - p.next() - for i := 1; i > 0; p.next() { - switch p.tok { - case '{': - i++ - case '}': - i-- - } - } - } - return sig -} - -// MethodDecl = "func" Receiver Name Func . -// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" . -// -func (p *parser) parseMethodDecl() { - // "func" already consumed - p.expect('(') - recv, _ := p.parseParameter() // receiver - p.expect(')') - - // determine receiver base type object - base := deref(recv.Type()).(*types.Named) - - // parse method name, signature, and possibly inlined body - _, name := p.parseName(nil, false) - sig := p.parseFunc(recv) - - // methods always belong to the same package as the base type object - pkg := base.Obj().Pkg() - - // add method to type unless type was imported before - // and method exists already - // TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small. - base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig)) -} - -// FuncDecl = "func" ExportedName Func . -// -func (p *parser) parseFuncDecl() { - // "func" already consumed - pkg, name := p.parseExportedName() - typ := p.parseFunc(nil) - pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ)) -} - -// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" . -// -func (p *parser) parseDecl() { - if p.tok == scanner.Ident { - switch p.lit { - case "import": - p.parseImportDecl() - case "const": - p.parseConstDecl() - case "type": - p.parseTypeDecl() - case "var": - p.parseVarDecl() - case "func": - p.next() // look ahead - if p.tok == '(' { - p.parseMethodDecl() - } else { - p.parseFuncDecl() - } - } - } - p.expect('\n') -} - -// ---------------------------------------------------------------------------- -// Export - -// Export = "PackageClause { Decl } "$$" . -// PackageClause = "package" PackageName [ "safe" ] "\n" . -// -func (p *parser) parseExport() *types.Package { - p.expectKeyword("package") - name := p.parsePackageName() - if p.tok == scanner.Ident && p.lit == "safe" { - // package was compiled with -u option - ignore - p.next() - } - p.expect('\n') - - pkg := p.getPkg(p.id, name) - - for p.tok != '$' && p.tok != scanner.EOF { - p.parseDecl() - } - - if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' { - // don't call next()/expect() since reading past the - // export data may cause scanner errors (e.g. NUL chars) - p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch) - } - - if n := p.scanner.ErrorCount; n != 0 { - p.errorf("expected no scanner errors, got %d", n) - } - - // Record all locally referenced packages as imports. - var imports []*types.Package - for id, pkg2 := range p.localPkgs { - if pkg2.Name() == "" { - p.errorf("%s package has no name", id) - } - if id == p.id { - continue // avoid self-edge - } - imports = append(imports, pkg2) - } - sort.Sort(byPath(imports)) - pkg.SetImports(imports) - - // package was imported completely and without errors - pkg.MarkComplete() - - return pkg -} - -type byPath []*types.Package - -func (a byPath) Len() int { return len(a) } -func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() } diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go deleted file mode 100644 index 4be32a2e55..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go +++ /dev/null @@ -1,739 +0,0 @@ -// Copyright 2019 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. - -// Indexed binary package export. -// This file was derived from $GOROOT/src/cmd/compile/internal/gc/iexport.go; -// see that file for specification of the format. - -package gcimporter - -import ( - "bytes" - "encoding/binary" - "go/ast" - "go/constant" - "go/token" - "go/types" - "io" - "math/big" - "reflect" - "sort" -) - -// Current indexed export format version. Increase with each format change. -// 0: Go1.11 encoding -const iexportVersion = 0 - -// IExportData returns the binary export data for pkg. -// -// If no file set is provided, position info will be missing. -// The package path of the top-level package will not be recorded, -// so that calls to IImportData can override with a provided package path. -func IExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) { - defer func() { - if e := recover(); e != nil { - if ierr, ok := e.(internalError); ok { - err = ierr - return - } - // Not an internal error; panic again. - panic(e) - } - }() - - p := iexporter{ - out: bytes.NewBuffer(nil), - fset: fset, - allPkgs: map[*types.Package]bool{}, - stringIndex: map[string]uint64{}, - declIndex: map[types.Object]uint64{}, - typIndex: map[types.Type]uint64{}, - localpkg: pkg, - } - - for i, pt := range predeclared() { - p.typIndex[pt] = uint64(i) - } - if len(p.typIndex) > predeclReserved { - panic(internalErrorf("too many predeclared types: %d > %d", len(p.typIndex), predeclReserved)) - } - - // Initialize work queue with exported declarations. - scope := pkg.Scope() - for _, name := range scope.Names() { - if ast.IsExported(name) { - p.pushDecl(scope.Lookup(name)) - } - } - - // Loop until no more work. - for !p.declTodo.empty() { - p.doDecl(p.declTodo.popHead()) - } - - // Append indices to data0 section. - dataLen := uint64(p.data0.Len()) - w := p.newWriter() - w.writeIndex(p.declIndex) - w.flush() - - // Assemble header. - var hdr intWriter - hdr.WriteByte('i') - hdr.uint64(iexportVersion) - hdr.uint64(uint64(p.strings.Len())) - hdr.uint64(dataLen) - - // Flush output. - io.Copy(p.out, &hdr) - io.Copy(p.out, &p.strings) - io.Copy(p.out, &p.data0) - - return p.out.Bytes(), nil -} - -// writeIndex writes out an object index. mainIndex indicates whether -// we're writing out the main index, which is also read by -// non-compiler tools and includes a complete package description -// (i.e., name and height). -func (w *exportWriter) writeIndex(index map[types.Object]uint64) { - // Build a map from packages to objects from that package. - pkgObjs := map[*types.Package][]types.Object{} - - // For the main index, make sure to include every package that - // we reference, even if we're not exporting (or reexporting) - // any symbols from it. - pkgObjs[w.p.localpkg] = nil - for pkg := range w.p.allPkgs { - pkgObjs[pkg] = nil - } - - for obj := range index { - pkgObjs[obj.Pkg()] = append(pkgObjs[obj.Pkg()], obj) - } - - var pkgs []*types.Package - for pkg, objs := range pkgObjs { - pkgs = append(pkgs, pkg) - - sort.Slice(objs, func(i, j int) bool { - return objs[i].Name() < objs[j].Name() - }) - } - - sort.Slice(pkgs, func(i, j int) bool { - return w.exportPath(pkgs[i]) < w.exportPath(pkgs[j]) - }) - - w.uint64(uint64(len(pkgs))) - for _, pkg := range pkgs { - w.string(w.exportPath(pkg)) - w.string(pkg.Name()) - w.uint64(uint64(0)) // package height is not needed for go/types - - objs := pkgObjs[pkg] - w.uint64(uint64(len(objs))) - for _, obj := range objs { - w.string(obj.Name()) - w.uint64(index[obj]) - } - } -} - -type iexporter struct { - fset *token.FileSet - out *bytes.Buffer - - localpkg *types.Package - - // allPkgs tracks all packages that have been referenced by - // the export data, so we can ensure to include them in the - // main index. - allPkgs map[*types.Package]bool - - declTodo objQueue - - strings intWriter - stringIndex map[string]uint64 - - data0 intWriter - declIndex map[types.Object]uint64 - typIndex map[types.Type]uint64 -} - -// stringOff returns the offset of s within the string section. -// If not already present, it's added to the end. -func (p *iexporter) stringOff(s string) uint64 { - off, ok := p.stringIndex[s] - if !ok { - off = uint64(p.strings.Len()) - p.stringIndex[s] = off - - p.strings.uint64(uint64(len(s))) - p.strings.WriteString(s) - } - return off -} - -// pushDecl adds n to the declaration work queue, if not already present. -func (p *iexporter) pushDecl(obj types.Object) { - // Package unsafe is known to the compiler and predeclared. - assert(obj.Pkg() != types.Unsafe) - - if _, ok := p.declIndex[obj]; ok { - return - } - - p.declIndex[obj] = ^uint64(0) // mark n present in work queue - p.declTodo.pushTail(obj) -} - -// exportWriter handles writing out individual data section chunks. -type exportWriter struct { - p *iexporter - - data intWriter - currPkg *types.Package - prevFile string - prevLine int64 -} - -func (w *exportWriter) exportPath(pkg *types.Package) string { - if pkg == w.p.localpkg { - return "" - } - return pkg.Path() -} - -func (p *iexporter) doDecl(obj types.Object) { - w := p.newWriter() - w.setPkg(obj.Pkg(), false) - - switch obj := obj.(type) { - case *types.Var: - w.tag('V') - w.pos(obj.Pos()) - w.typ(obj.Type(), obj.Pkg()) - - case *types.Func: - sig, _ := obj.Type().(*types.Signature) - if sig.Recv() != nil { - panic(internalErrorf("unexpected method: %v", sig)) - } - w.tag('F') - w.pos(obj.Pos()) - w.signature(sig) - - case *types.Const: - w.tag('C') - w.pos(obj.Pos()) - w.value(obj.Type(), obj.Val()) - - case *types.TypeName: - if obj.IsAlias() { - w.tag('A') - w.pos(obj.Pos()) - w.typ(obj.Type(), obj.Pkg()) - break - } - - // Defined type. - w.tag('T') - w.pos(obj.Pos()) - - underlying := obj.Type().Underlying() - w.typ(underlying, obj.Pkg()) - - t := obj.Type() - if types.IsInterface(t) { - break - } - - named, ok := t.(*types.Named) - if !ok { - panic(internalErrorf("%s is not a defined type", t)) - } - - n := named.NumMethods() - w.uint64(uint64(n)) - for i := 0; i < n; i++ { - m := named.Method(i) - w.pos(m.Pos()) - w.string(m.Name()) - sig, _ := m.Type().(*types.Signature) - w.param(sig.Recv()) - w.signature(sig) - } - - default: - panic(internalErrorf("unexpected object: %v", obj)) - } - - p.declIndex[obj] = w.flush() -} - -func (w *exportWriter) tag(tag byte) { - w.data.WriteByte(tag) -} - -func (w *exportWriter) pos(pos token.Pos) { - if w.p.fset == nil { - w.int64(0) - return - } - - p := w.p.fset.Position(pos) - file := p.Filename - line := int64(p.Line) - - // When file is the same as the last position (common case), - // we can save a few bytes by delta encoding just the line - // number. - // - // Note: Because data objects may be read out of order (or not - // at all), we can only apply delta encoding within a single - // object. This is handled implicitly by tracking prevFile and - // prevLine as fields of exportWriter. - - if file == w.prevFile { - delta := line - w.prevLine - w.int64(delta) - if delta == deltaNewFile { - w.int64(-1) - } - } else { - w.int64(deltaNewFile) - w.int64(line) // line >= 0 - w.string(file) - w.prevFile = file - } - w.prevLine = line -} - -func (w *exportWriter) pkg(pkg *types.Package) { - // Ensure any referenced packages are declared in the main index. - w.p.allPkgs[pkg] = true - - w.string(w.exportPath(pkg)) -} - -func (w *exportWriter) qualifiedIdent(obj types.Object) { - // Ensure any referenced declarations are written out too. - w.p.pushDecl(obj) - - w.string(obj.Name()) - w.pkg(obj.Pkg()) -} - -func (w *exportWriter) typ(t types.Type, pkg *types.Package) { - w.data.uint64(w.p.typOff(t, pkg)) -} - -func (p *iexporter) newWriter() *exportWriter { - return &exportWriter{p: p} -} - -func (w *exportWriter) flush() uint64 { - off := uint64(w.p.data0.Len()) - io.Copy(&w.p.data0, &w.data) - return off -} - -func (p *iexporter) typOff(t types.Type, pkg *types.Package) uint64 { - off, ok := p.typIndex[t] - if !ok { - w := p.newWriter() - w.doTyp(t, pkg) - off = predeclReserved + w.flush() - p.typIndex[t] = off - } - return off -} - -func (w *exportWriter) startType(k itag) { - w.data.uint64(uint64(k)) -} - -func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { - switch t := t.(type) { - case *types.Named: - w.startType(definedType) - w.qualifiedIdent(t.Obj()) - - case *types.Pointer: - w.startType(pointerType) - w.typ(t.Elem(), pkg) - - case *types.Slice: - w.startType(sliceType) - w.typ(t.Elem(), pkg) - - case *types.Array: - w.startType(arrayType) - w.uint64(uint64(t.Len())) - w.typ(t.Elem(), pkg) - - case *types.Chan: - w.startType(chanType) - // 1 RecvOnly; 2 SendOnly; 3 SendRecv - var dir uint64 - switch t.Dir() { - case types.RecvOnly: - dir = 1 - case types.SendOnly: - dir = 2 - case types.SendRecv: - dir = 3 - } - w.uint64(dir) - w.typ(t.Elem(), pkg) - - case *types.Map: - w.startType(mapType) - w.typ(t.Key(), pkg) - w.typ(t.Elem(), pkg) - - case *types.Signature: - w.startType(signatureType) - w.setPkg(pkg, true) - w.signature(t) - - case *types.Struct: - w.startType(structType) - w.setPkg(pkg, true) - - n := t.NumFields() - w.uint64(uint64(n)) - for i := 0; i < n; i++ { - f := t.Field(i) - w.pos(f.Pos()) - w.string(f.Name()) - w.typ(f.Type(), pkg) - w.bool(f.Anonymous()) - w.string(t.Tag(i)) // note (or tag) - } - - case *types.Interface: - w.startType(interfaceType) - w.setPkg(pkg, true) - - n := t.NumEmbeddeds() - w.uint64(uint64(n)) - for i := 0; i < n; i++ { - f := t.Embedded(i) - w.pos(f.Obj().Pos()) - w.typ(f.Obj().Type(), f.Obj().Pkg()) - } - - n = t.NumExplicitMethods() - w.uint64(uint64(n)) - for i := 0; i < n; i++ { - m := t.ExplicitMethod(i) - w.pos(m.Pos()) - w.string(m.Name()) - sig, _ := m.Type().(*types.Signature) - w.signature(sig) - } - - default: - panic(internalErrorf("unexpected type: %v, %v", t, reflect.TypeOf(t))) - } -} - -func (w *exportWriter) setPkg(pkg *types.Package, write bool) { - if write { - w.pkg(pkg) - } - - w.currPkg = pkg -} - -func (w *exportWriter) signature(sig *types.Signature) { - w.paramList(sig.Params()) - w.paramList(sig.Results()) - if sig.Params().Len() > 0 { - w.bool(sig.Variadic()) - } -} - -func (w *exportWriter) paramList(tup *types.Tuple) { - n := tup.Len() - w.uint64(uint64(n)) - for i := 0; i < n; i++ { - w.param(tup.At(i)) - } -} - -func (w *exportWriter) param(obj types.Object) { - w.pos(obj.Pos()) - w.localIdent(obj) - w.typ(obj.Type(), obj.Pkg()) -} - -func (w *exportWriter) value(typ types.Type, v constant.Value) { - w.typ(typ, nil) - - switch v.Kind() { - case constant.Bool: - w.bool(constant.BoolVal(v)) - case constant.Int: - var i big.Int - if i64, exact := constant.Int64Val(v); exact { - i.SetInt64(i64) - } else if ui64, exact := constant.Uint64Val(v); exact { - i.SetUint64(ui64) - } else { - i.SetString(v.ExactString(), 10) - } - w.mpint(&i, typ) - case constant.Float: - f := constantToFloat(v) - w.mpfloat(f, typ) - case constant.Complex: - w.mpfloat(constantToFloat(constant.Real(v)), typ) - w.mpfloat(constantToFloat(constant.Imag(v)), typ) - case constant.String: - w.string(constant.StringVal(v)) - case constant.Unknown: - // package contains type errors - default: - panic(internalErrorf("unexpected value %v (%T)", v, v)) - } -} - -// constantToFloat converts a constant.Value with kind constant.Float to a -// big.Float. -func constantToFloat(x constant.Value) *big.Float { - assert(x.Kind() == constant.Float) - // Use the same floating-point precision (512) as cmd/compile - // (see Mpprec in cmd/compile/internal/gc/mpfloat.go). - const mpprec = 512 - var f big.Float - f.SetPrec(mpprec) - if v, exact := constant.Float64Val(x); exact { - // float64 - f.SetFloat64(v) - } else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int { - // TODO(gri): add big.Rat accessor to constant.Value. - n := valueToRat(num) - d := valueToRat(denom) - f.SetRat(n.Quo(n, d)) - } else { - // Value too large to represent as a fraction => inaccessible. - // TODO(gri): add big.Float accessor to constant.Value. - _, ok := f.SetString(x.ExactString()) - assert(ok) - } - return &f -} - -// mpint exports a multi-precision integer. -// -// For unsigned types, small values are written out as a single -// byte. Larger values are written out as a length-prefixed big-endian -// byte string, where the length prefix is encoded as its complement. -// For example, bytes 0, 1, and 2 directly represent the integer -// values 0, 1, and 2; while bytes 255, 254, and 253 indicate a 1-, -// 2-, and 3-byte big-endian string follow. -// -// Encoding for signed types use the same general approach as for -// unsigned types, except small values use zig-zag encoding and the -// bottom bit of length prefix byte for large values is reserved as a -// sign bit. -// -// The exact boundary between small and large encodings varies -// according to the maximum number of bytes needed to encode a value -// of type typ. As a special case, 8-bit types are always encoded as a -// single byte. -// -// TODO(mdempsky): Is this level of complexity really worthwhile? -func (w *exportWriter) mpint(x *big.Int, typ types.Type) { - basic, ok := typ.Underlying().(*types.Basic) - if !ok { - panic(internalErrorf("unexpected type %v (%T)", typ.Underlying(), typ.Underlying())) - } - - signed, maxBytes := intSize(basic) - - negative := x.Sign() < 0 - if !signed && negative { - panic(internalErrorf("negative unsigned integer; type %v, value %v", typ, x)) - } - - b := x.Bytes() - if len(b) > 0 && b[0] == 0 { - panic(internalErrorf("leading zeros")) - } - if uint(len(b)) > maxBytes { - panic(internalErrorf("bad mpint length: %d > %d (type %v, value %v)", len(b), maxBytes, typ, x)) - } - - maxSmall := 256 - maxBytes - if signed { - maxSmall = 256 - 2*maxBytes - } - if maxBytes == 1 { - maxSmall = 256 - } - - // Check if x can use small value encoding. - if len(b) <= 1 { - var ux uint - if len(b) == 1 { - ux = uint(b[0]) - } - if signed { - ux <<= 1 - if negative { - ux-- - } - } - if ux < maxSmall { - w.data.WriteByte(byte(ux)) - return - } - } - - n := 256 - uint(len(b)) - if signed { - n = 256 - 2*uint(len(b)) - if negative { - n |= 1 - } - } - if n < maxSmall || n >= 256 { - panic(internalErrorf("encoding mistake: %d, %v, %v => %d", len(b), signed, negative, n)) - } - - w.data.WriteByte(byte(n)) - w.data.Write(b) -} - -// mpfloat exports a multi-precision floating point number. -// -// The number's value is decomposed into mantissa × 2**exponent, where -// mantissa is an integer. The value is written out as mantissa (as a -// multi-precision integer) and then the exponent, except exponent is -// omitted if mantissa is zero. -func (w *exportWriter) mpfloat(f *big.Float, typ types.Type) { - if f.IsInf() { - panic("infinite constant") - } - - // Break into f = mant × 2**exp, with 0.5 <= mant < 1. - var mant big.Float - exp := int64(f.MantExp(&mant)) - - // Scale so that mant is an integer. - prec := mant.MinPrec() - mant.SetMantExp(&mant, int(prec)) - exp -= int64(prec) - - manti, acc := mant.Int(nil) - if acc != big.Exact { - panic(internalErrorf("mantissa scaling failed for %f (%s)", f, acc)) - } - w.mpint(manti, typ) - if manti.Sign() != 0 { - w.int64(exp) - } -} - -func (w *exportWriter) bool(b bool) bool { - var x uint64 - if b { - x = 1 - } - w.uint64(x) - return b -} - -func (w *exportWriter) int64(x int64) { w.data.int64(x) } -func (w *exportWriter) uint64(x uint64) { w.data.uint64(x) } -func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) } - -func (w *exportWriter) localIdent(obj types.Object) { - // Anonymous parameters. - if obj == nil { - w.string("") - return - } - - name := obj.Name() - if name == "_" { - w.string("_") - return - } - - w.string(name) -} - -type intWriter struct { - bytes.Buffer -} - -func (w *intWriter) int64(x int64) { - var buf [binary.MaxVarintLen64]byte - n := binary.PutVarint(buf[:], x) - w.Write(buf[:n]) -} - -func (w *intWriter) uint64(x uint64) { - var buf [binary.MaxVarintLen64]byte - n := binary.PutUvarint(buf[:], x) - w.Write(buf[:n]) -} - -func assert(cond bool) { - if !cond { - panic("internal error: assertion failed") - } -} - -// The below is copied from go/src/cmd/compile/internal/gc/syntax.go. - -// objQueue is a FIFO queue of types.Object. The zero value of objQueue is -// a ready-to-use empty queue. -type objQueue struct { - ring []types.Object - head, tail int -} - -// empty returns true if q contains no Nodes. -func (q *objQueue) empty() bool { - return q.head == q.tail -} - -// pushTail appends n to the tail of the queue. -func (q *objQueue) pushTail(obj types.Object) { - if len(q.ring) == 0 { - q.ring = make([]types.Object, 16) - } else if q.head+len(q.ring) == q.tail { - // Grow the ring. - nring := make([]types.Object, len(q.ring)*2) - // Copy the old elements. - part := q.ring[q.head%len(q.ring):] - if q.tail-q.head <= len(part) { - part = part[:q.tail-q.head] - copy(nring, part) - } else { - pos := copy(nring, part) - copy(nring[pos:], q.ring[:q.tail%len(q.ring)]) - } - q.ring, q.head, q.tail = nring, 0, q.tail-q.head - } - - q.ring[q.tail%len(q.ring)] = obj - q.tail++ -} - -// popHead pops a node from the head of the queue. It panics if q is empty. -func (q *objQueue) popHead() types.Object { - if q.empty() { - panic("dequeue empty") - } - obj := q.ring[q.head%len(q.ring)] - q.head++ - return obj -} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go deleted file mode 100644 index a31a880263..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go +++ /dev/null @@ -1,630 +0,0 @@ -// 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. - -// Indexed package import. -// See cmd/compile/internal/gc/iexport.go for the export data format. - -// This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go. - -package gcimporter - -import ( - "bytes" - "encoding/binary" - "fmt" - "go/constant" - "go/token" - "go/types" - "io" - "sort" -) - -type intReader struct { - *bytes.Reader - path string -} - -func (r *intReader) int64() int64 { - i, err := binary.ReadVarint(r.Reader) - if err != nil { - errorf("import %q: read varint error: %v", r.path, err) - } - return i -} - -func (r *intReader) uint64() uint64 { - i, err := binary.ReadUvarint(r.Reader) - if err != nil { - errorf("import %q: read varint error: %v", r.path, err) - } - return i -} - -const predeclReserved = 32 - -type itag uint64 - -const ( - // Types - definedType itag = iota - pointerType - sliceType - arrayType - chanType - mapType - signatureType - structType - interfaceType -) - -// IImportData imports a package from the serialized package data -// and returns the number of bytes consumed and a reference to the package. -// If the export data version is not recognized or the format is otherwise -// compromised, an error is returned. -func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { - const currentVersion = 1 - version := int64(-1) - defer func() { - if e := recover(); e != nil { - if version > currentVersion { - err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) - } else { - err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) - } - } - }() - - r := &intReader{bytes.NewReader(data), path} - - version = int64(r.uint64()) - switch version { - case currentVersion, 0: - default: - errorf("unknown iexport format version %d", version) - } - - sLen := int64(r.uint64()) - dLen := int64(r.uint64()) - - whence, _ := r.Seek(0, io.SeekCurrent) - stringData := data[whence : whence+sLen] - declData := data[whence+sLen : whence+sLen+dLen] - r.Seek(sLen+dLen, io.SeekCurrent) - - p := iimporter{ - ipath: path, - version: int(version), - - stringData: stringData, - stringCache: make(map[uint64]string), - pkgCache: make(map[uint64]*types.Package), - - declData: declData, - pkgIndex: make(map[*types.Package]map[string]uint64), - typCache: make(map[uint64]types.Type), - - fake: fakeFileSet{ - fset: fset, - files: make(map[string]*token.File), - }, - } - - for i, pt := range predeclared() { - p.typCache[uint64(i)] = pt - } - - pkgList := make([]*types.Package, r.uint64()) - for i := range pkgList { - pkgPathOff := r.uint64() - pkgPath := p.stringAt(pkgPathOff) - pkgName := p.stringAt(r.uint64()) - _ = r.uint64() // package height; unused by go/types - - if pkgPath == "" { - pkgPath = path - } - pkg := imports[pkgPath] - if pkg == nil { - pkg = types.NewPackage(pkgPath, pkgName) - imports[pkgPath] = pkg - } else if pkg.Name() != pkgName { - errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) - } - - p.pkgCache[pkgPathOff] = pkg - - nameIndex := make(map[string]uint64) - for nSyms := r.uint64(); nSyms > 0; nSyms-- { - name := p.stringAt(r.uint64()) - nameIndex[name] = r.uint64() - } - - p.pkgIndex[pkg] = nameIndex - pkgList[i] = pkg - } - if len(pkgList) == 0 { - errorf("no packages found for %s", path) - panic("unreachable") - } - p.ipkg = pkgList[0] - names := make([]string, 0, len(p.pkgIndex[p.ipkg])) - for name := range p.pkgIndex[p.ipkg] { - names = append(names, name) - } - sort.Strings(names) - for _, name := range names { - p.doDecl(p.ipkg, name) - } - - for _, typ := range p.interfaceList { - typ.Complete() - } - - // record all referenced packages as imports - list := append(([]*types.Package)(nil), pkgList[1:]...) - sort.Sort(byPath(list)) - p.ipkg.SetImports(list) - - // package was imported completely and without errors - p.ipkg.MarkComplete() - - consumed, _ := r.Seek(0, io.SeekCurrent) - return int(consumed), p.ipkg, nil -} - -type iimporter struct { - ipath string - ipkg *types.Package - version int - - stringData []byte - stringCache map[uint64]string - pkgCache map[uint64]*types.Package - - declData []byte - pkgIndex map[*types.Package]map[string]uint64 - typCache map[uint64]types.Type - - fake fakeFileSet - interfaceList []*types.Interface -} - -func (p *iimporter) doDecl(pkg *types.Package, name string) { - // See if we've already imported this declaration. - if obj := pkg.Scope().Lookup(name); obj != nil { - return - } - - off, ok := p.pkgIndex[pkg][name] - if !ok { - errorf("%v.%v not in index", pkg, name) - } - - r := &importReader{p: p, currPkg: pkg} - r.declReader.Reset(p.declData[off:]) - - r.obj(name) -} - -func (p *iimporter) stringAt(off uint64) string { - if s, ok := p.stringCache[off]; ok { - return s - } - - slen, n := binary.Uvarint(p.stringData[off:]) - if n <= 0 { - errorf("varint failed") - } - spos := off + uint64(n) - s := string(p.stringData[spos : spos+slen]) - p.stringCache[off] = s - return s -} - -func (p *iimporter) pkgAt(off uint64) *types.Package { - if pkg, ok := p.pkgCache[off]; ok { - return pkg - } - path := p.stringAt(off) - if path == p.ipath { - return p.ipkg - } - errorf("missing package %q in %q", path, p.ipath) - return nil -} - -func (p *iimporter) typAt(off uint64, base *types.Named) types.Type { - if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) { - return t - } - - if off < predeclReserved { - errorf("predeclared type missing from cache: %v", off) - } - - r := &importReader{p: p} - r.declReader.Reset(p.declData[off-predeclReserved:]) - t := r.doType(base) - - if base == nil || !isInterface(t) { - p.typCache[off] = t - } - return t -} - -type importReader struct { - p *iimporter - declReader bytes.Reader - currPkg *types.Package - prevFile string - prevLine int64 - prevColumn int64 -} - -func (r *importReader) obj(name string) { - tag := r.byte() - pos := r.pos() - - switch tag { - case 'A': - typ := r.typ() - - r.declare(types.NewTypeName(pos, r.currPkg, name, typ)) - - case 'C': - typ, val := r.value() - - r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) - - case 'F': - sig := r.signature(nil) - - r.declare(types.NewFunc(pos, r.currPkg, name, sig)) - - case 'T': - // Types can be recursive. We need to setup a stub - // declaration before recursing. - obj := types.NewTypeName(pos, r.currPkg, name, nil) - named := types.NewNamed(obj, nil, nil) - r.declare(obj) - - underlying := r.p.typAt(r.uint64(), named).Underlying() - named.SetUnderlying(underlying) - - if !isInterface(underlying) { - for n := r.uint64(); n > 0; n-- { - mpos := r.pos() - mname := r.ident() - recv := r.param() - msig := r.signature(recv) - - named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) - } - } - - case 'V': - typ := r.typ() - - r.declare(types.NewVar(pos, r.currPkg, name, typ)) - - default: - errorf("unexpected tag: %v", tag) - } -} - -func (r *importReader) declare(obj types.Object) { - obj.Pkg().Scope().Insert(obj) -} - -func (r *importReader) value() (typ types.Type, val constant.Value) { - typ = r.typ() - - switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType { - case types.IsBoolean: - val = constant.MakeBool(r.bool()) - - case types.IsString: - val = constant.MakeString(r.string()) - - case types.IsInteger: - val = r.mpint(b) - - case types.IsFloat: - val = r.mpfloat(b) - - case types.IsComplex: - re := r.mpfloat(b) - im := r.mpfloat(b) - val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) - - default: - if b.Kind() == types.Invalid { - val = constant.MakeUnknown() - return - } - errorf("unexpected type %v", typ) // panics - panic("unreachable") - } - - return -} - -func intSize(b *types.Basic) (signed bool, maxBytes uint) { - if (b.Info() & types.IsUntyped) != 0 { - return true, 64 - } - - switch b.Kind() { - case types.Float32, types.Complex64: - return true, 3 - case types.Float64, types.Complex128: - return true, 7 - } - - signed = (b.Info() & types.IsUnsigned) == 0 - switch b.Kind() { - case types.Int8, types.Uint8: - maxBytes = 1 - case types.Int16, types.Uint16: - maxBytes = 2 - case types.Int32, types.Uint32: - maxBytes = 4 - default: - maxBytes = 8 - } - - return -} - -func (r *importReader) mpint(b *types.Basic) constant.Value { - signed, maxBytes := intSize(b) - - maxSmall := 256 - maxBytes - if signed { - maxSmall = 256 - 2*maxBytes - } - if maxBytes == 1 { - maxSmall = 256 - } - - n, _ := r.declReader.ReadByte() - if uint(n) < maxSmall { - v := int64(n) - if signed { - v >>= 1 - if n&1 != 0 { - v = ^v - } - } - return constant.MakeInt64(v) - } - - v := -n - if signed { - v = -(n &^ 1) >> 1 - } - if v < 1 || uint(v) > maxBytes { - errorf("weird decoding: %v, %v => %v", n, signed, v) - } - - buf := make([]byte, v) - io.ReadFull(&r.declReader, buf) - - // convert to little endian - // TODO(gri) go/constant should have a more direct conversion function - // (e.g., once it supports a big.Float based implementation) - for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 { - buf[i], buf[j] = buf[j], buf[i] - } - - x := constant.MakeFromBytes(buf) - if signed && n&1 != 0 { - x = constant.UnaryOp(token.SUB, x, 0) - } - return x -} - -func (r *importReader) mpfloat(b *types.Basic) constant.Value { - x := r.mpint(b) - if constant.Sign(x) == 0 { - return x - } - - exp := r.int64() - switch { - case exp > 0: - x = constant.Shift(x, token.SHL, uint(exp)) - case exp < 0: - d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) - x = constant.BinaryOp(x, token.QUO, d) - } - return x -} - -func (r *importReader) ident() string { - return r.string() -} - -func (r *importReader) qualifiedIdent() (*types.Package, string) { - name := r.string() - pkg := r.pkg() - return pkg, name -} - -func (r *importReader) pos() token.Pos { - if r.p.version >= 1 { - r.posv1() - } else { - r.posv0() - } - - if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 { - return token.NoPos - } - return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn)) -} - -func (r *importReader) posv0() { - delta := r.int64() - if delta != deltaNewFile { - r.prevLine += delta - } else if l := r.int64(); l == -1 { - r.prevLine += deltaNewFile - } else { - r.prevFile = r.string() - r.prevLine = l - } -} - -func (r *importReader) posv1() { - delta := r.int64() - r.prevColumn += delta >> 1 - if delta&1 != 0 { - delta = r.int64() - r.prevLine += delta >> 1 - if delta&1 != 0 { - r.prevFile = r.string() - } - } -} - -func (r *importReader) typ() types.Type { - return r.p.typAt(r.uint64(), nil) -} - -func isInterface(t types.Type) bool { - _, ok := t.(*types.Interface) - return ok -} - -func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) } -func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } - -func (r *importReader) doType(base *types.Named) types.Type { - switch k := r.kind(); k { - default: - errorf("unexpected kind tag in %q: %v", r.p.ipath, k) - return nil - - case definedType: - pkg, name := r.qualifiedIdent() - r.p.doDecl(pkg, name) - return pkg.Scope().Lookup(name).(*types.TypeName).Type() - case pointerType: - return types.NewPointer(r.typ()) - case sliceType: - return types.NewSlice(r.typ()) - case arrayType: - n := r.uint64() - return types.NewArray(r.typ(), int64(n)) - case chanType: - dir := chanDir(int(r.uint64())) - return types.NewChan(dir, r.typ()) - case mapType: - return types.NewMap(r.typ(), r.typ()) - case signatureType: - r.currPkg = r.pkg() - return r.signature(nil) - - case structType: - r.currPkg = r.pkg() - - fields := make([]*types.Var, r.uint64()) - tags := make([]string, len(fields)) - for i := range fields { - fpos := r.pos() - fname := r.ident() - ftyp := r.typ() - emb := r.bool() - tag := r.string() - - fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb) - tags[i] = tag - } - return types.NewStruct(fields, tags) - - case interfaceType: - r.currPkg = r.pkg() - - embeddeds := make([]types.Type, r.uint64()) - for i := range embeddeds { - _ = r.pos() - embeddeds[i] = r.typ() - } - - methods := make([]*types.Func, r.uint64()) - for i := range methods { - mpos := r.pos() - mname := r.ident() - - // TODO(mdempsky): Matches bimport.go, but I - // don't agree with this. - var recv *types.Var - if base != nil { - recv = types.NewVar(token.NoPos, r.currPkg, "", base) - } - - msig := r.signature(recv) - methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig) - } - - typ := newInterface(methods, embeddeds) - r.p.interfaceList = append(r.p.interfaceList, typ) - return typ - } -} - -func (r *importReader) kind() itag { - return itag(r.uint64()) -} - -func (r *importReader) signature(recv *types.Var) *types.Signature { - params := r.paramList() - results := r.paramList() - variadic := params.Len() > 0 && r.bool() - return types.NewSignature(recv, params, results, variadic) -} - -func (r *importReader) paramList() *types.Tuple { - xs := make([]*types.Var, r.uint64()) - for i := range xs { - xs[i] = r.param() - } - return types.NewTuple(xs...) -} - -func (r *importReader) param() *types.Var { - pos := r.pos() - name := r.ident() - typ := r.typ() - return types.NewParam(pos, r.currPkg, name, typ) -} - -func (r *importReader) bool() bool { - return r.uint64() != 0 -} - -func (r *importReader) int64() int64 { - n, err := binary.ReadVarint(&r.declReader) - if err != nil { - errorf("readVarint: %v", err) - } - return n -} - -func (r *importReader) uint64() uint64 { - n, err := binary.ReadUvarint(&r.declReader) - if err != nil { - errorf("readUvarint: %v", err) - } - return n -} - -func (r *importReader) byte() byte { - x, err := r.declReader.ReadByte() - if err != nil { - errorf("declReader.ReadByte: %v", err) - } - return x -} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go b/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go deleted file mode 100644 index 463f252271..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -// +build !go1.11 - -package gcimporter - -import "go/types" - -func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { - named := make([]*types.Named, len(embeddeds)) - for i, e := range embeddeds { - var ok bool - named[i], ok = e.(*types.Named) - if !ok { - panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11") - } - } - return types.NewInterface(methods, named) -} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go b/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go deleted file mode 100644 index ab28b95cbb..0000000000 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -// +build go1.11 - -package gcimporter - -import "go/types" - -func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface { - return types.NewInterfaceType(methods, embeddeds) -} diff --git a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go deleted file mode 100644 index f4d73b2339..0000000000 --- a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go +++ /dev/null @@ -1,49 +0,0 @@ -// 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 packagesdriver fetches type sizes for go/packages and go/analysis. -package packagesdriver - -import ( - "context" - "fmt" - "go/types" - "strings" - - "golang.org/x/tools/internal/gocommand" -) - -var debug = false - -func GetSizesGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (types.Sizes, error) { - inv.Verb = "list" - inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"} - stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv) - var goarch, compiler string - if rawErr != nil { - if strings.Contains(rawErr.Error(), "cannot find main module") { - // User's running outside of a module. All bets are off. Get GOARCH and guess compiler is gc. - // TODO(matloob): Is this a problem in practice? - inv.Verb = "env" - inv.Args = []string{"GOARCH"} - envout, enverr := gocmdRunner.Run(ctx, inv) - if enverr != nil { - return nil, enverr - } - goarch = strings.TrimSpace(envout.String()) - compiler = "gc" - } else { - return nil, friendlyErr - } - } else { - fields := strings.Fields(stdout.String()) - if len(fields) < 2 { - return nil, fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\":\nstdout: <<%s>>\nstderr: <<%s>>", - stdout.String(), stderr.String()) - } - goarch = fields[0] - compiler = fields[1] - } - return types.SizesFor(compiler, goarch), nil -} diff --git a/vendor/golang.org/x/tools/go/loader/doc.go b/vendor/golang.org/x/tools/go/loader/doc.go deleted file mode 100644 index c5aa31c1a0..0000000000 --- a/vendor/golang.org/x/tools/go/loader/doc.go +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2015 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 loader loads a complete Go program from source code, parsing -// and type-checking the initial packages plus their transitive closure -// of dependencies. The ASTs and the derived facts are retained for -// later use. -// -// Deprecated: This is an older API and does not have support -// for modules. Use golang.org/x/tools/go/packages instead. -// -// The package defines two primary types: Config, which specifies a -// set of initial packages to load and various other options; and -// Program, which is the result of successfully loading the packages -// specified by a configuration. -// -// The configuration can be set directly, but *Config provides various -// convenience methods to simplify the common cases, each of which can -// be called any number of times. Finally, these are followed by a -// call to Load() to actually load and type-check the program. -// -// var conf loader.Config -// -// // Use the command-line arguments to specify -// // a set of initial packages to load from source. -// // See FromArgsUsage for help. -// rest, err := conf.FromArgs(os.Args[1:], wantTests) -// -// // Parse the specified files and create an ad hoc package with path "foo". -// // All files must have the same 'package' declaration. -// conf.CreateFromFilenames("foo", "foo.go", "bar.go") -// -// // Create an ad hoc package with path "foo" from -// // the specified already-parsed files. -// // All ASTs must have the same 'package' declaration. -// conf.CreateFromFiles("foo", parsedFiles) -// -// // Add "runtime" to the set of packages to be loaded. -// conf.Import("runtime") -// -// // Adds "fmt" and "fmt_test" to the set of packages -// // to be loaded. "fmt" will include *_test.go files. -// conf.ImportWithTests("fmt") -// -// // Finally, load all the packages specified by the configuration. -// prog, err := conf.Load() -// -// See examples_test.go for examples of API usage. -// -// -// CONCEPTS AND TERMINOLOGY -// -// The WORKSPACE is the set of packages accessible to the loader. The -// workspace is defined by Config.Build, a *build.Context. The -// default context treats subdirectories of $GOROOT and $GOPATH as -// packages, but this behavior may be overridden. -// -// An AD HOC package is one specified as a set of source files on the -// command line. In the simplest case, it may consist of a single file -// such as $GOROOT/src/net/http/triv.go. -// -// EXTERNAL TEST packages are those comprised of a set of *_test.go -// files all with the same 'package foo_test' declaration, all in the -// same directory. (go/build.Package calls these files XTestFiles.) -// -// An IMPORTABLE package is one that can be referred to by some import -// spec. Every importable package is uniquely identified by its -// PACKAGE PATH or just PATH, a string such as "fmt", "encoding/json", -// or "cmd/vendor/golang.org/x/arch/x86/x86asm". A package path -// typically denotes a subdirectory of the workspace. -// -// An import declaration uses an IMPORT PATH to refer to a package. -// Most import declarations use the package path as the import path. -// -// Due to VENDORING (https://golang.org/s/go15vendor), the -// interpretation of an import path may depend on the directory in which -// it appears. To resolve an import path to a package path, go/build -// must search the enclosing directories for a subdirectory named -// "vendor". -// -// ad hoc packages and external test packages are NON-IMPORTABLE. The -// path of an ad hoc package is inferred from the package -// declarations of its files and is therefore not a unique package key. -// For example, Config.CreatePkgs may specify two initial ad hoc -// packages, both with path "main". -// -// An AUGMENTED package is an importable package P plus all the -// *_test.go files with same 'package foo' declaration as P. -// (go/build.Package calls these files TestFiles.) -// -// The INITIAL packages are those specified in the configuration. A -// DEPENDENCY is a package loaded to satisfy an import in an initial -// package or another dependency. -// -package loader - -// IMPLEMENTATION NOTES -// -// 'go test', in-package test files, and import cycles -// --------------------------------------------------- -// -// An external test package may depend upon members of the augmented -// package that are not in the unaugmented package, such as functions -// that expose internals. (See bufio/export_test.go for an example.) -// So, the loader must ensure that for each external test package -// it loads, it also augments the corresponding non-test package. -// -// The import graph over n unaugmented packages must be acyclic; the -// import graph over n-1 unaugmented packages plus one augmented -// package must also be acyclic. ('go test' relies on this.) But the -// import graph over n augmented packages may contain cycles. -// -// First, all the (unaugmented) non-test packages and their -// dependencies are imported in the usual way; the loader reports an -// error if it detects an import cycle. -// -// Then, each package P for which testing is desired is augmented by -// the list P' of its in-package test files, by calling -// (*types.Checker).Files. This arrangement ensures that P' may -// reference definitions within P, but P may not reference definitions -// within P'. Furthermore, P' may import any other package, including -// ones that depend upon P, without an import cycle error. -// -// Consider two packages A and B, both of which have lists of -// in-package test files we'll call A' and B', and which have the -// following import graph edges: -// B imports A -// B' imports A -// A' imports B -// This last edge would be expected to create an error were it not -// for the special type-checking discipline above. -// Cycles of size greater than two are possible. For example: -// compress/bzip2/bzip2_test.go (package bzip2) imports "io/ioutil" -// io/ioutil/tempfile_test.go (package ioutil) imports "regexp" -// regexp/exec_test.go (package regexp) imports "compress/bzip2" -// -// -// Concurrency -// ----------- -// -// Let us define the import dependency graph as follows. Each node is a -// list of files passed to (Checker).Files at once. Many of these lists -// are the production code of an importable Go package, so those nodes -// are labelled by the package's path. The remaining nodes are -// ad hoc packages and lists of in-package *_test.go files that augment -// an importable package; those nodes have no label. -// -// The edges of the graph represent import statements appearing within a -// file. An edge connects a node (a list of files) to the node it -// imports, which is importable and thus always labelled. -// -// Loading is controlled by this dependency graph. -// -// To reduce I/O latency, we start loading a package's dependencies -// asynchronously as soon as we've parsed its files and enumerated its -// imports (scanImports). This performs a preorder traversal of the -// import dependency graph. -// -// To exploit hardware parallelism, we type-check unrelated packages in -// parallel, where "unrelated" means not ordered by the partial order of -// the import dependency graph. -// -// We use a concurrency-safe non-blocking cache (importer.imported) to -// record the results of type-checking, whether success or failure. An -// entry is created in this cache by startLoad the first time the -// package is imported. The first goroutine to request an entry becomes -// responsible for completing the task and broadcasting completion to -// subsequent requestors, which block until then. -// -// Type checking occurs in (parallel) postorder: we cannot type-check a -// set of files until we have loaded and type-checked all of their -// immediate dependencies (and thus all of their transitive -// dependencies). If the input were guaranteed free of import cycles, -// this would be trivial: we could simply wait for completion of the -// dependencies and then invoke the typechecker. -// -// But as we saw in the 'go test' section above, some cycles in the -// import graph over packages are actually legal, so long as the -// cycle-forming edge originates in the in-package test files that -// augment the package. This explains why the nodes of the import -// dependency graph are not packages, but lists of files: the unlabelled -// nodes avoid the cycles. Consider packages A and B where B imports A -// and A's in-package tests AT import B. The naively constructed import -// graph over packages would contain a cycle (A+AT) --> B --> (A+AT) but -// the graph over lists of files is AT --> B --> A, where AT is an -// unlabelled node. -// -// Awaiting completion of the dependencies in a cyclic graph would -// deadlock, so we must materialize the import dependency graph (as -// importer.graph) and check whether each import edge forms a cycle. If -// x imports y, and the graph already contains a path from y to x, then -// there is an import cycle, in which case the processing of x must not -// wait for the completion of processing of y. -// -// When the type-checker makes a callback (doImport) to the loader for a -// given import edge, there are two possible cases. In the normal case, -// the dependency has already been completely type-checked; doImport -// does a cache lookup and returns it. In the cyclic case, the entry in -// the cache is still necessarily incomplete, indicating a cycle. We -// perform the cycle check again to obtain the error message, and return -// the error. -// -// The result of using concurrency is about a 2.5x speedup for stdlib_test. diff --git a/vendor/golang.org/x/tools/go/loader/loader.go b/vendor/golang.org/x/tools/go/loader/loader.go deleted file mode 100644 index bc12ca33d1..0000000000 --- a/vendor/golang.org/x/tools/go/loader/loader.go +++ /dev/null @@ -1,1086 +0,0 @@ -// Copyright 2013 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 loader - -// See doc.go for package documentation and implementation notes. - -import ( - "errors" - "fmt" - "go/ast" - "go/build" - "go/parser" - "go/token" - "go/types" - "os" - "path/filepath" - "sort" - "strings" - "sync" - "time" - - "golang.org/x/tools/go/ast/astutil" - "golang.org/x/tools/go/internal/cgo" -) - -var ignoreVendor build.ImportMode - -const trace = false // show timing info for type-checking - -// Config specifies the configuration for loading a whole program from -// Go source code. -// The zero value for Config is a ready-to-use default configuration. -type Config struct { - // Fset is the file set for the parser to use when loading the - // program. If nil, it may be lazily initialized by any - // method of Config. - Fset *token.FileSet - - // ParserMode specifies the mode to be used by the parser when - // loading source packages. - ParserMode parser.Mode - - // TypeChecker contains options relating to the type checker. - // - // The supplied IgnoreFuncBodies is not used; the effective - // value comes from the TypeCheckFuncBodies func below. - // The supplied Import function is not used either. - TypeChecker types.Config - - // TypeCheckFuncBodies is a predicate over package paths. - // A package for which the predicate is false will - // have its package-level declarations type checked, but not - // its function bodies; this can be used to quickly load - // dependencies from source. If nil, all func bodies are type - // checked. - TypeCheckFuncBodies func(path string) bool - - // If Build is non-nil, it is used to locate source packages. - // Otherwise &build.Default is used. - // - // By default, cgo is invoked to preprocess Go files that - // import the fake package "C". This behaviour can be - // disabled by setting CGO_ENABLED=0 in the environment prior - // to startup, or by setting Build.CgoEnabled=false. - Build *build.Context - - // The current directory, used for resolving relative package - // references such as "./go/loader". If empty, os.Getwd will be - // used instead. - Cwd string - - // If DisplayPath is non-nil, it is used to transform each - // file name obtained from Build.Import(). This can be used - // to prevent a virtualized build.Config's file names from - // leaking into the user interface. - DisplayPath func(path string) string - - // If AllowErrors is true, Load will return a Program even - // if some of the its packages contained I/O, parser or type - // errors; such errors are accessible via PackageInfo.Errors. If - // false, Load will fail if any package had an error. - AllowErrors bool - - // CreatePkgs specifies a list of non-importable initial - // packages to create. The resulting packages will appear in - // the corresponding elements of the Program.Created slice. - CreatePkgs []PkgSpec - - // ImportPkgs specifies a set of initial packages to load. - // The map keys are package paths. - // - // The map value indicates whether to load tests. If true, Load - // will add and type-check two lists of files to the package: - // non-test files followed by in-package *_test.go files. In - // addition, it will append the external test package (if any) - // to Program.Created. - ImportPkgs map[string]bool - - // FindPackage is called during Load to create the build.Package - // for a given import path from a given directory. - // If FindPackage is nil, (*build.Context).Import is used. - // A client may use this hook to adapt to a proprietary build - // system that does not follow the "go build" layout - // conventions, for example. - // - // It must be safe to call concurrently from multiple goroutines. - FindPackage func(ctxt *build.Context, importPath, fromDir string, mode build.ImportMode) (*build.Package, error) - - // AfterTypeCheck is called immediately after a list of files - // has been type-checked and appended to info.Files. - // - // This optional hook function is the earliest opportunity for - // the client to observe the output of the type checker, - // which may be useful to reduce analysis latency when loading - // a large program. - // - // The function is permitted to modify info.Info, for instance - // to clear data structures that are no longer needed, which can - // dramatically reduce peak memory consumption. - // - // The function may be called twice for the same PackageInfo: - // once for the files of the package and again for the - // in-package test files. - // - // It must be safe to call concurrently from multiple goroutines. - AfterTypeCheck func(info *PackageInfo, files []*ast.File) -} - -// A PkgSpec specifies a non-importable package to be created by Load. -// Files are processed first, but typically only one of Files and -// Filenames is provided. The path needn't be globally unique. -// -// For vendoring purposes, the package's directory is the one that -// contains the first file. -type PkgSpec struct { - Path string // package path ("" => use package declaration) - Files []*ast.File // ASTs of already-parsed files - Filenames []string // names of files to be parsed -} - -// A Program is a Go program loaded from source as specified by a Config. -type Program struct { - Fset *token.FileSet // the file set for this program - - // Created[i] contains the initial package whose ASTs or - // filenames were supplied by Config.CreatePkgs[i], followed by - // the external test package, if any, of each package in - // Config.ImportPkgs ordered by ImportPath. - // - // NOTE: these files must not import "C". Cgo preprocessing is - // only performed on imported packages, not ad hoc packages. - // - // TODO(adonovan): we need to copy and adapt the logic of - // goFilesPackage (from $GOROOT/src/cmd/go/build.go) and make - // Config.Import and Config.Create methods return the same kind - // of entity, essentially a build.Package. - // Perhaps we can even reuse that type directly. - Created []*PackageInfo - - // Imported contains the initially imported packages, - // as specified by Config.ImportPkgs. - Imported map[string]*PackageInfo - - // AllPackages contains the PackageInfo of every package - // encountered by Load: all initial packages and all - // dependencies, including incomplete ones. - AllPackages map[*types.Package]*PackageInfo - - // importMap is the canonical mapping of package paths to - // packages. It contains all Imported initial packages, but not - // Created ones, and all imported dependencies. - importMap map[string]*types.Package -} - -// PackageInfo holds the ASTs and facts derived by the type-checker -// for a single package. -// -// Not mutated once exposed via the API. -// -type PackageInfo struct { - Pkg *types.Package - Importable bool // true if 'import "Pkg.Path()"' would resolve to this - TransitivelyErrorFree bool // true if Pkg and all its dependencies are free of errors - Files []*ast.File // syntax trees for the package's files - Errors []error // non-nil if the package had errors - types.Info // type-checker deductions. - dir string // package directory - - checker *types.Checker // transient type-checker state - errorFunc func(error) -} - -func (info *PackageInfo) String() string { return info.Pkg.Path() } - -func (info *PackageInfo) appendError(err error) { - if info.errorFunc != nil { - info.errorFunc(err) - } else { - fmt.Fprintln(os.Stderr, err) - } - info.Errors = append(info.Errors, err) -} - -func (conf *Config) fset() *token.FileSet { - if conf.Fset == nil { - conf.Fset = token.NewFileSet() - } - return conf.Fset -} - -// ParseFile is a convenience function (intended for testing) that invokes -// the parser using the Config's FileSet, which is initialized if nil. -// -// src specifies the parser input as a string, []byte, or io.Reader, and -// filename is its apparent name. If src is nil, the contents of -// filename are read from the file system. -// -func (conf *Config) ParseFile(filename string, src interface{}) (*ast.File, error) { - // TODO(adonovan): use conf.build() etc like parseFiles does. - return parser.ParseFile(conf.fset(), filename, src, conf.ParserMode) -} - -// FromArgsUsage is a partial usage message that applications calling -// FromArgs may wish to include in their -help output. -const FromArgsUsage = ` -<args> is a list of arguments denoting a set of initial packages. -It may take one of two forms: - -1. A list of *.go source files. - - All of the specified files are loaded, parsed and type-checked - as a single package. All the files must belong to the same directory. - -2. A list of import paths, each denoting a package. - - The package's directory is found relative to the $GOROOT and - $GOPATH using similar logic to 'go build', and the *.go files in - that directory are loaded, parsed and type-checked as a single - package. - - In addition, all *_test.go files in the directory are then loaded - and parsed. Those files whose package declaration equals that of - the non-*_test.go files are included in the primary package. Test - files whose package declaration ends with "_test" are type-checked - as another package, the 'external' test package, so that a single - import path may denote two packages. (Whether this behaviour is - enabled is tool-specific, and may depend on additional flags.) - -A '--' argument terminates the list of packages. -` - -// FromArgs interprets args as a set of initial packages to load from -// source and updates the configuration. It returns the list of -// unconsumed arguments. -// -// It is intended for use in command-line interfaces that require a -// set of initial packages to be specified; see FromArgsUsage message -// for details. -// -// Only superficial errors are reported at this stage; errors dependent -// on I/O are detected during Load. -// -func (conf *Config) FromArgs(args []string, xtest bool) ([]string, error) { - var rest []string - for i, arg := range args { - if arg == "--" { - rest = args[i+1:] - args = args[:i] - break // consume "--" and return the remaining args - } - } - - if len(args) > 0 && strings.HasSuffix(args[0], ".go") { - // Assume args is a list of a *.go files - // denoting a single ad hoc package. - for _, arg := range args { - if !strings.HasSuffix(arg, ".go") { - return nil, fmt.Errorf("named files must be .go files: %s", arg) - } - } - conf.CreateFromFilenames("", args...) - } else { - // Assume args are directories each denoting a - // package and (perhaps) an external test, iff xtest. - for _, arg := range args { - if xtest { - conf.ImportWithTests(arg) - } else { - conf.Import(arg) - } - } - } - - return rest, nil -} - -// CreateFromFilenames is a convenience function that adds -// a conf.CreatePkgs entry to create a package of the specified *.go -// files. -// -func (conf *Config) CreateFromFilenames(path string, filenames ...string) { - conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Filenames: filenames}) -} - -// CreateFromFiles is a convenience function that adds a conf.CreatePkgs -// entry to create package of the specified path and parsed files. -// -func (conf *Config) CreateFromFiles(path string, files ...*ast.File) { - conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Files: files}) -} - -// ImportWithTests is a convenience function that adds path to -// ImportPkgs, the set of initial source packages located relative to -// $GOPATH. The package will be augmented by any *_test.go files in -// its directory that contain a "package x" (not "package x_test") -// declaration. -// -// In addition, if any *_test.go files contain a "package x_test" -// declaration, an additional package comprising just those files will -// be added to CreatePkgs. -// -func (conf *Config) ImportWithTests(path string) { conf.addImport(path, true) } - -// Import is a convenience function that adds path to ImportPkgs, the -// set of initial packages that will be imported from source. -// -func (conf *Config) Import(path string) { conf.addImport(path, false) } - -func (conf *Config) addImport(path string, tests bool) { - if path == "C" { - return // ignore; not a real package - } - if conf.ImportPkgs == nil { - conf.ImportPkgs = make(map[string]bool) - } - conf.ImportPkgs[path] = conf.ImportPkgs[path] || tests -} - -// PathEnclosingInterval returns the PackageInfo and ast.Node that -// contain source interval [start, end), and all the node's ancestors -// up to the AST root. It searches all ast.Files of all packages in prog. -// exact is defined as for astutil.PathEnclosingInterval. -// -// The zero value is returned if not found. -// -func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) { - for _, info := range prog.AllPackages { - for _, f := range info.Files { - if f.Pos() == token.NoPos { - // This can happen if the parser saw - // too many errors and bailed out. - // (Use parser.AllErrors to prevent that.) - continue - } - if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) { - continue - } - if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil { - return info, path, exact - } - } - } - return nil, nil, false -} - -// InitialPackages returns a new slice containing the set of initial -// packages (Created + Imported) in unspecified order. -// -func (prog *Program) InitialPackages() []*PackageInfo { - infos := make([]*PackageInfo, 0, len(prog.Created)+len(prog.Imported)) - infos = append(infos, prog.Created...) - for _, info := range prog.Imported { - infos = append(infos, info) - } - return infos -} - -// Package returns the ASTs and results of type checking for the -// specified package. -func (prog *Program) Package(path string) *PackageInfo { - if info, ok := prog.AllPackages[prog.importMap[path]]; ok { - return info - } - for _, info := range prog.Created { - if path == info.Pkg.Path() { - return info - } - } - return nil -} - -// ---------- Implementation ---------- - -// importer holds the working state of the algorithm. -type importer struct { - conf *Config // the client configuration - start time.Time // for logging - - progMu sync.Mutex // guards prog - prog *Program // the resulting program - - // findpkg is a memoization of FindPackage. - findpkgMu sync.Mutex // guards findpkg - findpkg map[findpkgKey]*findpkgValue - - importedMu sync.Mutex // guards imported - imported map[string]*importInfo // all imported packages (incl. failures) by import path - - // import dependency graph: graph[x][y] => x imports y - // - // Since non-importable packages cannot be cyclic, we ignore - // their imports, thus we only need the subgraph over importable - // packages. Nodes are identified by their import paths. - graphMu sync.Mutex - graph map[string]map[string]bool -} - -type findpkgKey struct { - importPath string - fromDir string - mode build.ImportMode -} - -type findpkgValue struct { - ready chan struct{} // closed to broadcast readiness - bp *build.Package - err error -} - -// importInfo tracks the success or failure of a single import. -// -// Upon completion, exactly one of info and err is non-nil: -// info on successful creation of a package, err otherwise. -// A successful package may still contain type errors. -// -type importInfo struct { - path string // import path - info *PackageInfo // results of typechecking (including errors) - complete chan struct{} // closed to broadcast that info is set. -} - -// awaitCompletion blocks until ii is complete, -// i.e. the info field is safe to inspect. -func (ii *importInfo) awaitCompletion() { - <-ii.complete // wait for close -} - -// Complete marks ii as complete. -// Its info and err fields will not be subsequently updated. -func (ii *importInfo) Complete(info *PackageInfo) { - if info == nil { - panic("info == nil") - } - ii.info = info - close(ii.complete) -} - -type importError struct { - path string // import path - err error // reason for failure to create a package -} - -// Load creates the initial packages specified by conf.{Create,Import}Pkgs, -// loading their dependencies packages as needed. -// -// On success, Load returns a Program containing a PackageInfo for -// each package. On failure, it returns an error. -// -// If AllowErrors is true, Load will return a Program even if some -// packages contained I/O, parser or type errors, or if dependencies -// were missing. (Such errors are accessible via PackageInfo.Errors. If -// false, Load will fail if any package had an error. -// -// It is an error if no packages were loaded. -// -func (conf *Config) Load() (*Program, error) { - // Create a simple default error handler for parse/type errors. - if conf.TypeChecker.Error == nil { - conf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) } - } - - // Set default working directory for relative package references. - if conf.Cwd == "" { - var err error - conf.Cwd, err = os.Getwd() - if err != nil { - return nil, err - } - } - - // Install default FindPackage hook using go/build logic. - if conf.FindPackage == nil { - conf.FindPackage = (*build.Context).Import - } - - prog := &Program{ - Fset: conf.fset(), - Imported: make(map[string]*PackageInfo), - importMap: make(map[string]*types.Package), - AllPackages: make(map[*types.Package]*PackageInfo), - } - - imp := importer{ - conf: conf, - prog: prog, - findpkg: make(map[findpkgKey]*findpkgValue), - imported: make(map[string]*importInfo), - start: time.Now(), - graph: make(map[string]map[string]bool), - } - - // -- loading proper (concurrent phase) -------------------------------- - - var errpkgs []string // packages that contained errors - - // Load the initially imported packages and their dependencies, - // in parallel. - // No vendor check on packages imported from the command line. - infos, importErrors := imp.importAll("", conf.Cwd, conf.ImportPkgs, ignoreVendor) - for _, ie := range importErrors { - conf.TypeChecker.Error(ie.err) // failed to create package - errpkgs = append(errpkgs, ie.path) - } - for _, info := range infos { - prog.Imported[info.Pkg.Path()] = info - } - - // Augment the designated initial packages by their tests. - // Dependencies are loaded in parallel. - var xtestPkgs []*build.Package - for importPath, augment := range conf.ImportPkgs { - if !augment { - continue - } - - // No vendor check on packages imported from command line. - bp, err := imp.findPackage(importPath, conf.Cwd, ignoreVendor) - if err != nil { - // Package not found, or can't even parse package declaration. - // Already reported by previous loop; ignore it. - continue - } - - // Needs external test package? - if len(bp.XTestGoFiles) > 0 { - xtestPkgs = append(xtestPkgs, bp) - } - - // Consult the cache using the canonical package path. - path := bp.ImportPath - imp.importedMu.Lock() // (unnecessary, we're sequential here) - ii, ok := imp.imported[path] - // Paranoid checks added due to issue #11012. - if !ok { - // Unreachable. - // The previous loop called importAll and thus - // startLoad for each path in ImportPkgs, which - // populates imp.imported[path] with a non-zero value. - panic(fmt.Sprintf("imported[%q] not found", path)) - } - if ii == nil { - // Unreachable. - // The ii values in this loop are the same as in - // the previous loop, which enforced the invariant - // that at least one of ii.err and ii.info is non-nil. - panic(fmt.Sprintf("imported[%q] == nil", path)) - } - if ii.info == nil { - // Unreachable. - // awaitCompletion has the postcondition - // ii.info != nil. - panic(fmt.Sprintf("imported[%q].info = nil", path)) - } - info := ii.info - imp.importedMu.Unlock() - - // Parse the in-package test files. - files, errs := imp.conf.parsePackageFiles(bp, 't') - for _, err := range errs { - info.appendError(err) - } - - // The test files augmenting package P cannot be imported, - // but may import packages that import P, - // so we must disable the cycle check. - imp.addFiles(info, files, false) - } - - createPkg := func(path, dir string, files []*ast.File, errs []error) { - info := imp.newPackageInfo(path, dir) - for _, err := range errs { - info.appendError(err) - } - - // Ad hoc packages are non-importable, - // so no cycle check is needed. - // addFiles loads dependencies in parallel. - imp.addFiles(info, files, false) - prog.Created = append(prog.Created, info) - } - - // Create packages specified by conf.CreatePkgs. - for _, cp := range conf.CreatePkgs { - files, errs := parseFiles(conf.fset(), conf.build(), nil, conf.Cwd, cp.Filenames, conf.ParserMode) - files = append(files, cp.Files...) - - path := cp.Path - if path == "" { - if len(files) > 0 { - path = files[0].Name.Name - } else { - path = "(unnamed)" - } - } - - dir := conf.Cwd - if len(files) > 0 && files[0].Pos().IsValid() { - dir = filepath.Dir(conf.fset().File(files[0].Pos()).Name()) - } - createPkg(path, dir, files, errs) - } - - // Create external test packages. - sort.Sort(byImportPath(xtestPkgs)) - for _, bp := range xtestPkgs { - files, errs := imp.conf.parsePackageFiles(bp, 'x') - createPkg(bp.ImportPath+"_test", bp.Dir, files, errs) - } - - // -- finishing up (sequential) ---------------------------------------- - - if len(prog.Imported)+len(prog.Created) == 0 { - return nil, errors.New("no initial packages were loaded") - } - - // Create infos for indirectly imported packages. - // e.g. incomplete packages without syntax, loaded from export data. - for _, obj := range prog.importMap { - info := prog.AllPackages[obj] - if info == nil { - prog.AllPackages[obj] = &PackageInfo{Pkg: obj, Importable: true} - } else { - // finished - info.checker = nil - info.errorFunc = nil - } - } - - if !conf.AllowErrors { - // Report errors in indirectly imported packages. - for _, info := range prog.AllPackages { - if len(info.Errors) > 0 { - errpkgs = append(errpkgs, info.Pkg.Path()) - } - } - if errpkgs != nil { - var more string - if len(errpkgs) > 3 { - more = fmt.Sprintf(" and %d more", len(errpkgs)-3) - errpkgs = errpkgs[:3] - } - return nil, fmt.Errorf("couldn't load packages due to errors: %s%s", - strings.Join(errpkgs, ", "), more) - } - } - - markErrorFreePackages(prog.AllPackages) - - return prog, nil -} - -type byImportPath []*build.Package - -func (b byImportPath) Len() int { return len(b) } -func (b byImportPath) Less(i, j int) bool { return b[i].ImportPath < b[j].ImportPath } -func (b byImportPath) Swap(i, j int) { b[i], b[j] = b[j], b[i] } - -// markErrorFreePackages sets the TransitivelyErrorFree flag on all -// applicable packages. -func markErrorFreePackages(allPackages map[*types.Package]*PackageInfo) { - // Build the transpose of the import graph. - importedBy := make(map[*types.Package]map[*types.Package]bool) - for P := range allPackages { - for _, Q := range P.Imports() { - clients, ok := importedBy[Q] - if !ok { - clients = make(map[*types.Package]bool) - importedBy[Q] = clients - } - clients[P] = true - } - } - - // Find all packages reachable from some error package. - reachable := make(map[*types.Package]bool) - var visit func(*types.Package) - visit = func(p *types.Package) { - if !reachable[p] { - reachable[p] = true - for q := range importedBy[p] { - visit(q) - } - } - } - for _, info := range allPackages { - if len(info.Errors) > 0 { - visit(info.Pkg) - } - } - - // Mark the others as "transitively error-free". - for _, info := range allPackages { - if !reachable[info.Pkg] { - info.TransitivelyErrorFree = true - } - } -} - -// build returns the effective build context. -func (conf *Config) build() *build.Context { - if conf.Build != nil { - return conf.Build - } - return &build.Default -} - -// parsePackageFiles enumerates the files belonging to package path, -// then loads, parses and returns them, plus a list of I/O or parse -// errors that were encountered. -// -// 'which' indicates which files to include: -// 'g': include non-test *.go source files (GoFiles + processed CgoFiles) -// 't': include in-package *_test.go source files (TestGoFiles) -// 'x': include external *_test.go source files. (XTestGoFiles) -// -func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) { - if bp.ImportPath == "unsafe" { - return nil, nil - } - var filenames []string - switch which { - case 'g': - filenames = bp.GoFiles - case 't': - filenames = bp.TestGoFiles - case 'x': - filenames = bp.XTestGoFiles - default: - panic(which) - } - - files, errs := parseFiles(conf.fset(), conf.build(), conf.DisplayPath, bp.Dir, filenames, conf.ParserMode) - - // Preprocess CgoFiles and parse the outputs (sequentially). - if which == 'g' && bp.CgoFiles != nil { - cgofiles, err := cgo.ProcessFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode) - if err != nil { - errs = append(errs, err) - } else { - files = append(files, cgofiles...) - } - } - - return files, errs -} - -// doImport imports the package denoted by path. -// It implements the types.Importer signature. -// -// It returns an error if a package could not be created -// (e.g. go/build or parse error), but type errors are reported via -// the types.Config.Error callback (the first of which is also saved -// in the package's PackageInfo). -// -// Idempotent. -// -func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) { - if to == "C" { - // This should be unreachable, but ad hoc packages are - // not currently subject to cgo preprocessing. - // See https://golang.org/issue/11627. - return nil, fmt.Errorf(`the loader doesn't cgo-process ad hoc packages like %q; see Go issue 11627`, - from.Pkg.Path()) - } - - bp, err := imp.findPackage(to, from.dir, 0) - if err != nil { - return nil, err - } - - // The standard unsafe package is handled specially, - // and has no PackageInfo. - if bp.ImportPath == "unsafe" { - return types.Unsafe, nil - } - - // Look for the package in the cache using its canonical path. - path := bp.ImportPath - imp.importedMu.Lock() - ii := imp.imported[path] - imp.importedMu.Unlock() - if ii == nil { - panic("internal error: unexpected import: " + path) - } - if ii.info != nil { - return ii.info.Pkg, nil - } - - // Import of incomplete package: this indicates a cycle. - fromPath := from.Pkg.Path() - if cycle := imp.findPath(path, fromPath); cycle != nil { - // Normalize cycle: start from alphabetically largest node. - pos, start := -1, "" - for i, s := range cycle { - if pos < 0 || s > start { - pos, start = i, s - } - } - cycle = append(cycle, cycle[:pos]...)[pos:] // rotate cycle to start from largest - cycle = append(cycle, cycle[0]) // add start node to end to show cycliness - return nil, fmt.Errorf("import cycle: %s", strings.Join(cycle, " -> ")) - } - - panic("internal error: import of incomplete (yet acyclic) package: " + fromPath) -} - -// findPackage locates the package denoted by the importPath in the -// specified directory. -func (imp *importer) findPackage(importPath, fromDir string, mode build.ImportMode) (*build.Package, error) { - // We use a non-blocking duplicate-suppressing cache (gopl.io §9.7) - // to avoid holding the lock around FindPackage. - key := findpkgKey{importPath, fromDir, mode} - imp.findpkgMu.Lock() - v, ok := imp.findpkg[key] - if ok { - // cache hit - imp.findpkgMu.Unlock() - - <-v.ready // wait for entry to become ready - } else { - // Cache miss: this goroutine becomes responsible for - // populating the map entry and broadcasting its readiness. - v = &findpkgValue{ready: make(chan struct{})} - imp.findpkg[key] = v - imp.findpkgMu.Unlock() - - ioLimit <- true - v.bp, v.err = imp.conf.FindPackage(imp.conf.build(), importPath, fromDir, mode) - <-ioLimit - - if _, ok := v.err.(*build.NoGoError); ok { - v.err = nil // empty directory is not an error - } - - close(v.ready) // broadcast ready condition - } - return v.bp, v.err -} - -// importAll loads, parses, and type-checks the specified packages in -// parallel and returns their completed importInfos in unspecified order. -// -// fromPath is the package path of the importing package, if it is -// importable, "" otherwise. It is used for cycle detection. -// -// fromDir is the directory containing the import declaration that -// caused these imports. -// -func (imp *importer) importAll(fromPath, fromDir string, imports map[string]bool, mode build.ImportMode) (infos []*PackageInfo, errors []importError) { - // TODO(adonovan): opt: do the loop in parallel once - // findPackage is non-blocking. - var pending []*importInfo - for importPath := range imports { - bp, err := imp.findPackage(importPath, fromDir, mode) - if err != nil { - errors = append(errors, importError{ - path: importPath, - err: err, - }) - continue - } - pending = append(pending, imp.startLoad(bp)) - } - - if fromPath != "" { - // We're loading a set of imports. - // - // We must record graph edges from the importing package - // to its dependencies, and check for cycles. - imp.graphMu.Lock() - deps, ok := imp.graph[fromPath] - if !ok { - deps = make(map[string]bool) - imp.graph[fromPath] = deps - } - for _, ii := range pending { - deps[ii.path] = true - } - imp.graphMu.Unlock() - } - - for _, ii := range pending { - if fromPath != "" { - if cycle := imp.findPath(ii.path, fromPath); cycle != nil { - // Cycle-forming import: we must not await its - // completion since it would deadlock. - // - // We don't record the error in ii since - // the error is really associated with the - // cycle-forming edge, not the package itself. - // (Also it would complicate the - // invariants of importPath completion.) - if trace { - fmt.Fprintf(os.Stderr, "import cycle: %q\n", cycle) - } - continue - } - } - ii.awaitCompletion() - infos = append(infos, ii.info) - } - - return infos, errors -} - -// findPath returns an arbitrary path from 'from' to 'to' in the import -// graph, or nil if there was none. -func (imp *importer) findPath(from, to string) []string { - imp.graphMu.Lock() - defer imp.graphMu.Unlock() - - seen := make(map[string]bool) - var search func(stack []string, importPath string) []string - search = func(stack []string, importPath string) []string { - if !seen[importPath] { - seen[importPath] = true - stack = append(stack, importPath) - if importPath == to { - return stack - } - for x := range imp.graph[importPath] { - if p := search(stack, x); p != nil { - return p - } - } - } - return nil - } - return search(make([]string, 0, 20), from) -} - -// startLoad initiates the loading, parsing and type-checking of the -// specified package and its dependencies, if it has not already begun. -// -// It returns an importInfo, not necessarily in a completed state. The -// caller must call awaitCompletion() before accessing its info field. -// -// startLoad is concurrency-safe and idempotent. -// -func (imp *importer) startLoad(bp *build.Package) *importInfo { - path := bp.ImportPath - imp.importedMu.Lock() - ii, ok := imp.imported[path] - if !ok { - ii = &importInfo{path: path, complete: make(chan struct{})} - imp.imported[path] = ii - go func() { - info := imp.load(bp) - ii.Complete(info) - }() - } - imp.importedMu.Unlock() - - return ii -} - -// load implements package loading by parsing Go source files -// located by go/build. -func (imp *importer) load(bp *build.Package) *PackageInfo { - info := imp.newPackageInfo(bp.ImportPath, bp.Dir) - info.Importable = true - files, errs := imp.conf.parsePackageFiles(bp, 'g') - for _, err := range errs { - info.appendError(err) - } - - imp.addFiles(info, files, true) - - imp.progMu.Lock() - imp.prog.importMap[bp.ImportPath] = info.Pkg - imp.progMu.Unlock() - - return info -} - -// addFiles adds and type-checks the specified files to info, loading -// their dependencies if needed. The order of files determines the -// package initialization order. It may be called multiple times on the -// same package. Errors are appended to the info.Errors field. -// -// cycleCheck determines whether the imports within files create -// dependency edges that should be checked for potential cycles. -// -func (imp *importer) addFiles(info *PackageInfo, files []*ast.File, cycleCheck bool) { - // Ensure the dependencies are loaded, in parallel. - var fromPath string - if cycleCheck { - fromPath = info.Pkg.Path() - } - // TODO(adonovan): opt: make the caller do scanImports. - // Callers with a build.Package can skip it. - imp.importAll(fromPath, info.dir, scanImports(files), 0) - - if trace { - fmt.Fprintf(os.Stderr, "%s: start %q (%d)\n", - time.Since(imp.start), info.Pkg.Path(), len(files)) - } - - // Don't call checker.Files on Unsafe, even with zero files, - // because it would mutate the package, which is a global. - if info.Pkg == types.Unsafe { - if len(files) > 0 { - panic(`"unsafe" package contains unexpected files`) - } - } else { - // Ignore the returned (first) error since we - // already collect them all in the PackageInfo. - info.checker.Files(files) - info.Files = append(info.Files, files...) - } - - if imp.conf.AfterTypeCheck != nil { - imp.conf.AfterTypeCheck(info, files) - } - - if trace { - fmt.Fprintf(os.Stderr, "%s: stop %q\n", - time.Since(imp.start), info.Pkg.Path()) - } -} - -func (imp *importer) newPackageInfo(path, dir string) *PackageInfo { - var pkg *types.Package - if path == "unsafe" { - pkg = types.Unsafe - } else { - pkg = types.NewPackage(path, "") - } - info := &PackageInfo{ - Pkg: pkg, - 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), - }, - errorFunc: imp.conf.TypeChecker.Error, - dir: dir, - } - - // Copy the types.Config so we can vary it across PackageInfos. - tc := imp.conf.TypeChecker - tc.IgnoreFuncBodies = false - if f := imp.conf.TypeCheckFuncBodies; f != nil { - tc.IgnoreFuncBodies = !f(path) - } - tc.Importer = closure{imp, info} - tc.Error = info.appendError // appendError wraps the user's Error function - - info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info) - imp.progMu.Lock() - imp.prog.AllPackages[pkg] = info - imp.progMu.Unlock() - return info -} - -type closure struct { - imp *importer - info *PackageInfo -} - -func (c closure) Import(to string) (*types.Package, error) { return c.imp.doImport(c.info, to) } diff --git a/vendor/golang.org/x/tools/go/loader/util.go b/vendor/golang.org/x/tools/go/loader/util.go deleted file mode 100644 index 7f38dd7407..0000000000 --- a/vendor/golang.org/x/tools/go/loader/util.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2013 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 loader - -import ( - "go/ast" - "go/build" - "go/parser" - "go/token" - "io" - "os" - "strconv" - "sync" - - "golang.org/x/tools/go/buildutil" -) - -// We use a counting semaphore to limit -// the number of parallel I/O calls per process. -var ioLimit = make(chan bool, 10) - -// parseFiles parses the Go source files within directory dir and -// returns the ASTs of the ones that could be at least partially parsed, -// along with a list of I/O and parse errors encountered. -// -// I/O is done via ctxt, which may specify a virtual file system. -// displayPath is used to transform the filenames attached to the ASTs. -// -func parseFiles(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, files []string, mode parser.Mode) ([]*ast.File, []error) { - if displayPath == nil { - displayPath = func(path string) string { return path } - } - var wg sync.WaitGroup - n := len(files) - parsed := make([]*ast.File, n) - errors := make([]error, n) - for i, file := range files { - if !buildutil.IsAbsPath(ctxt, file) { - file = buildutil.JoinPath(ctxt, dir, file) - } - wg.Add(1) - go func(i int, file string) { - ioLimit <- true // wait - defer func() { - wg.Done() - <-ioLimit // signal - }() - var rd io.ReadCloser - var err error - if ctxt.OpenFile != nil { - rd, err = ctxt.OpenFile(file) - } else { - rd, err = os.Open(file) - } - if err != nil { - errors[i] = err // open failed - return - } - - // ParseFile may return both an AST and an error. - parsed[i], errors[i] = parser.ParseFile(fset, displayPath(file), rd, mode) - rd.Close() - }(i, file) - } - wg.Wait() - - // Eliminate nils, preserving order. - var o int - for _, f := range parsed { - if f != nil { - parsed[o] = f - o++ - } - } - parsed = parsed[:o] - - o = 0 - for _, err := range errors { - if err != nil { - errors[o] = err - o++ - } - } - errors = errors[:o] - - return parsed, errors -} - -// scanImports returns the set of all import paths from all -// import specs in the specified files. -func scanImports(files []*ast.File) map[string]bool { - imports := make(map[string]bool) - for _, f := range files { - for _, decl := range f.Decls { - if decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT { - for _, spec := range decl.Specs { - spec := spec.(*ast.ImportSpec) - - // NB: do not assume the program is well-formed! - path, err := strconv.Unquote(spec.Path.Value) - if err != nil { - continue // quietly ignore the error - } - if path == "C" { - continue // skip pseudopackage - } - imports[path] = true - } - } - } - } - return imports -} - -// ---------- Internal helpers ---------- - -// TODO(adonovan): make this a method: func (*token.File) Contains(token.Pos) -func tokenFileContainsPos(f *token.File, pos token.Pos) bool { - p := int(pos) - base := f.Base() - return base <= p && p < base+f.Size() -} diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go deleted file mode 100644 index 4bfe28a51f..0000000000 --- a/vendor/golang.org/x/tools/go/packages/doc.go +++ /dev/null @@ -1,221 +0,0 @@ -// 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 packages loads Go packages for inspection and analysis. - -The Load function takes as input a list of patterns and return a list of Package -structs describing individual packages matched by those patterns. -The LoadMode controls the amount of detail in the loaded packages. - -Load passes most patterns directly to the underlying build tool, -but all patterns with the prefix "query=", where query is a -non-empty string of letters from [a-z], are reserved and may be -interpreted as query operators. - -Two query operators are currently supported: "file" and "pattern". - -The query "file=path/to/file.go" matches the package or packages enclosing -the Go source file path/to/file.go. For example "file=~/go/src/fmt/print.go" -might return the packages "fmt" and "fmt [fmt.test]". - -The query "pattern=string" causes "string" to be passed directly to -the underlying build tool. In most cases this is unnecessary, -but an application can use Load("pattern=" + x) as an escaping mechanism -to ensure that x is not interpreted as a query operator if it contains '='. - -All other query operators are reserved for future use and currently -cause Load to report an error. - -The Package struct provides basic information about the package, including - - - ID, a unique identifier for the package in the returned set; - - GoFiles, the names of the package's Go source files; - - Imports, a map from source import strings to the Packages they name; - - Types, the type information for the package's exported symbols; - - Syntax, the parsed syntax trees for the package's source code; and - - TypeInfo, the result of a complete type-check of the package syntax trees. - -(See the documentation for type Package for the complete list of fields -and more detailed descriptions.) - -For example, - - Load(nil, "bytes", "unicode...") - -returns four Package structs describing the standard library packages -bytes, unicode, unicode/utf16, and unicode/utf8. Note that one pattern -can match multiple packages and that a package might be matched by -multiple patterns: in general it is not possible to determine which -packages correspond to which patterns. - -Note that the list returned by Load contains only the packages matched -by the patterns. Their dependencies can be found by walking the import -graph using the Imports fields. - -The Load function can be configured by passing a pointer to a Config as -the first argument. A nil Config is equivalent to the zero Config, which -causes Load to run in LoadFiles mode, collecting minimal information. -See the documentation for type Config for details. - -As noted earlier, the Config.Mode controls the amount of detail -reported about the loaded packages. See the documentation for type LoadMode -for details. - -Most tools should pass their command-line arguments (after any flags) -uninterpreted to the loader, so that the loader can interpret them -according to the conventions of the underlying build system. -See the Example function for typical usage. - -*/ -package packages // import "golang.org/x/tools/go/packages" - -/* - -Motivation and design considerations - -The new package's design solves problems addressed by two existing -packages: go/build, which locates and describes packages, and -golang.org/x/tools/go/loader, which loads, parses and type-checks them. -The go/build.Package structure encodes too much of the 'go build' way -of organizing projects, leaving us in need of a data type that describes a -package of Go source code independent of the underlying build system. -We wanted something that works equally well with go build and vgo, and -also other build systems such as Bazel and Blaze, making it possible to -construct analysis tools that work in all these environments. -Tools such as errcheck and staticcheck were essentially unavailable to -the Go community at Google, and some of Google's internal tools for Go -are unavailable externally. -This new package provides a uniform way to obtain package metadata by -querying each of these build systems, optionally supporting their -preferred command-line notations for packages, so that tools integrate -neatly with users' build environments. The Metadata query function -executes an external query tool appropriate to the current workspace. - -Loading packages always returns the complete import graph "all the way down", -even if all you want is information about a single package, because the query -mechanisms of all the build systems we currently support ({go,vgo} list, and -blaze/bazel aspect-based query) cannot provide detailed information -about one package without visiting all its dependencies too, so there is -no additional asymptotic cost to providing transitive information. -(This property might not be true of a hypothetical 5th build system.) - -In calls to TypeCheck, all initial packages, and any package that -transitively depends on one of them, must be loaded from source. -Consider A->B->C->D->E: if A,C are initial, A,B,C must be loaded from -source; D may be loaded from export data, and E may not be loaded at all -(though it's possible that D's export data mentions it, so a -types.Package may be created for it and exposed.) - -The old loader had a feature to suppress type-checking of function -bodies on a per-package basis, primarily intended to reduce the work of -obtaining type information for imported packages. Now that imports are -satisfied by export data, the optimization no longer seems necessary. - -Despite some early attempts, the old loader did not exploit export data, -instead always using the equivalent of WholeProgram mode. This was due -to the complexity of mixing source and export data packages (now -resolved by the upward traversal mentioned above), and because export data -files were nearly always missing or stale. Now that 'go build' supports -caching, all the underlying build systems can guarantee to produce -export data in a reasonable (amortized) time. - -Test "main" packages synthesized by the build system are now reported as -first-class packages, avoiding the need for clients (such as go/ssa) to -reinvent this generation logic. - -One way in which go/packages is simpler than the old loader is in its -treatment of in-package tests. In-package tests are packages that -consist of all the files of the library under test, plus the test files. -The old loader constructed in-package tests by a two-phase process of -mutation called "augmentation": first it would construct and type check -all the ordinary library packages and type-check the packages that -depend on them; then it would add more (test) files to the package and -type-check again. This two-phase approach had four major problems: -1) in processing the tests, the loader modified the library package, - leaving no way for a client application to see both the test - package and the library package; one would mutate into the other. -2) because test files can declare additional methods on types defined in - the library portion of the package, the dispatch of method calls in - the library portion was affected by the presence of the test files. - This should have been a clue that the packages were logically - different. -3) this model of "augmentation" assumed at most one in-package test - per library package, which is true of projects using 'go build', - but not other build systems. -4) because of the two-phase nature of test processing, all packages that - import the library package had to be processed before augmentation, - forcing a "one-shot" API and preventing the client from calling Load - in several times in sequence as is now possible in WholeProgram mode. - (TypeCheck mode has a similar one-shot restriction for a different reason.) - -Early drafts of this package supported "multi-shot" operation. -Although it allowed clients to make a sequence of calls (or concurrent -calls) to Load, building up the graph of Packages incrementally, -it was of marginal value: it complicated the API -(since it allowed some options to vary across calls but not others), -it complicated the implementation, -it cannot be made to work in Types mode, as explained above, -and it was less efficient than making one combined call (when this is possible). -Among the clients we have inspected, none made multiple calls to load -but could not be easily and satisfactorily modified to make only a single call. -However, applications changes may be required. -For example, the ssadump command loads the user-specified packages -and in addition the runtime package. It is tempting to simply append -"runtime" to the user-provided list, but that does not work if the user -specified an ad-hoc package such as [a.go b.go]. -Instead, ssadump no longer requests the runtime package, -but seeks it among the dependencies of the user-specified packages, -and emits an error if it is not found. - -Overlays: The Overlay field in the Config allows providing alternate contents -for Go source files, by providing a mapping from file path to contents. -go/packages will pull in new imports added in overlay files when go/packages -is run in LoadImports mode or greater. -Overlay support for the go list driver isn't complete yet: if the file doesn't -exist on disk, it will only be recognized in an overlay if it is a non-test file -and the package would be reported even without the overlay. - -Questions & Tasks - -- Add GOARCH/GOOS? - They are not portable concepts, but could be made portable. - Our goal has been to allow users to express themselves using the conventions - of the underlying build system: if the build system honors GOARCH - during a build and during a metadata query, then so should - applications built atop that query mechanism. - Conversely, if the target architecture of the build is determined by - command-line flags, the application can pass the relevant - flags through to the build system using a command such as: - myapp -query_flag="--cpu=amd64" -query_flag="--os=darwin" - However, this approach is low-level, unwieldy, and non-portable. - GOOS and GOARCH seem important enough to warrant a dedicated option. - -- How should we handle partial failures such as a mixture of good and - malformed patterns, existing and non-existent packages, successful and - failed builds, import failures, import cycles, and so on, in a call to - Load? - -- Support bazel, blaze, and go1.10 list, not just go1.11 list. - -- Handle (and test) various partial success cases, e.g. - a mixture of good packages and: - invalid patterns - nonexistent packages - empty packages - packages with malformed package or import declarations - unreadable files - import cycles - other parse errors - type errors - Make sure we record errors at the correct place in the graph. - -- Missing packages among initial arguments are not reported. - Return bogus packages for them, like golist does. - -- "undeclared name" errors (for example) are reported out of source file - order. I suspect this is due to the breadth-first resolution now used - by go/types. Is that a bug? Discuss with gri. - -*/ diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go deleted file mode 100644 index 7242a0a7d2..0000000000 --- a/vendor/golang.org/x/tools/go/packages/external.go +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -// This file enables an external tool to intercept package requests. -// If the tool is present then its results are used in preference to -// the go list command. - -package packages - -import ( - "bytes" - "encoding/json" - "fmt" - exec "golang.org/x/sys/execabs" - "os" - "strings" -) - -// The Driver Protocol -// -// The driver, given the inputs to a call to Load, returns metadata about the packages specified. -// This allows for different build systems to support go/packages by telling go/packages how the -// packages' source is organized. -// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in -// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package -// documentation in doc.go for the full description of the patterns that need to be supported. -// A driver receives as a JSON-serialized driverRequest struct in standard input and will -// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output. - -// driverRequest is used to provide the portion of Load's Config that is needed by a driver. -type driverRequest struct { - Mode LoadMode `json:"mode"` - // Env specifies the environment the underlying build system should be run in. - Env []string `json:"env"` - // BuildFlags are flags that should be passed to the underlying build system. - BuildFlags []string `json:"build_flags"` - // Tests specifies whether the patterns should also return test packages. - Tests bool `json:"tests"` - // Overlay maps file paths (relative to the driver's working directory) to the byte contents - // of overlay files. - Overlay map[string][]byte `json:"overlay"` -} - -// findExternalDriver returns the file path of a tool that supplies -// the build system package structure, or "" if not found." -// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its -// value, otherwise it searches for a binary named gopackagesdriver on the PATH. -func findExternalDriver(cfg *Config) driver { - const toolPrefix = "GOPACKAGESDRIVER=" - tool := "" - for _, env := range cfg.Env { - if val := strings.TrimPrefix(env, toolPrefix); val != env { - tool = val - } - } - if tool != "" && tool == "off" { - return nil - } - if tool == "" { - var err error - tool, err = exec.LookPath("gopackagesdriver") - if err != nil { - return nil - } - } - return func(cfg *Config, words ...string) (*driverResponse, error) { - req, err := json.Marshal(driverRequest{ - Mode: cfg.Mode, - Env: cfg.Env, - BuildFlags: cfg.BuildFlags, - Tests: cfg.Tests, - Overlay: cfg.Overlay, - }) - if err != nil { - return nil, fmt.Errorf("failed to encode message to driver tool: %v", err) - } - - buf := new(bytes.Buffer) - stderr := new(bytes.Buffer) - cmd := exec.CommandContext(cfg.Context, tool, words...) - cmd.Dir = cfg.Dir - cmd.Env = cfg.Env - cmd.Stdin = bytes.NewReader(req) - cmd.Stdout = buf - cmd.Stderr = stderr - - if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr) - } - if len(stderr.Bytes()) != 0 && os.Getenv("GOPACKAGESPRINTDRIVERERRORS") != "" { - fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr) - } - - var response driverResponse - if err := json.Unmarshal(buf.Bytes(), &response); err != nil { - return nil, err - } - return &response, nil - } -} diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go deleted file mode 100644 index ec417ba830..0000000000 --- a/vendor/golang.org/x/tools/go/packages/golist.go +++ /dev/null @@ -1,1096 +0,0 @@ -// 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 packages - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "go/types" - exec "golang.org/x/sys/execabs" - "io/ioutil" - "log" - "os" - "path" - "path/filepath" - "reflect" - "sort" - "strconv" - "strings" - "sync" - "unicode" - - "golang.org/x/tools/go/internal/packagesdriver" - "golang.org/x/tools/internal/gocommand" - "golang.org/x/xerrors" -) - -// debug controls verbose logging. -var debug, _ = strconv.ParseBool(os.Getenv("GOPACKAGESDEBUG")) - -// A goTooOldError reports that the go command -// found by exec.LookPath is too old to use the new go list behavior. -type goTooOldError struct { - error -} - -// responseDeduper wraps a driverResponse, deduplicating its contents. -type responseDeduper struct { - seenRoots map[string]bool - seenPackages map[string]*Package - dr *driverResponse -} - -func newDeduper() *responseDeduper { - return &responseDeduper{ - dr: &driverResponse{}, - seenRoots: map[string]bool{}, - seenPackages: map[string]*Package{}, - } -} - -// addAll fills in r with a driverResponse. -func (r *responseDeduper) addAll(dr *driverResponse) { - for _, pkg := range dr.Packages { - r.addPackage(pkg) - } - for _, root := range dr.Roots { - r.addRoot(root) - } -} - -func (r *responseDeduper) addPackage(p *Package) { - if r.seenPackages[p.ID] != nil { - return - } - r.seenPackages[p.ID] = p - r.dr.Packages = append(r.dr.Packages, p) -} - -func (r *responseDeduper) addRoot(id string) { - if r.seenRoots[id] { - return - } - r.seenRoots[id] = true - r.dr.Roots = append(r.dr.Roots, id) -} - -type golistState struct { - cfg *Config - ctx context.Context - - envOnce sync.Once - goEnvError error - goEnv map[string]string - - rootsOnce sync.Once - rootDirsError error - rootDirs map[string]string - - goVersionOnce sync.Once - goVersionError error - goVersion int // The X in Go 1.X. - - // vendorDirs caches the (non)existence of vendor directories. - vendorDirs map[string]bool -} - -// getEnv returns Go environment variables. Only specific variables are -// populated -- computing all of them is slow. -func (state *golistState) getEnv() (map[string]string, error) { - state.envOnce.Do(func() { - var b *bytes.Buffer - b, state.goEnvError = state.invokeGo("env", "-json", "GOMOD", "GOPATH") - if state.goEnvError != nil { - return - } - - state.goEnv = make(map[string]string) - decoder := json.NewDecoder(b) - if state.goEnvError = decoder.Decode(&state.goEnv); state.goEnvError != nil { - return - } - }) - return state.goEnv, state.goEnvError -} - -// mustGetEnv is a convenience function that can be used if getEnv has already succeeded. -func (state *golistState) mustGetEnv() map[string]string { - env, err := state.getEnv() - if err != nil { - panic(fmt.Sprintf("mustGetEnv: %v", err)) - } - return env -} - -// goListDriver uses the go list command to interpret the patterns and produce -// the build system package structure. -// See driver for more details. -func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { - // Make sure that any asynchronous go commands are killed when we return. - parentCtx := cfg.Context - if parentCtx == nil { - parentCtx = context.Background() - } - ctx, cancel := context.WithCancel(parentCtx) - defer cancel() - - response := newDeduper() - - state := &golistState{ - cfg: cfg, - ctx: ctx, - vendorDirs: map[string]bool{}, - } - - // Fill in response.Sizes asynchronously if necessary. - var sizeserr error - var sizeswg sync.WaitGroup - if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { - sizeswg.Add(1) - go func() { - var sizes types.Sizes - sizes, sizeserr = packagesdriver.GetSizesGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner) - // types.SizesFor always returns nil or a *types.StdSizes. - response.dr.Sizes, _ = sizes.(*types.StdSizes) - sizeswg.Done() - }() - } - - // Determine files requested in contains patterns - var containFiles []string - restPatterns := make([]string, 0, len(patterns)) - // Extract file= and other [querytype]= patterns. Report an error if querytype - // doesn't exist. -extractQueries: - for _, pattern := range patterns { - eqidx := strings.Index(pattern, "=") - if eqidx < 0 { - restPatterns = append(restPatterns, pattern) - } else { - query, value := pattern[:eqidx], pattern[eqidx+len("="):] - switch query { - case "file": - containFiles = append(containFiles, value) - case "pattern": - restPatterns = append(restPatterns, value) - case "": // not a reserved query - restPatterns = append(restPatterns, pattern) - default: - for _, rune := range query { - if rune < 'a' || rune > 'z' { // not a reserved query - restPatterns = append(restPatterns, pattern) - continue extractQueries - } - } - // Reject all other patterns containing "=" - return nil, fmt.Errorf("invalid query type %q in query pattern %q", query, pattern) - } - } - } - - // See if we have any patterns to pass through to go list. Zero initial - // patterns also requires a go list call, since it's the equivalent of - // ".". - if len(restPatterns) > 0 || len(patterns) == 0 { - dr, err := state.createDriverResponse(restPatterns...) - if err != nil { - return nil, err - } - response.addAll(dr) - } - - if len(containFiles) != 0 { - if err := state.runContainsQueries(response, containFiles); err != nil { - return nil, err - } - } - - // Only use go/packages' overlay processing if we're using a Go version - // below 1.16. Otherwise, go list handles it. - if goVersion, err := state.getGoVersion(); err == nil && goVersion < 16 { - modifiedPkgs, needPkgs, err := state.processGolistOverlay(response) - if err != nil { - return nil, err - } - - var containsCandidates []string - if len(containFiles) > 0 { - containsCandidates = append(containsCandidates, modifiedPkgs...) - containsCandidates = append(containsCandidates, needPkgs...) - } - if err := state.addNeededOverlayPackages(response, needPkgs); err != nil { - return nil, err - } - // Check candidate packages for containFiles. - if len(containFiles) > 0 { - for _, id := range containsCandidates { - pkg, ok := response.seenPackages[id] - if !ok { - response.addPackage(&Package{ - ID: id, - Errors: []Error{{ - Kind: ListError, - Msg: fmt.Sprintf("package %s expected but not seen", id), - }}, - }) - continue - } - for _, f := range containFiles { - for _, g := range pkg.GoFiles { - if sameFile(f, g) { - response.addRoot(id) - } - } - } - } - } - // Add root for any package that matches a pattern. This applies only to - // packages that are modified by overlays, since they are not added as - // roots automatically. - for _, pattern := range restPatterns { - match := matchPattern(pattern) - for _, pkgID := range modifiedPkgs { - pkg, ok := response.seenPackages[pkgID] - if !ok { - continue - } - if match(pkg.PkgPath) { - response.addRoot(pkg.ID) - } - } - } - } - - sizeswg.Wait() - if sizeserr != nil { - return nil, sizeserr - } - return response.dr, nil -} - -func (state *golistState) addNeededOverlayPackages(response *responseDeduper, pkgs []string) error { - if len(pkgs) == 0 { - return nil - } - dr, err := state.createDriverResponse(pkgs...) - if err != nil { - return err - } - for _, pkg := range dr.Packages { - response.addPackage(pkg) - } - _, needPkgs, err := state.processGolistOverlay(response) - if err != nil { - return err - } - return state.addNeededOverlayPackages(response, needPkgs) -} - -func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error { - for _, query := range queries { - // TODO(matloob): Do only one query per directory. - fdir := filepath.Dir(query) - // Pass absolute path of directory to go list so that it knows to treat it as a directory, - // not a package path. - pattern, err := filepath.Abs(fdir) - if err != nil { - return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err) - } - dirResponse, err := state.createDriverResponse(pattern) - - // If there was an error loading the package, or the package is returned - // with errors, try to load the file as an ad-hoc package. - // Usually the error will appear in a returned package, but may not if we're - // in module mode and the ad-hoc is located outside a module. - if err != nil || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 && - len(dirResponse.Packages[0].Errors) == 1 { - var queryErr error - if dirResponse, queryErr = state.adhocPackage(pattern, query); queryErr != nil { - return err // return the original error - } - } - isRoot := make(map[string]bool, len(dirResponse.Roots)) - for _, root := range dirResponse.Roots { - isRoot[root] = true - } - for _, pkg := range dirResponse.Packages { - // Add any new packages to the main set - // We don't bother to filter packages that will be dropped by the changes of roots, - // that will happen anyway during graph construction outside this function. - // Over-reporting packages is not a problem. - response.addPackage(pkg) - // if the package was not a root one, it cannot have the file - if !isRoot[pkg.ID] { - continue - } - for _, pkgFile := range pkg.GoFiles { - if filepath.Base(query) == filepath.Base(pkgFile) { - response.addRoot(pkg.ID) - break - } - } - } - } - return nil -} - -// adhocPackage attempts to load or construct an ad-hoc package for a given -// query, if the original call to the driver produced inadequate results. -func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) { - response, err := state.createDriverResponse(query) - if err != nil { - return nil, err - } - // If we get nothing back from `go list`, - // try to make this file into its own ad-hoc package. - // TODO(rstambler): Should this check against the original response? - if len(response.Packages) == 0 { - response.Packages = append(response.Packages, &Package{ - ID: "command-line-arguments", - PkgPath: query, - GoFiles: []string{query}, - CompiledGoFiles: []string{query}, - Imports: make(map[string]*Package), - }) - response.Roots = append(response.Roots, "command-line-arguments") - } - // Handle special cases. - if len(response.Packages) == 1 { - // golang/go#33482: If this is a file= query for ad-hoc packages where - // the file only exists on an overlay, and exists outside of a module, - // add the file to the package and remove the errors. - if response.Packages[0].ID == "command-line-arguments" || - filepath.ToSlash(response.Packages[0].PkgPath) == filepath.ToSlash(query) { - if len(response.Packages[0].GoFiles) == 0 { - filename := filepath.Join(pattern, filepath.Base(query)) // avoid recomputing abspath - // TODO(matloob): check if the file is outside of a root dir? - for path := range state.cfg.Overlay { - if path == filename { - response.Packages[0].Errors = nil - response.Packages[0].GoFiles = []string{path} - response.Packages[0].CompiledGoFiles = []string{path} - } - } - } - } - } - return response, nil -} - -// Fields must match go list; -// see $GOROOT/src/cmd/go/internal/load/pkg.go. -type jsonPackage struct { - ImportPath string - Dir string - Name string - Export string - GoFiles []string - CompiledGoFiles []string - IgnoredGoFiles []string - IgnoredOtherFiles []string - CFiles []string - CgoFiles []string - CXXFiles []string - MFiles []string - HFiles []string - FFiles []string - SFiles []string - SwigFiles []string - SwigCXXFiles []string - SysoFiles []string - Imports []string - ImportMap map[string]string - Deps []string - Module *Module - TestGoFiles []string - TestImports []string - XTestGoFiles []string - XTestImports []string - ForTest string // q in a "p [q.test]" package, else "" - DepOnly bool - - Error *jsonPackageError -} - -type jsonPackageError struct { - ImportStack []string - Pos string - Err string -} - -func otherFiles(p *jsonPackage) [][]string { - return [][]string{p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.SwigFiles, p.SwigCXXFiles, p.SysoFiles} -} - -// createDriverResponse uses the "go list" command to expand the pattern -// words and return a response for the specified packages. -func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) { - // go list uses the following identifiers in ImportPath and Imports: - // - // "p" -- importable package or main (command) - // "q.test" -- q's test executable - // "p [q.test]" -- variant of p as built for q's test executable - // "q_test [q.test]" -- q's external test package - // - // The packages p that are built differently for a test q.test - // are q itself, plus any helpers used by the external test q_test, - // typically including "testing" and all its dependencies. - - // Run "go list" for complete - // information on the specified packages. - buf, err := state.invokeGo("list", golistargs(state.cfg, words)...) - if err != nil { - return nil, err - } - seen := make(map[string]*jsonPackage) - pkgs := make(map[string]*Package) - additionalErrors := make(map[string][]Error) - // Decode the JSON and convert it to Package form. - var response driverResponse - for dec := json.NewDecoder(buf); dec.More(); { - p := new(jsonPackage) - if err := dec.Decode(p); err != nil { - return nil, fmt.Errorf("JSON decoding failed: %v", err) - } - - if p.ImportPath == "" { - // The documentation for go list says that “[e]rroneous packages will have - // a non-empty ImportPath”. If for some reason it comes back empty, we - // prefer to error out rather than silently discarding data or handing - // back a package without any way to refer to it. - if p.Error != nil { - return nil, Error{ - Pos: p.Error.Pos, - Msg: p.Error.Err, - } - } - return nil, fmt.Errorf("package missing import path: %+v", p) - } - - // Work around https://golang.org/issue/33157: - // go list -e, when given an absolute path, will find the package contained at - // that directory. But when no package exists there, it will return a fake package - // with an error and the ImportPath set to the absolute path provided to go list. - // Try to convert that absolute path to what its package path would be if it's - // contained in a known module or GOPATH entry. This will allow the package to be - // properly "reclaimed" when overlays are processed. - if filepath.IsAbs(p.ImportPath) && p.Error != nil { - pkgPath, ok, err := state.getPkgPath(p.ImportPath) - if err != nil { - return nil, err - } - if ok { - p.ImportPath = pkgPath - } - } - - if old, found := seen[p.ImportPath]; found { - // If one version of the package has an error, and the other doesn't, assume - // that this is a case where go list is reporting a fake dependency variant - // of the imported package: When a package tries to invalidly import another - // package, go list emits a variant of the imported package (with the same - // import path, but with an error on it, and the package will have a - // DepError set on it). An example of when this can happen is for imports of - // main packages: main packages can not be imported, but they may be - // separately matched and listed by another pattern. - // See golang.org/issue/36188 for more details. - - // The plan is that eventually, hopefully in Go 1.15, the error will be - // reported on the importing package rather than the duplicate "fake" - // version of the imported package. Once all supported versions of Go - // have the new behavior this logic can be deleted. - // TODO(matloob): delete the workaround logic once all supported versions of - // Go return the errors on the proper package. - - // There should be exactly one version of a package that doesn't have an - // error. - if old.Error == nil && p.Error == nil { - if !reflect.DeepEqual(p, old) { - return nil, fmt.Errorf("internal error: go list gives conflicting information for package %v", p.ImportPath) - } - continue - } - - // Determine if this package's error needs to be bubbled up. - // This is a hack, and we expect for go list to eventually set the error - // on the package. - if old.Error != nil { - var errkind string - if strings.Contains(old.Error.Err, "not an importable package") { - errkind = "not an importable package" - } else if strings.Contains(old.Error.Err, "use of internal package") && strings.Contains(old.Error.Err, "not allowed") { - errkind = "use of internal package not allowed" - } - if errkind != "" { - if len(old.Error.ImportStack) < 1 { - return nil, fmt.Errorf(`internal error: go list gave a %q error with empty import stack`, errkind) - } - importingPkg := old.Error.ImportStack[len(old.Error.ImportStack)-1] - if importingPkg == old.ImportPath { - // Using an older version of Go which put this package itself on top of import - // stack, instead of the importer. Look for importer in second from top - // position. - if len(old.Error.ImportStack) < 2 { - return nil, fmt.Errorf(`internal error: go list gave a %q error with an import stack without importing package`, errkind) - } - importingPkg = old.Error.ImportStack[len(old.Error.ImportStack)-2] - } - additionalErrors[importingPkg] = append(additionalErrors[importingPkg], Error{ - Pos: old.Error.Pos, - Msg: old.Error.Err, - Kind: ListError, - }) - } - } - - // Make sure that if there's a version of the package without an error, - // that's the one reported to the user. - if old.Error == nil { - continue - } - - // This package will replace the old one at the end of the loop. - } - seen[p.ImportPath] = p - - pkg := &Package{ - Name: p.Name, - ID: p.ImportPath, - GoFiles: absJoin(p.Dir, p.GoFiles, p.CgoFiles), - CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles), - OtherFiles: absJoin(p.Dir, otherFiles(p)...), - IgnoredFiles: absJoin(p.Dir, p.IgnoredGoFiles, p.IgnoredOtherFiles), - forTest: p.ForTest, - Module: p.Module, - } - - if (state.cfg.Mode&typecheckCgo) != 0 && len(p.CgoFiles) != 0 { - if len(p.CompiledGoFiles) > len(p.GoFiles) { - // We need the cgo definitions, which are in the first - // CompiledGoFile after the non-cgo ones. This is a hack but there - // isn't currently a better way to find it. We also need the pure - // Go files and unprocessed cgo files, all of which are already - // in pkg.GoFiles. - cgoTypes := p.CompiledGoFiles[len(p.GoFiles)] - pkg.CompiledGoFiles = append([]string{cgoTypes}, pkg.GoFiles...) - } else { - // golang/go#38990: go list silently fails to do cgo processing - pkg.CompiledGoFiles = nil - pkg.Errors = append(pkg.Errors, Error{ - Msg: "go list failed to return CompiledGoFiles; https://golang.org/issue/38990?", - Kind: ListError, - }) - } - } - - // Work around https://golang.org/issue/28749: - // cmd/go puts assembly, C, and C++ files in CompiledGoFiles. - // Filter out any elements of CompiledGoFiles that are also in OtherFiles. - // We have to keep this workaround in place until go1.12 is a distant memory. - if len(pkg.OtherFiles) > 0 { - other := make(map[string]bool, len(pkg.OtherFiles)) - for _, f := range pkg.OtherFiles { - other[f] = true - } - - out := pkg.CompiledGoFiles[:0] - for _, f := range pkg.CompiledGoFiles { - if other[f] { - continue - } - out = append(out, f) - } - pkg.CompiledGoFiles = out - } - - // Extract the PkgPath from the package's ID. - if i := strings.IndexByte(pkg.ID, ' '); i >= 0 { - pkg.PkgPath = pkg.ID[:i] - } else { - pkg.PkgPath = pkg.ID - } - - if pkg.PkgPath == "unsafe" { - pkg.GoFiles = nil // ignore fake unsafe.go file - } - - // Assume go list emits only absolute paths for Dir. - if p.Dir != "" && !filepath.IsAbs(p.Dir) { - log.Fatalf("internal error: go list returned non-absolute Package.Dir: %s", p.Dir) - } - - if p.Export != "" && !filepath.IsAbs(p.Export) { - pkg.ExportFile = filepath.Join(p.Dir, p.Export) - } else { - pkg.ExportFile = p.Export - } - - // imports - // - // Imports contains the IDs of all imported packages. - // ImportsMap records (path, ID) only where they differ. - ids := make(map[string]bool) - for _, id := range p.Imports { - ids[id] = true - } - pkg.Imports = make(map[string]*Package) - for path, id := range p.ImportMap { - pkg.Imports[path] = &Package{ID: id} // non-identity import - delete(ids, id) - } - for id := range ids { - if id == "C" { - continue - } - - pkg.Imports[id] = &Package{ID: id} // identity import - } - if !p.DepOnly { - response.Roots = append(response.Roots, pkg.ID) - } - - // Work around for pre-go.1.11 versions of go list. - // TODO(matloob): they should be handled by the fallback. - // Can we delete this? - if len(pkg.CompiledGoFiles) == 0 { - pkg.CompiledGoFiles = pkg.GoFiles - } - - // Temporary work-around for golang/go#39986. Parse filenames out of - // error messages. This happens if there are unrecoverable syntax - // errors in the source, so we can't match on a specific error message. - if err := p.Error; err != nil && state.shouldAddFilenameFromError(p) { - addFilenameFromPos := func(pos string) bool { - split := strings.Split(pos, ":") - if len(split) < 1 { - return false - } - filename := strings.TrimSpace(split[0]) - if filename == "" { - return false - } - if !filepath.IsAbs(filename) { - filename = filepath.Join(state.cfg.Dir, filename) - } - info, _ := os.Stat(filename) - if info == nil { - return false - } - pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, filename) - pkg.GoFiles = append(pkg.GoFiles, filename) - return true - } - found := addFilenameFromPos(err.Pos) - // In some cases, go list only reports the error position in the - // error text, not the error position. One such case is when the - // file's package name is a keyword (see golang.org/issue/39763). - if !found { - addFilenameFromPos(err.Err) - } - } - - if p.Error != nil { - msg := strings.TrimSpace(p.Error.Err) // Trim to work around golang.org/issue/32363. - // Address golang.org/issue/35964 by appending import stack to error message. - if msg == "import cycle not allowed" && len(p.Error.ImportStack) != 0 { - msg += fmt.Sprintf(": import stack: %v", p.Error.ImportStack) - } - pkg.Errors = append(pkg.Errors, Error{ - Pos: p.Error.Pos, - Msg: msg, - Kind: ListError, - }) - } - - pkgs[pkg.ID] = pkg - } - - for id, errs := range additionalErrors { - if p, ok := pkgs[id]; ok { - p.Errors = append(p.Errors, errs...) - } - } - for _, pkg := range pkgs { - response.Packages = append(response.Packages, pkg) - } - sort.Slice(response.Packages, func(i, j int) bool { return response.Packages[i].ID < response.Packages[j].ID }) - - return &response, nil -} - -func (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool { - if len(p.GoFiles) > 0 || len(p.CompiledGoFiles) > 0 { - return false - } - - goV, err := state.getGoVersion() - if err != nil { - return false - } - - // On Go 1.14 and earlier, only add filenames from errors if the import stack is empty. - // The import stack behaves differently for these versions than newer Go versions. - if goV < 15 { - return len(p.Error.ImportStack) == 0 - } - - // On Go 1.15 and later, only parse filenames out of error if there's no import stack, - // or the current package is at the top of the import stack. This is not guaranteed - // to work perfectly, but should avoid some cases where files in errors don't belong to this - // package. - return len(p.Error.ImportStack) == 0 || p.Error.ImportStack[len(p.Error.ImportStack)-1] == p.ImportPath -} - -func (state *golistState) getGoVersion() (int, error) { - state.goVersionOnce.Do(func() { - state.goVersion, state.goVersionError = gocommand.GoVersion(state.ctx, state.cfgInvocation(), state.cfg.gocmdRunner) - }) - return state.goVersion, state.goVersionError -} - -// getPkgPath finds the package path of a directory if it's relative to a root -// directory. -func (state *golistState) getPkgPath(dir string) (string, bool, error) { - absDir, err := filepath.Abs(dir) - if err != nil { - return "", false, err - } - roots, err := state.determineRootDirs() - if err != nil { - return "", false, err - } - - for rdir, rpath := range roots { - // Make sure that the directory is in the module, - // to avoid creating a path relative to another module. - if !strings.HasPrefix(absDir, rdir) { - continue - } - // TODO(matloob): This doesn't properly handle symlinks. - r, err := filepath.Rel(rdir, dir) - if err != nil { - continue - } - if rpath != "" { - // We choose only one root even though the directory even it can belong in multiple modules - // or GOPATH entries. This is okay because we only need to work with absolute dirs when a - // file is missing from disk, for instance when gopls calls go/packages in an overlay. - // Once the file is saved, gopls, or the next invocation of the tool will get the correct - // result straight from golist. - // TODO(matloob): Implement module tiebreaking? - return path.Join(rpath, filepath.ToSlash(r)), true, nil - } - return filepath.ToSlash(r), true, nil - } - return "", false, nil -} - -// absJoin absolutizes and flattens the lists of files. -func absJoin(dir string, fileses ...[]string) (res []string) { - for _, files := range fileses { - for _, file := range files { - if !filepath.IsAbs(file) { - file = filepath.Join(dir, file) - } - res = append(res, file) - } - } - return res -} - -func golistargs(cfg *Config, words []string) []string { - const findFlags = NeedImports | NeedTypes | NeedSyntax | NeedTypesInfo - fullargs := []string{ - "-e", "-json", - fmt.Sprintf("-compiled=%t", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypes|NeedTypesInfo|NeedTypesSizes) != 0), - fmt.Sprintf("-test=%t", cfg.Tests), - fmt.Sprintf("-export=%t", usesExportData(cfg)), - fmt.Sprintf("-deps=%t", cfg.Mode&NeedImports != 0), - // go list doesn't let you pass -test and -find together, - // probably because you'd just get the TestMain. - fmt.Sprintf("-find=%t", !cfg.Tests && cfg.Mode&findFlags == 0), - } - fullargs = append(fullargs, cfg.BuildFlags...) - fullargs = append(fullargs, "--") - fullargs = append(fullargs, words...) - return fullargs -} - -// cfgInvocation returns an Invocation that reflects cfg's settings. -func (state *golistState) cfgInvocation() gocommand.Invocation { - cfg := state.cfg - return gocommand.Invocation{ - BuildFlags: cfg.BuildFlags, - ModFile: cfg.modFile, - ModFlag: cfg.modFlag, - CleanEnv: cfg.Env != nil, - Env: cfg.Env, - Logf: cfg.Logf, - WorkingDir: cfg.Dir, - } -} - -// invokeGo returns the stdout of a go command invocation. -func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, error) { - cfg := state.cfg - - inv := state.cfgInvocation() - - // For Go versions 1.16 and above, `go list` accepts overlays directly via - // the -overlay flag. Set it, if it's available. - // - // The check for "list" is not necessarily required, but we should avoid - // getting the go version if possible. - if verb == "list" { - goVersion, err := state.getGoVersion() - if err != nil { - return nil, err - } - if goVersion >= 16 { - filename, cleanup, err := state.writeOverlays() - if err != nil { - return nil, err - } - defer cleanup() - inv.Overlay = filename - } - } - inv.Verb = verb - inv.Args = args - gocmdRunner := cfg.gocmdRunner - if gocmdRunner == nil { - gocmdRunner = &gocommand.Runner{} - } - stdout, stderr, _, err := gocmdRunner.RunRaw(cfg.Context, inv) - if err != nil { - // Check for 'go' executable not being found. - if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound { - return nil, fmt.Errorf("'go list' driver requires 'go', but %s", exec.ErrNotFound) - } - - exitErr, ok := err.(*exec.ExitError) - if !ok { - // Catastrophic error: - // - context cancellation - return nil, xerrors.Errorf("couldn't run 'go': %w", err) - } - - // Old go version? - if strings.Contains(stderr.String(), "flag provided but not defined") { - return nil, goTooOldError{fmt.Errorf("unsupported version of go: %s: %s", exitErr, stderr)} - } - - // Related to #24854 - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "unexpected directory layout") { - return nil, fmt.Errorf("%s", stderr.String()) - } - - // Is there an error running the C compiler in cgo? This will be reported in the "Error" field - // and should be suppressed by go list -e. - // - // This condition is not perfect yet because the error message can include other error messages than runtime/cgo. - isPkgPathRune := func(r rune) bool { - // From https://golang.org/ref/spec#Import_declarations: - // Implementation restriction: A compiler may restrict ImportPaths to non-empty strings - // using only characters belonging to Unicode's L, M, N, P, and S general categories - // (the Graphic characters without spaces) and may also exclude the - // characters !"#$%&'()*,:;<=>?[\]^`{|} and the Unicode replacement character U+FFFD. - return unicode.IsOneOf([]*unicode.RangeTable{unicode.L, unicode.M, unicode.N, unicode.P, unicode.S}, r) && - !strings.ContainsRune("!\"#$%&'()*,:;<=>?[\\]^`{|}\uFFFD", r) - } - // golang/go#36770: Handle case where cmd/go prints module download messages before the error. - msg := stderr.String() - for strings.HasPrefix(msg, "go: downloading") { - msg = msg[strings.IndexRune(msg, '\n')+1:] - } - if len(stderr.String()) > 0 && strings.HasPrefix(stderr.String(), "# ") { - msg := msg[len("# "):] - if strings.HasPrefix(strings.TrimLeftFunc(msg, isPkgPathRune), "\n") { - return stdout, nil - } - // Treat pkg-config errors as a special case (golang.org/issue/36770). - if strings.HasPrefix(msg, "pkg-config") { - return stdout, nil - } - } - - // This error only appears in stderr. See golang.org/cl/166398 for a fix in go list to show - // the error in the Err section of stdout in case -e option is provided. - // This fix is provided for backwards compatibility. - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "named files must be .go files") { - output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`, - strings.Trim(stderr.String(), "\n")) - return bytes.NewBufferString(output), nil - } - - // Similar to the previous error, but currently lacks a fix in Go. - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "named files must all be in one directory") { - output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`, - strings.Trim(stderr.String(), "\n")) - return bytes.NewBufferString(output), nil - } - - // Backwards compatibility for Go 1.11 because 1.12 and 1.13 put the directory in the ImportPath. - // If the package doesn't exist, put the absolute path of the directory into the error message, - // as Go 1.13 list does. - const noSuchDirectory = "no such directory" - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), noSuchDirectory) { - errstr := stderr.String() - abspath := strings.TrimSpace(errstr[strings.Index(errstr, noSuchDirectory)+len(noSuchDirectory):]) - output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`, - abspath, strings.Trim(stderr.String(), "\n")) - return bytes.NewBufferString(output), nil - } - - // Workaround for #29280: go list -e has incorrect behavior when an ad-hoc package doesn't exist. - // Note that the error message we look for in this case is different that the one looked for above. - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no such file or directory") { - output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`, - strings.Trim(stderr.String(), "\n")) - return bytes.NewBufferString(output), nil - } - - // Workaround for #34273. go list -e with GO111MODULE=on has incorrect behavior when listing a - // directory outside any module. - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "outside available modules") { - output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`, - // TODO(matloob): command-line-arguments isn't correct here. - "command-line-arguments", strings.Trim(stderr.String(), "\n")) - return bytes.NewBufferString(output), nil - } - - // Another variation of the previous error - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "outside module root") { - output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`, - // TODO(matloob): command-line-arguments isn't correct here. - "command-line-arguments", strings.Trim(stderr.String(), "\n")) - return bytes.NewBufferString(output), nil - } - - // Workaround for an instance of golang.org/issue/26755: go list -e will return a non-zero exit - // status if there's a dependency on a package that doesn't exist. But it should return - // a zero exit status and set an error on that package. - if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no Go files in") { - // Don't clobber stdout if `go list` actually returned something. - if len(stdout.String()) > 0 { - return stdout, nil - } - // try to extract package name from string - stderrStr := stderr.String() - var importPath string - colon := strings.Index(stderrStr, ":") - if colon > 0 && strings.HasPrefix(stderrStr, "go build ") { - importPath = stderrStr[len("go build "):colon] - } - output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`, - importPath, strings.Trim(stderrStr, "\n")) - return bytes.NewBufferString(output), nil - } - - // Export mode entails a build. - // If that build fails, errors appear on stderr - // (despite the -e flag) and the Export field is blank. - // Do not fail in that case. - // The same is true if an ad-hoc package given to go list doesn't exist. - // TODO(matloob): Remove these once we can depend on go list to exit with a zero status with -e even when - // packages don't exist or a build fails. - if !usesExportData(cfg) && !containsGoFile(args) { - return nil, fmt.Errorf("go %v: %s: %s", args, exitErr, stderr) - } - } - return stdout, nil -} - -// OverlayJSON is the format overlay files are expected to be in. -// The Replace map maps from overlaid paths to replacement paths: -// the Go command will forward all reads trying to open -// each overlaid path to its replacement path, or consider the overlaid -// path not to exist if the replacement path is empty. -// -// From golang/go#39958. -type OverlayJSON struct { - Replace map[string]string `json:"replace,omitempty"` -} - -// writeOverlays writes out files for go list's -overlay flag, as described -// above. -func (state *golistState) writeOverlays() (filename string, cleanup func(), err error) { - // Do nothing if there are no overlays in the config. - if len(state.cfg.Overlay) == 0 { - return "", func() {}, nil - } - dir, err := ioutil.TempDir("", "gopackages-*") - if err != nil { - return "", nil, err - } - // The caller must clean up this directory, unless this function returns an - // error. - cleanup = func() { - os.RemoveAll(dir) - } - defer func() { - if err != nil { - cleanup() - } - }() - overlays := map[string]string{} - for k, v := range state.cfg.Overlay { - // Create a unique filename for the overlaid files, to avoid - // creating nested directories. - noSeparator := strings.Join(strings.Split(filepath.ToSlash(k), "/"), "") - f, err := ioutil.TempFile(dir, fmt.Sprintf("*-%s", noSeparator)) - if err != nil { - return "", func() {}, err - } - if _, err := f.Write(v); err != nil { - return "", func() {}, err - } - if err := f.Close(); err != nil { - return "", func() {}, err - } - overlays[k] = f.Name() - } - b, err := json.Marshal(OverlayJSON{Replace: overlays}) - if err != nil { - return "", func() {}, err - } - // Write out the overlay file that contains the filepath mappings. - filename = filepath.Join(dir, "overlay.json") - if err := ioutil.WriteFile(filename, b, 0665); err != nil { - return "", func() {}, err - } - return filename, cleanup, nil -} - -func containsGoFile(s []string) bool { - for _, f := range s { - if strings.HasSuffix(f, ".go") { - return true - } - } - return false -} - -func cmdDebugStr(cmd *exec.Cmd) string { - env := make(map[string]string) - for _, kv := range cmd.Env { - split := strings.SplitN(kv, "=", 2) - k, v := split[0], split[1] - env[k] = v - } - - var args []string - for _, arg := range cmd.Args { - quoted := strconv.Quote(arg) - if quoted[1:len(quoted)-1] != arg || strings.Contains(arg, " ") { - args = append(args, quoted) - } else { - args = append(args, arg) - } - } - return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " ")) -} diff --git a/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/vendor/golang.org/x/tools/go/packages/golist_overlay.go deleted file mode 100644 index 9576b472f9..0000000000 --- a/vendor/golang.org/x/tools/go/packages/golist_overlay.go +++ /dev/null @@ -1,575 +0,0 @@ -// 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 packages - -import ( - "encoding/json" - "fmt" - "go/parser" - "go/token" - "os" - "path/filepath" - "regexp" - "sort" - "strconv" - "strings" - - "golang.org/x/tools/internal/gocommand" -) - -// processGolistOverlay provides rudimentary support for adding -// files that don't exist on disk to an overlay. The results can be -// sometimes incorrect. -// TODO(matloob): Handle unsupported cases, including the following: -// - determining the correct package to add given a new import path -func (state *golistState) processGolistOverlay(response *responseDeduper) (modifiedPkgs, needPkgs []string, err error) { - havePkgs := make(map[string]string) // importPath -> non-test package ID - needPkgsSet := make(map[string]bool) - modifiedPkgsSet := make(map[string]bool) - - pkgOfDir := make(map[string][]*Package) - for _, pkg := range response.dr.Packages { - // This is an approximation of import path to id. This can be - // wrong for tests, vendored packages, and a number of other cases. - havePkgs[pkg.PkgPath] = pkg.ID - dir, err := commonDir(pkg.GoFiles) - if err != nil { - return nil, nil, err - } - if dir != "" { - pkgOfDir[dir] = append(pkgOfDir[dir], pkg) - } - } - - // If no new imports are added, it is safe to avoid loading any needPkgs. - // Otherwise, it's hard to tell which package is actually being loaded - // (due to vendoring) and whether any modified package will show up - // in the transitive set of dependencies (because new imports are added, - // potentially modifying the transitive set of dependencies). - var overlayAddsImports bool - - // If both a package and its test package are created by the overlay, we - // need the real package first. Process all non-test files before test - // files, and make the whole process deterministic while we're at it. - var overlayFiles []string - for opath := range state.cfg.Overlay { - overlayFiles = append(overlayFiles, opath) - } - sort.Slice(overlayFiles, func(i, j int) bool { - iTest := strings.HasSuffix(overlayFiles[i], "_test.go") - jTest := strings.HasSuffix(overlayFiles[j], "_test.go") - if iTest != jTest { - return !iTest // non-tests are before tests. - } - return overlayFiles[i] < overlayFiles[j] - }) - for _, opath := range overlayFiles { - contents := state.cfg.Overlay[opath] - base := filepath.Base(opath) - dir := filepath.Dir(opath) - var pkg *Package // if opath belongs to both a package and its test variant, this will be the test variant - var testVariantOf *Package // if opath is a test file, this is the package it is testing - var fileExists bool - isTestFile := strings.HasSuffix(opath, "_test.go") - pkgName, ok := extractPackageName(opath, contents) - if !ok { - // Don't bother adding a file that doesn't even have a parsable package statement - // to the overlay. - continue - } - // If all the overlay files belong to a different package, change the - // package name to that package. - maybeFixPackageName(pkgName, isTestFile, pkgOfDir[dir]) - nextPackage: - for _, p := range response.dr.Packages { - if pkgName != p.Name && p.ID != "command-line-arguments" { - continue - } - for _, f := range p.GoFiles { - if !sameFile(filepath.Dir(f), dir) { - continue - } - // Make sure to capture information on the package's test variant, if needed. - if isTestFile && !hasTestFiles(p) { - // TODO(matloob): Are there packages other than the 'production' variant - // of a package that this can match? This shouldn't match the test main package - // because the file is generated in another directory. - testVariantOf = p - continue nextPackage - } else if !isTestFile && hasTestFiles(p) { - // We're examining a test variant, but the overlaid file is - // a non-test file. Because the overlay implementation - // (currently) only adds a file to one package, skip this - // package, so that we can add the file to the production - // variant of the package. (https://golang.org/issue/36857 - // tracks handling overlays on both the production and test - // variant of a package). - continue nextPackage - } - if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath { - // We have already seen the production version of the - // for which p is a test variant. - if hasTestFiles(p) { - testVariantOf = pkg - } - } - pkg = p - if filepath.Base(f) == base { - fileExists = true - } - } - } - // The overlay could have included an entirely new package or an - // ad-hoc package. An ad-hoc package is one that we have manually - // constructed from inadequate `go list` results for a file= query. - // It will have the ID command-line-arguments. - if pkg == nil || pkg.ID == "command-line-arguments" { - // Try to find the module or gopath dir the file is contained in. - // Then for modules, add the module opath to the beginning. - pkgPath, ok, err := state.getPkgPath(dir) - if err != nil { - return nil, nil, err - } - if !ok { - break - } - var forTest string // only set for x tests - isXTest := strings.HasSuffix(pkgName, "_test") - if isXTest { - forTest = pkgPath - pkgPath += "_test" - } - id := pkgPath - if isTestFile { - if isXTest { - id = fmt.Sprintf("%s [%s.test]", pkgPath, forTest) - } else { - id = fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath) - } - } - if pkg != nil { - // TODO(rstambler): We should change the package's path and ID - // here. The only issue is that this messes with the roots. - } else { - // Try to reclaim a package with the same ID, if it exists in the response. - for _, p := range response.dr.Packages { - if reclaimPackage(p, id, opath, contents) { - pkg = p - break - } - } - // Otherwise, create a new package. - if pkg == nil { - pkg = &Package{ - PkgPath: pkgPath, - ID: id, - Name: pkgName, - Imports: make(map[string]*Package), - } - response.addPackage(pkg) - havePkgs[pkg.PkgPath] = id - // Add the production package's sources for a test variant. - if isTestFile && !isXTest && testVariantOf != nil { - pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...) - pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...) - // Add the package under test and its imports to the test variant. - pkg.forTest = testVariantOf.PkgPath - for k, v := range testVariantOf.Imports { - pkg.Imports[k] = &Package{ID: v.ID} - } - } - if isXTest { - pkg.forTest = forTest - } - } - } - } - if !fileExists { - pkg.GoFiles = append(pkg.GoFiles, opath) - // TODO(matloob): Adding the file to CompiledGoFiles can exhibit the wrong behavior - // if the file will be ignored due to its build tags. - pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, opath) - modifiedPkgsSet[pkg.ID] = true - } - imports, err := extractImports(opath, contents) - if err != nil { - // Let the parser or type checker report errors later. - continue - } - for _, imp := range imports { - // TODO(rstambler): If the package is an x test and the import has - // a test variant, make sure to replace it. - if _, found := pkg.Imports[imp]; found { - continue - } - overlayAddsImports = true - id, ok := havePkgs[imp] - if !ok { - var err error - id, err = state.resolveImport(dir, imp) - if err != nil { - return nil, nil, err - } - } - pkg.Imports[imp] = &Package{ID: id} - // Add dependencies to the non-test variant version of this package as well. - if testVariantOf != nil { - testVariantOf.Imports[imp] = &Package{ID: id} - } - } - } - - // toPkgPath guesses the package path given the id. - toPkgPath := func(sourceDir, id string) (string, error) { - if i := strings.IndexByte(id, ' '); i >= 0 { - return state.resolveImport(sourceDir, id[:i]) - } - return state.resolveImport(sourceDir, id) - } - - // Now that new packages have been created, do another pass to determine - // the new set of missing packages. - for _, pkg := range response.dr.Packages { - for _, imp := range pkg.Imports { - if len(pkg.GoFiles) == 0 { - return nil, nil, fmt.Errorf("cannot resolve imports for package %q with no Go files", pkg.PkgPath) - } - pkgPath, err := toPkgPath(filepath.Dir(pkg.GoFiles[0]), imp.ID) - if err != nil { - return nil, nil, err - } - if _, ok := havePkgs[pkgPath]; !ok { - needPkgsSet[pkgPath] = true - } - } - } - - if overlayAddsImports { - needPkgs = make([]string, 0, len(needPkgsSet)) - for pkg := range needPkgsSet { - needPkgs = append(needPkgs, pkg) - } - } - modifiedPkgs = make([]string, 0, len(modifiedPkgsSet)) - for pkg := range modifiedPkgsSet { - modifiedPkgs = append(modifiedPkgs, pkg) - } - return modifiedPkgs, needPkgs, err -} - -// resolveImport finds the ID of a package given its import path. -// In particular, it will find the right vendored copy when in GOPATH mode. -func (state *golistState) resolveImport(sourceDir, importPath string) (string, error) { - env, err := state.getEnv() - if err != nil { - return "", err - } - if env["GOMOD"] != "" { - return importPath, nil - } - - searchDir := sourceDir - for { - vendorDir := filepath.Join(searchDir, "vendor") - exists, ok := state.vendorDirs[vendorDir] - if !ok { - info, err := os.Stat(vendorDir) - exists = err == nil && info.IsDir() - state.vendorDirs[vendorDir] = exists - } - - if exists { - vendoredPath := filepath.Join(vendorDir, importPath) - if info, err := os.Stat(vendoredPath); err == nil && info.IsDir() { - // We should probably check for .go files here, but shame on anyone who fools us. - path, ok, err := state.getPkgPath(vendoredPath) - if err != nil { - return "", err - } - if ok { - return path, nil - } - } - } - - // We know we've hit the top of the filesystem when we Dir / and get /, - // or C:\ and get C:\, etc. - next := filepath.Dir(searchDir) - if next == searchDir { - break - } - searchDir = next - } - return importPath, nil -} - -func hasTestFiles(p *Package) bool { - for _, f := range p.GoFiles { - if strings.HasSuffix(f, "_test.go") { - return true - } - } - return false -} - -// determineRootDirs returns a mapping from absolute directories that could -// contain code to their corresponding import path prefixes. -func (state *golistState) determineRootDirs() (map[string]string, error) { - env, err := state.getEnv() - if err != nil { - return nil, err - } - if env["GOMOD"] != "" { - state.rootsOnce.Do(func() { - state.rootDirs, state.rootDirsError = state.determineRootDirsModules() - }) - } else { - state.rootsOnce.Do(func() { - state.rootDirs, state.rootDirsError = state.determineRootDirsGOPATH() - }) - } - return state.rootDirs, state.rootDirsError -} - -func (state *golistState) determineRootDirsModules() (map[string]string, error) { - // List all of the modules--the first will be the directory for the main - // module. Any replaced modules will also need to be treated as roots. - // Editing files in the module cache isn't a great idea, so we don't - // plan to ever support that. - out, err := state.invokeGo("list", "-m", "-json", "all") - if err != nil { - // 'go list all' will fail if we're outside of a module and - // GO111MODULE=on. Try falling back without 'all'. - var innerErr error - out, innerErr = state.invokeGo("list", "-m", "-json") - if innerErr != nil { - return nil, err - } - } - roots := map[string]string{} - modules := map[string]string{} - var i int - for dec := json.NewDecoder(out); dec.More(); { - mod := new(gocommand.ModuleJSON) - if err := dec.Decode(mod); err != nil { - return nil, err - } - if mod.Dir != "" && mod.Path != "" { - // This is a valid module; add it to the map. - absDir, err := filepath.Abs(mod.Dir) - if err != nil { - return nil, err - } - modules[absDir] = mod.Path - // The first result is the main module. - if i == 0 || mod.Replace != nil && mod.Replace.Path != "" { - roots[absDir] = mod.Path - } - } - i++ - } - return roots, nil -} - -func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) { - m := map[string]string{} - for _, dir := range filepath.SplitList(state.mustGetEnv()["GOPATH"]) { - absDir, err := filepath.Abs(dir) - if err != nil { - return nil, err - } - m[filepath.Join(absDir, "src")] = "" - } - return m, nil -} - -func extractImports(filename string, contents []byte) ([]string, error) { - f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.ImportsOnly) // TODO(matloob): reuse fileset? - if err != nil { - return nil, err - } - var res []string - for _, imp := range f.Imports { - quotedPath := imp.Path.Value - path, err := strconv.Unquote(quotedPath) - if err != nil { - return nil, err - } - res = append(res, path) - } - return res, nil -} - -// reclaimPackage attempts to reuse a package that failed to load in an overlay. -// -// If the package has errors and has no Name, GoFiles, or Imports, -// then it's possible that it doesn't yet exist on disk. -func reclaimPackage(pkg *Package, id string, filename string, contents []byte) bool { - // TODO(rstambler): Check the message of the actual error? - // It differs between $GOPATH and module mode. - if pkg.ID != id { - return false - } - if len(pkg.Errors) != 1 { - return false - } - if pkg.Name != "" || pkg.ExportFile != "" { - return false - } - if len(pkg.GoFiles) > 0 || len(pkg.CompiledGoFiles) > 0 || len(pkg.OtherFiles) > 0 { - return false - } - if len(pkg.Imports) > 0 { - return false - } - pkgName, ok := extractPackageName(filename, contents) - if !ok { - return false - } - pkg.Name = pkgName - pkg.Errors = nil - return true -} - -func extractPackageName(filename string, contents []byte) (string, bool) { - // TODO(rstambler): Check the message of the actual error? - // It differs between $GOPATH and module mode. - f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.PackageClauseOnly) // TODO(matloob): reuse fileset? - if err != nil { - return "", false - } - return f.Name.Name, true -} - -// commonDir returns the directory that all files are in, "" if files is empty, -// or an error if they aren't in the same directory. -func commonDir(files []string) (string, error) { - seen := make(map[string]bool) - for _, f := range files { - seen[filepath.Dir(f)] = true - } - if len(seen) > 1 { - return "", fmt.Errorf("files (%v) are in more than one directory: %v", files, seen) - } - for k := range seen { - // seen has only one element; return it. - return k, nil - } - return "", nil // no files -} - -// It is possible that the files in the disk directory dir have a different package -// name from newName, which is deduced from the overlays. If they all have a different -// package name, and they all have the same package name, then that name becomes -// the package name. -// It returns true if it changes the package name, false otherwise. -func maybeFixPackageName(newName string, isTestFile bool, pkgsOfDir []*Package) { - names := make(map[string]int) - for _, p := range pkgsOfDir { - names[p.Name]++ - } - if len(names) != 1 { - // some files are in different packages - return - } - var oldName string - for k := range names { - oldName = k - } - if newName == oldName { - return - } - // We might have a case where all of the package names in the directory are - // the same, but the overlay file is for an x test, which belongs to its - // own package. If the x test does not yet exist on disk, we may not yet - // have its package name on disk, but we should not rename the packages. - // - // We use a heuristic to determine if this file belongs to an x test: - // The test file should have a package name whose package name has a _test - // suffix or looks like "newName_test". - maybeXTest := strings.HasPrefix(oldName+"_test", newName) || strings.HasSuffix(newName, "_test") - if isTestFile && maybeXTest { - return - } - for _, p := range pkgsOfDir { - p.Name = newName - } -} - -// This function is copy-pasted from -// https://github.com/golang/go/blob/9706f510a5e2754595d716bd64be8375997311fb/src/cmd/go/internal/search/search.go#L360. -// It should be deleted when we remove support for overlays from go/packages. -// -// NOTE: This does not handle any ./... or ./ style queries, as this function -// doesn't know the working directory. -// -// matchPattern(pattern)(name) reports whether -// name matches pattern. Pattern is a limited glob -// pattern in which '...' means 'any string' and there -// is no other special syntax. -// Unfortunately, there are two special cases. Quoting "go help packages": -// -// First, /... at the end of the pattern can match an empty string, -// so that net/... matches both net and packages in its subdirectories, like net/http. -// Second, any slash-separated pattern element containing a wildcard never -// participates in a match of the "vendor" element in the path of a vendored -// package, so that ./... does not match packages in subdirectories of -// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. -// Note, however, that a directory named vendor that itself contains code -// is not a vendored package: cmd/vendor would be a command named vendor, -// and the pattern cmd/... matches it. -func matchPattern(pattern string) func(name string) bool { - // Convert pattern to regular expression. - // The strategy for the trailing /... is to nest it in an explicit ? expression. - // The strategy for the vendor exclusion is to change the unmatchable - // vendor strings to a disallowed code point (vendorChar) and to use - // "(anything but that codepoint)*" as the implementation of the ... wildcard. - // This is a bit complicated but the obvious alternative, - // namely a hand-written search like in most shell glob matchers, - // is too easy to make accidentally exponential. - // Using package regexp guarantees linear-time matching. - - const vendorChar = "\x00" - - if strings.Contains(pattern, vendorChar) { - return func(name string) bool { return false } - } - - re := regexp.QuoteMeta(pattern) - re = replaceVendor(re, vendorChar) - switch { - case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): - re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` - case re == vendorChar+`/\.\.\.`: - re = `(/vendor|/` + vendorChar + `/\.\.\.)` - case strings.HasSuffix(re, `/\.\.\.`): - re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` - } - re = strings.ReplaceAll(re, `\.\.\.`, `[^`+vendorChar+`]*`) - - reg := regexp.MustCompile(`^` + re + `$`) - - return func(name string) bool { - if strings.Contains(name, vendorChar) { - return false - } - return reg.MatchString(replaceVendor(name, vendorChar)) - } -} - -// replaceVendor returns the result of replacing -// non-trailing vendor path elements in x with repl. -func replaceVendor(x, repl string) string { - if !strings.Contains(x, "vendor") { - return x - } - elem := strings.Split(x, "/") - for i := 0; i < len(elem)-1; i++ { - if elem[i] == "vendor" { - elem[i] = repl - } - } - return strings.Join(elem, "/") -} diff --git a/vendor/golang.org/x/tools/go/packages/loadmode_string.go b/vendor/golang.org/x/tools/go/packages/loadmode_string.go deleted file mode 100644 index 7ea37e7eea..0000000000 --- a/vendor/golang.org/x/tools/go/packages/loadmode_string.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2019 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 packages - -import ( - "fmt" - "strings" -) - -var allModes = []LoadMode{ - NeedName, - NeedFiles, - NeedCompiledGoFiles, - NeedImports, - NeedDeps, - NeedExportsFile, - NeedTypes, - NeedSyntax, - NeedTypesInfo, - NeedTypesSizes, -} - -var modeStrings = []string{ - "NeedName", - "NeedFiles", - "NeedCompiledGoFiles", - "NeedImports", - "NeedDeps", - "NeedExportsFile", - "NeedTypes", - "NeedSyntax", - "NeedTypesInfo", - "NeedTypesSizes", -} - -func (mod LoadMode) String() string { - m := mod - if m == 0 { - return "LoadMode(0)" - } - var out []string - for i, x := range allModes { - if x > m { - break - } - if (m & x) != 0 { - out = append(out, modeStrings[i]) - m = m ^ x - } - } - if m != 0 { - out = append(out, "Unknown") - } - return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|")) -} diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go deleted file mode 100644 index 38475e8712..0000000000 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ /dev/null @@ -1,1233 +0,0 @@ -// 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 packages - -// See doc.go for package documentation and implementation notes. - -import ( - "context" - "encoding/json" - "fmt" - "go/ast" - "go/parser" - "go/scanner" - "go/token" - "go/types" - "io/ioutil" - "log" - "os" - "path/filepath" - "strings" - "sync" - "time" - - "golang.org/x/tools/go/gcexportdata" - "golang.org/x/tools/internal/gocommand" - "golang.org/x/tools/internal/packagesinternal" - "golang.org/x/tools/internal/typesinternal" -) - -// A LoadMode controls the amount of detail to return when loading. -// The bits below can be combined to specify which fields should be -// filled in the result packages. -// The zero value is a special case, equivalent to combining -// the NeedName, NeedFiles, and NeedCompiledGoFiles bits. -// ID and Errors (if present) will always be filled. -// Load may return more information than requested. -type LoadMode int - -// TODO(matloob): When a V2 of go/packages is released, rename NeedExportsFile to -// NeedExportFile to make it consistent with the Package field it's adding. - -const ( - // NeedName adds Name and PkgPath. - NeedName LoadMode = 1 << iota - - // NeedFiles adds GoFiles and OtherFiles. - NeedFiles - - // NeedCompiledGoFiles adds CompiledGoFiles. - NeedCompiledGoFiles - - // NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain - // "placeholder" Packages with only the ID set. - NeedImports - - // NeedDeps adds the fields requested by the LoadMode in the packages in Imports. - NeedDeps - - // NeedExportsFile adds ExportFile. - NeedExportsFile - - // NeedTypes adds Types, Fset, and IllTyped. - NeedTypes - - // NeedSyntax adds Syntax. - NeedSyntax - - // NeedTypesInfo adds TypesInfo. - NeedTypesInfo - - // NeedTypesSizes adds TypesSizes. - NeedTypesSizes - - // typecheckCgo enables full support for type checking cgo. Requires Go 1.15+. - // Modifies CompiledGoFiles and Types, and has no effect on its own. - typecheckCgo - - // NeedModule adds Module. - NeedModule -) - -const ( - // Deprecated: LoadFiles exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. - LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles - - // Deprecated: LoadImports exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. - LoadImports = LoadFiles | NeedImports - - // Deprecated: LoadTypes exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. - LoadTypes = LoadImports | NeedTypes | NeedTypesSizes - - // Deprecated: LoadSyntax exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. - LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo - - // Deprecated: LoadAllSyntax exists for historical compatibility - // and should not be used. Please directly specify the needed fields using the Need values. - LoadAllSyntax = LoadSyntax | NeedDeps -) - -// A Config specifies details about how packages should be loaded. -// The zero value is a valid configuration. -// Calls to Load do not modify this struct. -type Config struct { - // Mode controls the level of information returned for each package. - Mode LoadMode - - // Context specifies the context for the load operation. - // If the context is cancelled, the loader may stop early - // and return an ErrCancelled error. - // If Context is nil, the load cannot be cancelled. - Context context.Context - - // Logf is the logger for the config. - // If the user provides a logger, debug logging is enabled. - // If the GOPACKAGESDEBUG environment variable is set to true, - // but the logger is nil, default to log.Printf. - Logf func(format string, args ...interface{}) - - // Dir is the directory in which to run the build system's query tool - // that provides information about the packages. - // If Dir is empty, the tool is run in the current directory. - Dir string - - // Env is the environment to use when invoking the build system's query tool. - // If Env is nil, the current environment is used. - // As in os/exec's Cmd, only the last value in the slice for - // each environment key is used. To specify the setting of only - // a few variables, append to the current environment, as in: - // - // opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386") - // - Env []string - - // gocmdRunner guards go command calls from concurrency errors. - gocmdRunner *gocommand.Runner - - // BuildFlags is a list of command-line flags to be passed through to - // the build system's query tool. - BuildFlags []string - - // modFile will be used for -modfile in go command invocations. - modFile string - - // modFlag will be used for -modfile in go command invocations. - modFlag string - - // Fset provides source position information for syntax trees and types. - // If Fset is nil, Load will use a new fileset, but preserve Fset's value. - Fset *token.FileSet - - // ParseFile is called to read and parse each file - // when preparing a package's type-checked syntax tree. - // It must be safe to call ParseFile simultaneously from multiple goroutines. - // If ParseFile is nil, the loader will uses parser.ParseFile. - // - // ParseFile should parse the source from src and use filename only for - // recording position information. - // - // An application may supply a custom implementation of ParseFile - // to change the effective file contents or the behavior of the parser, - // or to modify the syntax tree. For example, selectively eliminating - // unwanted function bodies can significantly accelerate type checking. - ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) - - // If Tests is set, the loader includes not just the packages - // matching a particular pattern but also any related test packages, - // including test-only variants of the package and the test executable. - // - // For example, when using the go command, loading "fmt" with Tests=true - // returns four packages, with IDs "fmt" (the standard package), - // "fmt [fmt.test]" (the package as compiled for the test), - // "fmt_test" (the test functions from source files in package fmt_test), - // and "fmt.test" (the test binary). - // - // In build systems with explicit names for tests, - // setting Tests may have no effect. - Tests bool - - // Overlay provides a mapping of absolute file paths to file contents. - // If the file with the given path already exists, the parser will use the - // alternative file contents provided by the map. - // - // Overlays provide incomplete support for when a given file doesn't - // already exist on disk. See the package doc above for more details. - Overlay map[string][]byte -} - -// driver is the type for functions that query the build system for the -// packages named by the patterns. -type driver func(cfg *Config, patterns ...string) (*driverResponse, error) - -// driverResponse contains the results for a driver query. -type driverResponse struct { - // NotHandled is returned if the request can't be handled by the current - // driver. If an external driver returns a response with NotHandled, the - // rest of the driverResponse is ignored, and go/packages will fallback - // to the next driver. If go/packages is extended in the future to support - // lists of multiple drivers, go/packages will fall back to the next driver. - NotHandled bool - - // Sizes, if not nil, is the types.Sizes to use when type checking. - Sizes *types.StdSizes - - // Roots is the set of package IDs that make up the root packages. - // We have to encode this separately because when we encode a single package - // we cannot know if it is one of the roots as that requires knowledge of the - // graph it is part of. - Roots []string `json:",omitempty"` - - // Packages is the full set of packages in the graph. - // The packages are not connected into a graph. - // The Imports if populated will be stubs that only have their ID set. - // Imports will be connected and then type and syntax information added in a - // later pass (see refine). - Packages []*Package -} - -// Load loads and returns the Go packages named by the given patterns. -// -// Config specifies loading options; -// nil behaves the same as an empty Config. -// -// Load returns an error if any of the patterns was invalid -// as defined by the underlying build system. -// It may return an empty list of packages without an error, -// for instance for an empty expansion of a valid wildcard. -// Errors associated with a particular package are recorded in the -// corresponding Package's Errors list, and do not cause Load to -// return an error. Clients may need to handle such errors before -// proceeding with further analysis. The PrintErrors function is -// provided for convenient display of all errors. -func Load(cfg *Config, patterns ...string) ([]*Package, error) { - l := newLoader(cfg) - response, err := defaultDriver(&l.Config, patterns...) - if err != nil { - return nil, err - } - l.sizes = response.Sizes - return l.refine(response.Roots, response.Packages...) -} - -// defaultDriver is a driver that implements go/packages' fallback behavior. -// It will try to request to an external driver, if one exists. If there's -// no external driver, or the driver returns a response with NotHandled set, -// defaultDriver will fall back to the go list driver. -func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) { - driver := findExternalDriver(cfg) - if driver == nil { - driver = goListDriver - } - response, err := driver(cfg, patterns...) - if err != nil { - return response, err - } else if response.NotHandled { - return goListDriver(cfg, patterns...) - } - return response, nil -} - -// A Package describes a loaded Go package. -type Package struct { - // ID is a unique identifier for a package, - // in a syntax provided by the underlying build system. - // - // Because the syntax varies based on the build system, - // clients should treat IDs as opaque and not attempt to - // interpret them. - ID string - - // Name is the package name as it appears in the package source code. - Name string - - // PkgPath is the package path as used by the go/types package. - PkgPath string - - // Errors contains any errors encountered querying the metadata - // of the package, or while parsing or type-checking its files. - Errors []Error - - // GoFiles lists the absolute file paths of the package's Go source files. - GoFiles []string - - // CompiledGoFiles lists the absolute file paths of the package's source - // files that are suitable for type checking. - // This may differ from GoFiles if files are processed before compilation. - CompiledGoFiles []string - - // OtherFiles lists the absolute file paths of the package's non-Go source files, - // including assembly, C, C++, Fortran, Objective-C, SWIG, and so on. - OtherFiles []string - - // IgnoredFiles lists source files that are not part of the package - // using the current build configuration but that might be part of - // the package using other build configurations. - IgnoredFiles []string - - // ExportFile is the absolute path to a file containing type - // information for the package as provided by the build system. - ExportFile string - - // Imports maps import paths appearing in the package's Go source files - // to corresponding loaded Packages. - Imports map[string]*Package - - // Types provides type information for the package. - // The NeedTypes LoadMode bit sets this field for packages matching the - // patterns; type information for dependencies may be missing or incomplete, - // unless NeedDeps and NeedImports are also set. - Types *types.Package - - // Fset provides position information for Types, TypesInfo, and Syntax. - // It is set only when Types is set. - Fset *token.FileSet - - // IllTyped indicates whether the package or any dependency contains errors. - // It is set only when Types is set. - IllTyped bool - - // Syntax is the package's syntax trees, for the files listed in CompiledGoFiles. - // - // The NeedSyntax LoadMode bit populates this field for packages matching the patterns. - // If NeedDeps and NeedImports are also set, this field will also be populated - // for dependencies. - Syntax []*ast.File - - // TypesInfo provides type information about the package's syntax trees. - // It is set only when Syntax is set. - TypesInfo *types.Info - - // TypesSizes provides the effective size function for types in TypesInfo. - TypesSizes types.Sizes - - // forTest is the package under test, if any. - forTest string - - // module is the module information for the package if it exists. - Module *Module -} - -// Module provides module information for a package. -type Module struct { - Path string // module path - Version string // module version - Replace *Module // replaced by this module - Time *time.Time // time version was created - Main bool // is this the main module? - Indirect bool // is this module only an indirect dependency of main module? - Dir string // directory holding files for this module, if any - GoMod string // path to go.mod file used when loading this module, if any - GoVersion string // go version used in module - Error *ModuleError // error loading module -} - -// ModuleError holds errors loading a module. -type ModuleError struct { - Err string // the error itself -} - -func init() { - packagesinternal.GetForTest = func(p interface{}) string { - return p.(*Package).forTest - } - packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner { - return config.(*Config).gocmdRunner - } - packagesinternal.SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) { - config.(*Config).gocmdRunner = runner - } - packagesinternal.SetModFile = func(config interface{}, value string) { - config.(*Config).modFile = value - } - packagesinternal.SetModFlag = func(config interface{}, value string) { - config.(*Config).modFlag = value - } - packagesinternal.TypecheckCgo = int(typecheckCgo) -} - -// An Error describes a problem with a package's metadata, syntax, or types. -type Error struct { - Pos string // "file:line:col" or "file:line" or "" or "-" - Msg string - Kind ErrorKind -} - -// ErrorKind describes the source of the error, allowing the user to -// differentiate between errors generated by the driver, the parser, or the -// type-checker. -type ErrorKind int - -const ( - UnknownError ErrorKind = iota - ListError - ParseError - TypeError -) - -func (err Error) Error() string { - pos := err.Pos - if pos == "" { - pos = "-" // like token.Position{}.String() - } - return pos + ": " + err.Msg -} - -// flatPackage is the JSON form of Package -// It drops all the type and syntax fields, and transforms the Imports -// -// TODO(adonovan): identify this struct with Package, effectively -// publishing the JSON protocol. -type flatPackage struct { - ID string - Name string `json:",omitempty"` - PkgPath string `json:",omitempty"` - Errors []Error `json:",omitempty"` - GoFiles []string `json:",omitempty"` - CompiledGoFiles []string `json:",omitempty"` - OtherFiles []string `json:",omitempty"` - IgnoredFiles []string `json:",omitempty"` - ExportFile string `json:",omitempty"` - Imports map[string]string `json:",omitempty"` -} - -// MarshalJSON returns the Package in its JSON form. -// For the most part, the structure fields are written out unmodified, and -// the type and syntax fields are skipped. -// The imports are written out as just a map of path to package id. -// The errors are written using a custom type that tries to preserve the -// structure of error types we know about. -// -// This method exists to enable support for additional build systems. It is -// not intended for use by clients of the API and we may change the format. -func (p *Package) MarshalJSON() ([]byte, error) { - flat := &flatPackage{ - ID: p.ID, - Name: p.Name, - PkgPath: p.PkgPath, - Errors: p.Errors, - GoFiles: p.GoFiles, - CompiledGoFiles: p.CompiledGoFiles, - OtherFiles: p.OtherFiles, - IgnoredFiles: p.IgnoredFiles, - ExportFile: p.ExportFile, - } - if len(p.Imports) > 0 { - flat.Imports = make(map[string]string, len(p.Imports)) - for path, ipkg := range p.Imports { - flat.Imports[path] = ipkg.ID - } - } - return json.Marshal(flat) -} - -// UnmarshalJSON reads in a Package from its JSON format. -// See MarshalJSON for details about the format accepted. -func (p *Package) UnmarshalJSON(b []byte) error { - flat := &flatPackage{} - if err := json.Unmarshal(b, &flat); err != nil { - return err - } - *p = Package{ - ID: flat.ID, - Name: flat.Name, - PkgPath: flat.PkgPath, - Errors: flat.Errors, - GoFiles: flat.GoFiles, - CompiledGoFiles: flat.CompiledGoFiles, - OtherFiles: flat.OtherFiles, - ExportFile: flat.ExportFile, - } - if len(flat.Imports) > 0 { - p.Imports = make(map[string]*Package, len(flat.Imports)) - for path, id := range flat.Imports { - p.Imports[path] = &Package{ID: id} - } - } - return nil -} - -func (p *Package) String() string { return p.ID } - -// loaderPackage augments Package with state used during the loading phase -type loaderPackage struct { - *Package - importErrors map[string]error // maps each bad import to its error - loadOnce sync.Once - color uint8 // for cycle detection - needsrc bool // load from source (Mode >= LoadTypes) - needtypes bool // type information is either requested or depended on - initial bool // package was matched by a pattern -} - -// loader holds the working state of a single call to load. -type loader struct { - pkgs map[string]*loaderPackage - Config - sizes types.Sizes - parseCache map[string]*parseValue - parseCacheMu sync.Mutex - exportMu sync.Mutex // enforces mutual exclusion of exportdata operations - - // Config.Mode contains the implied mode (see impliedLoadMode). - // Implied mode contains all the fields we need the data for. - // In requestedMode there are the actually requested fields. - // We'll zero them out before returning packages to the user. - // This makes it easier for us to get the conditions where - // we need certain modes right. - requestedMode LoadMode -} - -type parseValue struct { - f *ast.File - err error - ready chan struct{} -} - -func newLoader(cfg *Config) *loader { - ld := &loader{ - parseCache: map[string]*parseValue{}, - } - if cfg != nil { - ld.Config = *cfg - // If the user has provided a logger, use it. - ld.Config.Logf = cfg.Logf - } - if ld.Config.Logf == nil { - // If the GOPACKAGESDEBUG environment variable is set to true, - // but the user has not provided a logger, default to log.Printf. - if debug { - ld.Config.Logf = log.Printf - } else { - ld.Config.Logf = func(format string, args ...interface{}) {} - } - } - if ld.Config.Mode == 0 { - ld.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles // Preserve zero behavior of Mode for backwards compatibility. - } - if ld.Config.Env == nil { - ld.Config.Env = os.Environ() - } - if ld.Config.gocmdRunner == nil { - ld.Config.gocmdRunner = &gocommand.Runner{} - } - if ld.Context == nil { - ld.Context = context.Background() - } - if ld.Dir == "" { - if dir, err := os.Getwd(); err == nil { - ld.Dir = dir - } - } - - // Save the actually requested fields. We'll zero them out before returning packages to the user. - ld.requestedMode = ld.Mode - ld.Mode = impliedLoadMode(ld.Mode) - - if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { - if ld.Fset == nil { - ld.Fset = token.NewFileSet() - } - - // ParseFile is required even in LoadTypes mode - // because we load source if export data is missing. - if ld.ParseFile == nil { - ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) { - const mode = parser.AllErrors | parser.ParseComments - return parser.ParseFile(fset, filename, src, mode) - } - } - } - - return ld -} - -// refine connects the supplied packages into a graph and then adds type and -// and syntax information as requested by the LoadMode. -func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) { - rootMap := make(map[string]int, len(roots)) - for i, root := range roots { - rootMap[root] = i - } - ld.pkgs = make(map[string]*loaderPackage) - // first pass, fixup and build the map and roots - var initial = make([]*loaderPackage, len(roots)) - for _, pkg := range list { - rootIndex := -1 - if i, found := rootMap[pkg.ID]; found { - rootIndex = i - } - - // Overlays can invalidate export data. - // TODO(matloob): make this check fine-grained based on dependencies on overlaid files - exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe" - // This package needs type information if the caller requested types and the package is - // either a root, or it's a non-root and the user requested dependencies ... - needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) - // This package needs source if the call requested source (or types info, which implies source) - // and the package is either a root, or itas a non- root and the user requested dependencies... - needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) || - // ... or if we need types and the exportData is invalid. We fall back to (incompletely) - // typechecking packages from source if they fail to compile. - (ld.Mode&NeedTypes|NeedTypesInfo != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe" - lpkg := &loaderPackage{ - Package: pkg, - needtypes: needtypes, - needsrc: needsrc, - } - ld.pkgs[lpkg.ID] = lpkg - if rootIndex >= 0 { - initial[rootIndex] = lpkg - lpkg.initial = true - } - } - for i, root := range roots { - if initial[i] == nil { - return nil, fmt.Errorf("root package %v is missing", root) - } - } - - // Materialize the import graph. - - const ( - white = 0 // new - grey = 1 // in progress - black = 2 // complete - ) - - // visit traverses the import graph, depth-first, - // and materializes the graph as Packages.Imports. - // - // Valid imports are saved in the Packages.Import map. - // Invalid imports (cycles and missing nodes) are saved in the importErrors map. - // Thus, even in the presence of both kinds of errors, the Import graph remains a DAG. - // - // visit returns whether the package needs src or has a transitive - // dependency on a package that does. These are the only packages - // for which we load source code. - var stack []*loaderPackage - var visit func(lpkg *loaderPackage) bool - var srcPkgs []*loaderPackage - visit = func(lpkg *loaderPackage) bool { - switch lpkg.color { - case black: - return lpkg.needsrc - case grey: - panic("internal error: grey node") - } - lpkg.color = grey - stack = append(stack, lpkg) // push - stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports - // If NeedImports isn't set, the imports fields will all be zeroed out. - if ld.Mode&NeedImports != 0 { - lpkg.Imports = make(map[string]*Package, len(stubs)) - for importPath, ipkg := range stubs { - var importErr error - imp := ld.pkgs[ipkg.ID] - if imp == nil { - // (includes package "C" when DisableCgo) - importErr = fmt.Errorf("missing package: %q", ipkg.ID) - } else if imp.color == grey { - importErr = fmt.Errorf("import cycle: %s", stack) - } - if importErr != nil { - if lpkg.importErrors == nil { - lpkg.importErrors = make(map[string]error) - } - lpkg.importErrors[importPath] = importErr - continue - } - - if visit(imp) { - lpkg.needsrc = true - } - lpkg.Imports[importPath] = imp.Package - } - } - if lpkg.needsrc { - srcPkgs = append(srcPkgs, lpkg) - } - if ld.Mode&NeedTypesSizes != 0 { - lpkg.TypesSizes = ld.sizes - } - stack = stack[:len(stack)-1] // pop - lpkg.color = black - - return lpkg.needsrc - } - - if ld.Mode&NeedImports == 0 { - // We do this to drop the stub import packages that we are not even going to try to resolve. - for _, lpkg := range initial { - lpkg.Imports = nil - } - } else { - // For each initial package, create its import DAG. - for _, lpkg := range initial { - visit(lpkg) - } - } - if ld.Mode&NeedImports != 0 && ld.Mode&NeedTypes != 0 { - for _, lpkg := range srcPkgs { - // Complete type information is required for the - // immediate dependencies of each source package. - for _, ipkg := range lpkg.Imports { - imp := ld.pkgs[ipkg.ID] - imp.needtypes = true - } - } - } - // Load type data and syntax if needed, starting at - // the initial packages (roots of the import DAG). - if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { - var wg sync.WaitGroup - for _, lpkg := range initial { - wg.Add(1) - go func(lpkg *loaderPackage) { - ld.loadRecursive(lpkg) - wg.Done() - }(lpkg) - } - wg.Wait() - } - - result := make([]*Package, len(initial)) - for i, lpkg := range initial { - result[i] = lpkg.Package - } - for i := range ld.pkgs { - // Clear all unrequested fields, - // to catch programs that use more than they request. - if ld.requestedMode&NeedName == 0 { - ld.pkgs[i].Name = "" - ld.pkgs[i].PkgPath = "" - } - if ld.requestedMode&NeedFiles == 0 { - ld.pkgs[i].GoFiles = nil - ld.pkgs[i].OtherFiles = nil - ld.pkgs[i].IgnoredFiles = nil - } - if ld.requestedMode&NeedCompiledGoFiles == 0 { - ld.pkgs[i].CompiledGoFiles = nil - } - if ld.requestedMode&NeedImports == 0 { - ld.pkgs[i].Imports = nil - } - if ld.requestedMode&NeedExportsFile == 0 { - ld.pkgs[i].ExportFile = "" - } - if ld.requestedMode&NeedTypes == 0 { - ld.pkgs[i].Types = nil - ld.pkgs[i].Fset = nil - ld.pkgs[i].IllTyped = false - } - if ld.requestedMode&NeedSyntax == 0 { - ld.pkgs[i].Syntax = nil - } - if ld.requestedMode&NeedTypesInfo == 0 { - ld.pkgs[i].TypesInfo = nil - } - if ld.requestedMode&NeedTypesSizes == 0 { - ld.pkgs[i].TypesSizes = nil - } - if ld.requestedMode&NeedModule == 0 { - ld.pkgs[i].Module = nil - } - } - - return result, nil -} - -// loadRecursive loads the specified package and its dependencies, -// recursively, in parallel, in topological order. -// It is atomic and idempotent. -// Precondition: ld.Mode&NeedTypes. -func (ld *loader) loadRecursive(lpkg *loaderPackage) { - lpkg.loadOnce.Do(func() { - // Load the direct dependencies, in parallel. - var wg sync.WaitGroup - for _, ipkg := range lpkg.Imports { - imp := ld.pkgs[ipkg.ID] - wg.Add(1) - go func(imp *loaderPackage) { - ld.loadRecursive(imp) - wg.Done() - }(imp) - } - wg.Wait() - ld.loadPackage(lpkg) - }) -} - -// loadPackage loads the specified package. -// It must be called only once per Package, -// after immediate dependencies are loaded. -// Precondition: ld.Mode & NeedTypes. -func (ld *loader) loadPackage(lpkg *loaderPackage) { - if lpkg.PkgPath == "unsafe" { - // Fill in the blanks to avoid surprises. - lpkg.Types = types.Unsafe - lpkg.Fset = ld.Fset - lpkg.Syntax = []*ast.File{} - lpkg.TypesInfo = new(types.Info) - lpkg.TypesSizes = ld.sizes - return - } - - // Call NewPackage directly with explicit name. - // This avoids skew between golist and go/types when the files' - // package declarations are inconsistent. - lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name) - lpkg.Fset = ld.Fset - - // Subtle: we populate all Types fields with an empty Package - // before loading export data so that export data processing - // never has to create a types.Package for an indirect dependency, - // which would then require that such created packages be explicitly - // inserted back into the Import graph as a final step after export data loading. - // The Diamond test exercises this case. - if !lpkg.needtypes && !lpkg.needsrc { - return - } - if !lpkg.needsrc { - ld.loadFromExportData(lpkg) - return // not a source package, don't get syntax trees - } - - appendError := func(err error) { - // Convert various error types into the one true Error. - var errs []Error - switch err := err.(type) { - case Error: - // from driver - errs = append(errs, err) - - case *os.PathError: - // from parser - errs = append(errs, Error{ - Pos: err.Path + ":1", - Msg: err.Err.Error(), - Kind: ParseError, - }) - - case scanner.ErrorList: - // from parser - for _, err := range err { - errs = append(errs, Error{ - Pos: err.Pos.String(), - Msg: err.Msg, - Kind: ParseError, - }) - } - - case types.Error: - // from type checker - errs = append(errs, Error{ - Pos: err.Fset.Position(err.Pos).String(), - Msg: err.Msg, - Kind: TypeError, - }) - - default: - // unexpected impoverished error from parser? - errs = append(errs, Error{ - Pos: "-", - Msg: err.Error(), - Kind: UnknownError, - }) - - // If you see this error message, please file a bug. - log.Printf("internal error: error %q (%T) without position", err, err) - } - - lpkg.Errors = append(lpkg.Errors, errs...) - } - - if ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != "" { - // The config requested loading sources and types, but sources are missing. - // Add an error to the package and fall back to loading from export data. - appendError(Error{"-", fmt.Sprintf("sources missing for package %s", lpkg.ID), ParseError}) - ld.loadFromExportData(lpkg) - return // can't get syntax trees for this package - } - - files, errs := ld.parseFiles(lpkg.CompiledGoFiles) - for _, err := range errs { - appendError(err) - } - - lpkg.Syntax = files - if ld.Config.Mode&NeedTypes == 0 { - return - } - - lpkg.TypesInfo = &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), - } - lpkg.TypesSizes = ld.sizes - - importer := importerFunc(func(path string) (*types.Package, error) { - if path == "unsafe" { - return types.Unsafe, nil - } - - // The imports map is keyed by import path. - ipkg := lpkg.Imports[path] - if ipkg == nil { - if err := lpkg.importErrors[path]; err != nil { - return nil, err - } - // There was skew between the metadata and the - // import declarations, likely due to an edit - // race, or because the ParseFile feature was - // used to supply alternative file contents. - return nil, fmt.Errorf("no metadata for %s", path) - } - - if ipkg.Types != nil && ipkg.Types.Complete() { - return ipkg.Types, nil - } - log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg) - panic("unreachable") - }) - - // type-check - tc := &types.Config{ - Importer: importer, - - // Type-check bodies of functions only in non-initial packages. - // Example: for import graph A->B->C and initial packages {A,C}, - // we can ignore function bodies in B. - IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial, - - Error: appendError, - Sizes: ld.sizes, - } - if (ld.Mode & typecheckCgo) != 0 { - if !typesinternal.SetUsesCgo(tc) { - appendError(Error{ - Msg: "typecheckCgo requires Go 1.15+", - Kind: ListError, - }) - return - } - } - types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) - - lpkg.importErrors = nil // no longer needed - - // If !Cgo, the type-checker uses FakeImportC mode, so - // it doesn't invoke the importer for import "C", - // nor report an error for the import, - // or for any undefined C.f reference. - // We must detect this explicitly and correctly - // mark the package as IllTyped (by reporting an error). - // TODO(adonovan): if these errors are annoying, - // we could just set IllTyped quietly. - if tc.FakeImportC { - outer: - for _, f := range lpkg.Syntax { - for _, imp := range f.Imports { - if imp.Path.Value == `"C"` { - err := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import "C" ignored`} - appendError(err) - break outer - } - } - } - } - - // Record accumulated errors. - illTyped := len(lpkg.Errors) > 0 - if !illTyped { - for _, imp := range lpkg.Imports { - if imp.IllTyped { - illTyped = true - break - } - } - } - lpkg.IllTyped = illTyped -} - -// An importFunc is an implementation of the single-method -// types.Importer interface based on a function value. -type importerFunc func(path string) (*types.Package, error) - -func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } - -// We use a counting semaphore to limit -// the number of parallel I/O calls per process. -var ioLimit = make(chan bool, 20) - -func (ld *loader) parseFile(filename string) (*ast.File, error) { - ld.parseCacheMu.Lock() - v, ok := ld.parseCache[filename] - if ok { - // cache hit - ld.parseCacheMu.Unlock() - <-v.ready - } else { - // cache miss - v = &parseValue{ready: make(chan struct{})} - ld.parseCache[filename] = v - ld.parseCacheMu.Unlock() - - var src []byte - for f, contents := range ld.Config.Overlay { - if sameFile(f, filename) { - src = contents - } - } - var err error - if src == nil { - ioLimit <- true // wait - src, err = ioutil.ReadFile(filename) - <-ioLimit // signal - } - if err != nil { - v.err = err - } else { - v.f, v.err = ld.ParseFile(ld.Fset, filename, src) - } - - close(v.ready) - } - return v.f, v.err -} - -// parseFiles reads and parses the Go source files and returns the ASTs -// of the ones that could be at least partially parsed, along with a -// list of I/O and parse errors encountered. -// -// Because files are scanned in parallel, the token.Pos -// positions of the resulting ast.Files are not ordered. -// -func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) { - var wg sync.WaitGroup - n := len(filenames) - parsed := make([]*ast.File, n) - errors := make([]error, n) - for i, file := range filenames { - if ld.Config.Context.Err() != nil { - parsed[i] = nil - errors[i] = ld.Config.Context.Err() - continue - } - wg.Add(1) - go func(i int, filename string) { - parsed[i], errors[i] = ld.parseFile(filename) - wg.Done() - }(i, file) - } - wg.Wait() - - // Eliminate nils, preserving order. - var o int - for _, f := range parsed { - if f != nil { - parsed[o] = f - o++ - } - } - parsed = parsed[:o] - - o = 0 - for _, err := range errors { - if err != nil { - errors[o] = err - o++ - } - } - errors = errors[:o] - - return parsed, errors -} - -// sameFile returns true if x and y have the same basename and denote -// the same file. -// -func sameFile(x, y string) bool { - if x == y { - // It could be the case that y doesn't exist. - // For instance, it may be an overlay file that - // hasn't been written to disk. To handle that case - // let x == y through. (We added the exact absolute path - // string to the CompiledGoFiles list, so the unwritten - // overlay case implies x==y.) - return true - } - if strings.EqualFold(filepath.Base(x), filepath.Base(y)) { // (optimisation) - if xi, err := os.Stat(x); err == nil { - if yi, err := os.Stat(y); err == nil { - return os.SameFile(xi, yi) - } - } - } - return false -} - -// loadFromExportData returns type information for the specified -// package, loading it from an export data file on the first request. -func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error) { - if lpkg.PkgPath == "" { - log.Fatalf("internal error: Package %s has no PkgPath", lpkg) - } - - // Because gcexportdata.Read has the potential to create or - // modify the types.Package for each node in the transitive - // closure of dependencies of lpkg, all exportdata operations - // must be sequential. (Finer-grained locking would require - // changes to the gcexportdata API.) - // - // The exportMu lock guards the Package.Pkg field and the - // types.Package it points to, for each Package in the graph. - // - // Not all accesses to Package.Pkg need to be protected by exportMu: - // graph ordering ensures that direct dependencies of source - // packages are fully loaded before the importer reads their Pkg field. - ld.exportMu.Lock() - defer ld.exportMu.Unlock() - - if tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() { - return tpkg, nil // cache hit - } - - lpkg.IllTyped = true // fail safe - - if lpkg.ExportFile == "" { - // Errors while building export data will have been printed to stderr. - return nil, fmt.Errorf("no export data file") - } - f, err := os.Open(lpkg.ExportFile) - if err != nil { - return nil, err - } - defer f.Close() - - // Read gc export data. - // - // We don't currently support gccgo export data because all - // underlying workspaces use the gc toolchain. (Even build - // systems that support gccgo don't use it for workspace - // queries.) - r, err := gcexportdata.NewReader(f) - if err != nil { - return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) - } - - // Build the view. - // - // The gcexportdata machinery has no concept of package ID. - // It identifies packages by their PkgPath, which although not - // globally unique is unique within the scope of one invocation - // of the linker, type-checker, or gcexportdata. - // - // So, we must build a PkgPath-keyed view of the global - // (conceptually ID-keyed) cache of packages and pass it to - // gcexportdata. The view must contain every existing - // package that might possibly be mentioned by the - // current package---its transitive closure. - // - // In loadPackage, we unconditionally create a types.Package for - // each dependency so that export data loading does not - // create new ones. - // - // TODO(adonovan): it would be simpler and more efficient - // if the export data machinery invoked a callback to - // get-or-create a package instead of a map. - // - view := make(map[string]*types.Package) // view seen by gcexportdata - seen := make(map[*loaderPackage]bool) // all visited packages - var visit func(pkgs map[string]*Package) - visit = func(pkgs map[string]*Package) { - for _, p := range pkgs { - lpkg := ld.pkgs[p.ID] - if !seen[lpkg] { - seen[lpkg] = true - view[lpkg.PkgPath] = lpkg.Types - visit(lpkg.Imports) - } - } - } - visit(lpkg.Imports) - - viewLen := len(view) + 1 // adding the self package - // Parse the export data. - // (May modify incomplete packages in view but not create new ones.) - tpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath) - if err != nil { - return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err) - } - if viewLen != len(view) { - log.Fatalf("Unexpected package creation during export data loading") - } - - lpkg.Types = tpkg - lpkg.IllTyped = false - - return tpkg, nil -} - -// impliedLoadMode returns loadMode with its dependencies. -func impliedLoadMode(loadMode LoadMode) LoadMode { - if loadMode&NeedTypesInfo != 0 && loadMode&NeedImports == 0 { - // If NeedTypesInfo, go/packages needs to do typechecking itself so it can - // associate type info with the AST. To do so, we need the export data - // for dependencies, which means we need to ask for the direct dependencies. - // NeedImports is used to ask for the direct dependencies. - loadMode |= NeedImports - } - - if loadMode&NeedDeps != 0 && loadMode&NeedImports == 0 { - // With NeedDeps we need to load at least direct dependencies. - // NeedImports is used to ask for the direct dependencies. - loadMode |= NeedImports - } - - return loadMode -} - -func usesExportData(cfg *Config) bool { - return cfg.Mode&NeedExportsFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0 -} diff --git a/vendor/golang.org/x/tools/go/packages/visit.go b/vendor/golang.org/x/tools/go/packages/visit.go deleted file mode 100644 index a1dcc40b72..0000000000 --- a/vendor/golang.org/x/tools/go/packages/visit.go +++ /dev/null @@ -1,59 +0,0 @@ -// 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 packages - -import ( - "fmt" - "os" - "sort" -) - -// Visit visits all the packages in the import graph whose roots are -// pkgs, calling the optional pre function the first time each package -// is encountered (preorder), and the optional post function after a -// package's dependencies have been visited (postorder). -// The boolean result of pre(pkg) determines whether -// the imports of package pkg are visited. -func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) { - seen := make(map[*Package]bool) - var visit func(*Package) - visit = func(pkg *Package) { - if !seen[pkg] { - seen[pkg] = true - - if pre == nil || pre(pkg) { - paths := make([]string, 0, len(pkg.Imports)) - for path := range pkg.Imports { - paths = append(paths, path) - } - sort.Strings(paths) // Imports is a map, this makes visit stable - for _, path := range paths { - visit(pkg.Imports[path]) - } - } - - if post != nil { - post(pkg) - } - } - } - for _, pkg := range pkgs { - visit(pkg) - } -} - -// PrintErrors prints to os.Stderr the accumulated errors of all -// packages in the import graph rooted at pkgs, dependencies first. -// PrintErrors returns the number of errors printed. -func PrintErrors(pkgs []*Package) int { - var n int - Visit(pkgs, nil, func(pkg *Package) { - for _, err := range pkg.Errors { - fmt.Fprintln(os.Stderr, err) - n++ - } - }) - return n -} diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go deleted file mode 100644 index cffd7acbee..0000000000 --- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ /dev/null @@ -1,524 +0,0 @@ -// 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 - names := scope.Names() - for _, name := range 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 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 -} |