summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/tools/go/loader
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/tools/go/loader')
-rw-r--r--vendor/golang.org/x/tools/go/loader/cgo.go207
-rw-r--r--vendor/golang.org/x/tools/go/loader/cgo_pkgconfig.go39
-rw-r--r--vendor/golang.org/x/tools/go/loader/doc.go205
-rw-r--r--vendor/golang.org/x/tools/go/loader/example_test.go179
-rw-r--r--vendor/golang.org/x/tools/go/loader/loader.go1077
-rw-r--r--vendor/golang.org/x/tools/go/loader/loader_test.go816
-rw-r--r--vendor/golang.org/x/tools/go/loader/stdlib_test.go201
-rw-r--r--vendor/golang.org/x/tools/go/loader/testdata/a.go1
-rw-r--r--vendor/golang.org/x/tools/go/loader/testdata/b.go1
-rw-r--r--vendor/golang.org/x/tools/go/loader/testdata/badpkgdecl.go1
-rw-r--r--vendor/golang.org/x/tools/go/loader/util.go124
11 files changed, 0 insertions, 2851 deletions
diff --git a/vendor/golang.org/x/tools/go/loader/cgo.go b/vendor/golang.org/x/tools/go/loader/cgo.go
deleted file mode 100644
index 72c6f50..0000000
--- a/vendor/golang.org/x/tools/go/loader/cgo.go
+++ /dev/null
@@ -1,207 +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
-
-// This file 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.
-
-import (
- "fmt"
- "go/ast"
- "go/build"
- "go/parser"
- "go/token"
- "io/ioutil"
- "log"
- "os"
- "os/exec"
- "path/filepath"
- "regexp"
- "strings"
-)
-
-// processCgoFiles invokes the cgo preprocessor on bp.CgoFiles, parses
-// the output and returns the resulting ASTs.
-//
-func processCgoFiles(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 := runCgo(bp, pkgdir, tmpdir)
- 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(`[/\\:]`)
-
-// runCgo 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.
-//
-// runCgo is adapted from (*builder).cgo in
-// $GOROOT/src/cmd/go/build.go, but these features are unsupported:
-// Objective C, CGOPKGPATH, CGO_FLAGS.
-//
-func runCgo(bp *build.Package, pkgdir, tmpdir string) (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")
- }
-
- args := stringList(
- "go", "tool", "cgo", "-objdir", tmpdir, cgoflags, "--",
- cgoCPPFLAGS, cgoexeCFLAGS, bp.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/loader/cgo_pkgconfig.go b/vendor/golang.org/x/tools/go/loader/cgo_pkgconfig.go
deleted file mode 100644
index de57422..0000000
--- a/vendor/golang.org/x/tools/go/loader/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 loader
-
-import (
- "errors"
- "fmt"
- "go/build"
- "os/exec"
- "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/loader/doc.go b/vendor/golang.org/x/tools/go/loader/doc.go
deleted file mode 100644
index 9b51c9e..0000000
--- a/vendor/golang.org/x/tools/go/loader/doc.go
+++ /dev/null
@@ -1,205 +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.
-//
-// THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE.
-//
-// 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.
-
-// TODO(adonovan): overhaul the package documentation.
diff --git a/vendor/golang.org/x/tools/go/loader/example_test.go b/vendor/golang.org/x/tools/go/loader/example_test.go
deleted file mode 100644
index 88adde3..0000000
--- a/vendor/golang.org/x/tools/go/loader/example_test.go
+++ /dev/null
@@ -1,179 +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.
-
-// +build go1.8,!go1.9 // TODO(adonovan) determine which versions we need to test here
-// +build !windows
-
-package loader_test
-
-import (
- "fmt"
- "go/token"
- "log"
- "path/filepath"
- "runtime"
- "sort"
- "strings"
-
- "golang.org/x/tools/go/loader"
-)
-
-func printProgram(prog *loader.Program) {
- // Created packages are the initial packages specified by a call
- // to CreateFromFilenames or CreateFromFiles.
- var names []string
- for _, info := range prog.Created {
- names = append(names, info.Pkg.Path())
- }
- fmt.Printf("created: %s\n", names)
-
- // Imported packages are the initial packages specified by a
- // call to Import or ImportWithTests.
- names = nil
- for _, info := range prog.Imported {
- if strings.Contains(info.Pkg.Path(), "internal") {
- continue // skip, to reduce fragility
- }
- names = append(names, info.Pkg.Path())
- }
- sort.Strings(names)
- fmt.Printf("imported: %s\n", names)
-
- // InitialPackages contains the union of created and imported.
- names = nil
- for _, info := range prog.InitialPackages() {
- names = append(names, info.Pkg.Path())
- }
- sort.Strings(names)
- fmt.Printf("initial: %s\n", names)
-
- // AllPackages contains all initial packages and their dependencies.
- names = nil
- for pkg := range prog.AllPackages {
- names = append(names, pkg.Path())
- }
- sort.Strings(names)
- fmt.Printf("all: %s\n", names)
-}
-
-func printFilenames(fset *token.FileSet, info *loader.PackageInfo) {
- var names []string
- for _, f := range info.Files {
- names = append(names, filepath.Base(fset.File(f.Pos()).Name()))
- }
- fmt.Printf("%s.Files: %s\n", info.Pkg.Path(), names)
-}
-
-// This example loads a set of packages and all of their dependencies
-// from a typical command-line. FromArgs parses a command line and
-// makes calls to the other methods of Config shown in the examples that
-// follow.
-func ExampleConfig_FromArgs() {
- args := []string{"mytool", "unicode/utf8", "errors", "runtime", "--", "foo", "bar"}
- const wantTests = false
-
- var conf loader.Config
- rest, err := conf.FromArgs(args[1:], wantTests)
- prog, err := conf.Load()
- if err != nil {
- log.Fatal(err)
- }
-
- fmt.Printf("rest: %s\n", rest)
- printProgram(prog)
- // Output:
- // rest: [foo bar]
- // created: []
- // imported: [errors runtime unicode/utf8]
- // initial: [errors runtime unicode/utf8]
- // all: [errors runtime runtime/internal/atomic runtime/internal/sys unicode/utf8 unsafe]
-}
-
-// This example creates and type-checks a single package (without tests)
-// from a list of filenames, and loads all of its dependencies.
-// (The input files are actually only a small part of the math/cmplx package.)
-func ExampleConfig_CreateFromFilenames() {
- var conf loader.Config
- conf.CreateFromFilenames("math/cmplx",
- filepath.Join(runtime.GOROOT(), "src/math/cmplx/abs.go"),
- filepath.Join(runtime.GOROOT(), "src/math/cmplx/sin.go"))
- prog, err := conf.Load()
- if err != nil {
- log.Fatal(err)
- }
-
- printProgram(prog)
- // Output:
- // created: [math/cmplx]
- // imported: []
- // initial: [math/cmplx]
- // all: [math math/cmplx unsafe]
-}
-
-// In the examples below, for stability, the chosen packages are
-// relatively small, platform-independent, and low-level (and thus
-// infrequently changing).
-// The strconv package has internal and external tests.
-
-const hello = `package main
-
-import "fmt"
-
-func main() {
- fmt.Println("Hello, world.")
-}
-`
-
-// This example creates and type-checks a package from a list of
-// already-parsed files, and loads all its dependencies.
-func ExampleConfig_CreateFromFiles() {
- var conf loader.Config
- f, err := conf.ParseFile("hello.go", hello)
- if err != nil {
- log.Fatal(err)
- }
- conf.CreateFromFiles("hello", f)
- prog, err := conf.Load()
- if err != nil {
- log.Fatal(err)
- }
-
- printProgram(prog)
- printFilenames(prog.Fset, prog.Package("strconv"))
- // Output:
- // created: [hello]
- // imported: []
- // initial: [hello]
- // all: [errors fmt hello internal/race io math os reflect runtime runtime/internal/atomic runtime/internal/sys strconv sync sync/atomic syscall time unicode/utf8 unsafe]
- // strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
-}
-
-// This example imports three packages, including the tests for one of
-// them, and loads all their dependencies.
-func ExampleConfig_Import() {
- // ImportWithTest("strconv") causes strconv to include
- // internal_test.go, and creates an external test package,
- // strconv_test.
- // (Compare with the example of CreateFromFiles.)
-
- var conf loader.Config
- conf.Import("unicode/utf8")
- conf.Import("errors")
- conf.ImportWithTests("strconv")
- prog, err := conf.Load()
- if err != nil {
- log.Fatal(err)
- }
-
- printProgram(prog)
- printFilenames(prog.Fset, prog.Package("strconv"))
- printFilenames(prog.Fset, prog.Package("strconv_test"))
- // Output:
- // created: [strconv_test]
- // imported: [errors strconv unicode/utf8]
- // initial: [errors strconv strconv_test unicode/utf8]
- // all: [bufio bytes errors flag fmt internal/race io log math math/rand os reflect runtime runtime/debug runtime/internal/atomic runtime/internal/sys runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing time unicode unicode/utf8 unsafe]
- // strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
- // strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go example_test.go fp_test.go ftoa_test.go itoa_test.go quote_test.go strconv_test.go]
-}
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 de756f7..0000000
--- a/vendor/golang.org/x/tools/go/loader/loader.go
+++ /dev/null
@@ -1,1077 +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"
-)
-
-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 := processCgoFiles(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://github.com/golang/go/issues/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 {
- cycle = append([]string{fromPath}, cycle...)
- 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/loader_test.go b/vendor/golang.org/x/tools/go/loader/loader_test.go
deleted file mode 100644
index 02630eb..0000000
--- a/vendor/golang.org/x/tools/go/loader/loader_test.go
+++ /dev/null
@@ -1,816 +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.
-
-// No testdata on Android.
-
-// +build !android
-
-package loader_test
-
-import (
- "fmt"
- "go/build"
- "go/constant"
- "go/types"
- "path/filepath"
- "reflect"
- "sort"
- "strings"
- "sync"
- "testing"
-
- "golang.org/x/tools/go/buildutil"
- "golang.org/x/tools/go/loader"
-)
-
-// TestFromArgs checks that conf.FromArgs populates conf correctly.
-// It does no I/O.
-func TestFromArgs(t *testing.T) {
- type result struct {
- Err string
- Rest []string
- ImportPkgs map[string]bool
- CreatePkgs []loader.PkgSpec
- }
- for _, test := range []struct {
- args []string
- tests bool
- want result
- }{
- // Mix of existing and non-existent packages.
- {
- args: []string{"nosuchpkg", "errors"},
- want: result{
- ImportPkgs: map[string]bool{"errors": false, "nosuchpkg": false},
- },
- },
- // Same, with -test flag.
- {
- args: []string{"nosuchpkg", "errors"},
- tests: true,
- want: result{
- ImportPkgs: map[string]bool{"errors": true, "nosuchpkg": true},
- },
- },
- // Surplus arguments.
- {
- args: []string{"fmt", "errors", "--", "surplus"},
- want: result{
- Rest: []string{"surplus"},
- ImportPkgs: map[string]bool{"errors": false, "fmt": false},
- },
- },
- // Ad hoc package specified as *.go files.
- {
- args: []string{"foo.go", "bar.go"},
- want: result{CreatePkgs: []loader.PkgSpec{{
- Filenames: []string{"foo.go", "bar.go"},
- }}},
- },
- // Mixture of *.go and import paths.
- {
- args: []string{"foo.go", "fmt"},
- want: result{
- Err: "named files must be .go files: fmt",
- },
- },
- } {
- var conf loader.Config
- rest, err := conf.FromArgs(test.args, test.tests)
- got := result{
- Rest: rest,
- ImportPkgs: conf.ImportPkgs,
- CreatePkgs: conf.CreatePkgs,
- }
- if err != nil {
- got.Err = err.Error()
- }
- if !reflect.DeepEqual(got, test.want) {
- t.Errorf("FromArgs(%q) = %+v, want %+v", test.args, got, test.want)
- }
- }
-}
-
-func TestLoad_NoInitialPackages(t *testing.T) {
- var conf loader.Config
-
- const wantErr = "no initial packages were loaded"
-
- prog, err := conf.Load()
- if err == nil {
- t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
- } else if err.Error() != wantErr {
- t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
- }
- if prog != nil {
- t.Errorf("Load unexpectedly returned a Program")
- }
-}
-
-func TestLoad_MissingInitialPackage(t *testing.T) {
- var conf loader.Config
- conf.Import("nosuchpkg")
- conf.Import("errors")
-
- const wantErr = "couldn't load packages due to errors: nosuchpkg"
-
- prog, err := conf.Load()
- if err == nil {
- t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
- } else if err.Error() != wantErr {
- t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
- }
- if prog != nil {
- t.Errorf("Load unexpectedly returned a Program")
- }
-}
-
-func TestLoad_MissingInitialPackage_AllowErrors(t *testing.T) {
- var conf loader.Config
- conf.AllowErrors = true
- conf.Import("nosuchpkg")
- conf.ImportWithTests("errors")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed unexpectedly: %v", err)
- }
- if prog == nil {
- t.Fatalf("Load returned a nil Program")
- }
- if got, want := created(prog), "errors_test"; got != want {
- t.Errorf("Created = %s, want %s", got, want)
- }
- if got, want := imported(prog), "errors"; got != want {
- t.Errorf("Imported = %s, want %s", got, want)
- }
-}
-
-func TestCreateUnnamedPackage(t *testing.T) {
- var conf loader.Config
- conf.CreateFromFilenames("")
- prog, err := conf.Load()
- if err != nil {
- t.Fatalf("Load failed: %v", err)
- }
- if got, want := fmt.Sprint(prog.InitialPackages()), "[(unnamed)]"; got != want {
- t.Errorf("InitialPackages = %s, want %s", got, want)
- }
-}
-
-func TestLoad_MissingFileInCreatedPackage(t *testing.T) {
- var conf loader.Config
- conf.CreateFromFilenames("", "missing.go")
-
- const wantErr = "couldn't load packages due to errors: (unnamed)"
-
- prog, err := conf.Load()
- if prog != nil {
- t.Errorf("Load unexpectedly returned a Program")
- }
- if err == nil {
- t.Fatalf("Load succeeded unexpectedly, want %q", wantErr)
- }
- if err.Error() != wantErr {
- t.Fatalf("Load failed with wrong error %q, want %q", err, wantErr)
- }
-}
-
-func TestLoad_MissingFileInCreatedPackage_AllowErrors(t *testing.T) {
- conf := loader.Config{AllowErrors: true}
- conf.CreateFromFilenames("", "missing.go")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed: %v", err)
- }
- if got, want := fmt.Sprint(prog.InitialPackages()), "[(unnamed)]"; got != want {
- t.Fatalf("InitialPackages = %s, want %s", got, want)
- }
-}
-
-func TestLoad_ParseError(t *testing.T) {
- var conf loader.Config
- conf.CreateFromFilenames("badpkg", "testdata/badpkgdecl.go")
-
- const wantErr = "couldn't load packages due to errors: badpkg"
-
- prog, err := conf.Load()
- if prog != nil {
- t.Errorf("Load unexpectedly returned a Program")
- }
- if err == nil {
- t.Fatalf("Load succeeded unexpectedly, want %q", wantErr)
- }
- if err.Error() != wantErr {
- t.Fatalf("Load failed with wrong error %q, want %q", err, wantErr)
- }
-}
-
-func TestLoad_ParseError_AllowErrors(t *testing.T) {
- var conf loader.Config
- conf.AllowErrors = true
- conf.CreateFromFilenames("badpkg", "testdata/badpkgdecl.go")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed unexpectedly: %v", err)
- }
- if prog == nil {
- t.Fatalf("Load returned a nil Program")
- }
- if got, want := created(prog), "badpkg"; got != want {
- t.Errorf("Created = %s, want %s", got, want)
- }
-
- badpkg := prog.Created[0]
- if len(badpkg.Files) != 1 {
- t.Errorf("badpkg has %d files, want 1", len(badpkg.Files))
- }
- wantErr := filepath.Join("testdata", "badpkgdecl.go") + ":1:34: expected 'package', found 'EOF'"
- if !hasError(badpkg.Errors, wantErr) {
- t.Errorf("badpkg.Errors = %v, want %s", badpkg.Errors, wantErr)
- }
-}
-
-func TestLoad_FromSource_Success(t *testing.T) {
- var conf loader.Config
- conf.CreateFromFilenames("P", "testdata/a.go", "testdata/b.go")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed unexpectedly: %v", err)
- }
- if prog == nil {
- t.Fatalf("Load returned a nil Program")
- }
- if got, want := created(prog), "P"; got != want {
- t.Errorf("Created = %s, want %s", got, want)
- }
-}
-
-func TestLoad_FromImports_Success(t *testing.T) {
- var conf loader.Config
- conf.ImportWithTests("fmt")
- conf.ImportWithTests("errors")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed unexpectedly: %v", err)
- }
- if prog == nil {
- t.Fatalf("Load returned a nil Program")
- }
- if got, want := created(prog), "errors_test fmt_test"; got != want {
- t.Errorf("Created = %q, want %s", got, want)
- }
- if got, want := imported(prog), "errors fmt"; got != want {
- t.Errorf("Imported = %s, want %s", got, want)
- }
- // Check set of transitive packages.
- // There are >30 and the set may grow over time, so only check a few.
- want := map[string]bool{
- "strings": true,
- "time": true,
- "runtime": true,
- "testing": true,
- "unicode": true,
- }
- for _, path := range all(prog) {
- delete(want, path)
- }
- if len(want) > 0 {
- t.Errorf("AllPackages is missing these keys: %q", keys(want))
- }
-}
-
-func TestLoad_MissingIndirectImport(t *testing.T) {
- pkgs := map[string]string{
- "a": `package a; import _ "b"`,
- "b": `package b; import _ "c"`,
- }
- conf := loader.Config{Build: fakeContext(pkgs)}
- conf.Import("a")
-
- const wantErr = "couldn't load packages due to errors: b"
-
- prog, err := conf.Load()
- if err == nil {
- t.Errorf("Load succeeded unexpectedly, want %q", wantErr)
- } else if err.Error() != wantErr {
- t.Errorf("Load failed with wrong error %q, want %q", err, wantErr)
- }
- if prog != nil {
- t.Errorf("Load unexpectedly returned a Program")
- }
-}
-
-func TestLoad_BadDependency_AllowErrors(t *testing.T) {
- for _, test := range []struct {
- descr string
- pkgs map[string]string
- wantPkgs string
- }{
-
- {
- descr: "missing dependency",
- pkgs: map[string]string{
- "a": `package a; import _ "b"`,
- "b": `package b; import _ "c"`,
- },
- wantPkgs: "a b",
- },
- {
- descr: "bad package decl in dependency",
- pkgs: map[string]string{
- "a": `package a; import _ "b"`,
- "b": `package b; import _ "c"`,
- "c": `package`,
- },
- wantPkgs: "a b",
- },
- {
- descr: "parse error in dependency",
- pkgs: map[string]string{
- "a": `package a; import _ "b"`,
- "b": `package b; import _ "c"`,
- "c": `package c; var x = `,
- },
- wantPkgs: "a b c",
- },
- } {
- conf := loader.Config{
- AllowErrors: true,
- Build: fakeContext(test.pkgs),
- }
- conf.Import("a")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("%s: Load failed unexpectedly: %v", test.descr, err)
- }
- if prog == nil {
- t.Fatalf("%s: Load returned a nil Program", test.descr)
- }
-
- if got, want := imported(prog), "a"; got != want {
- t.Errorf("%s: Imported = %s, want %s", test.descr, got, want)
- }
- if got := all(prog); strings.Join(got, " ") != test.wantPkgs {
- t.Errorf("%s: AllPackages = %s, want %s", test.descr, got, test.wantPkgs)
- }
- }
-}
-
-func TestCwd(t *testing.T) {
- ctxt := fakeContext(map[string]string{"one/two/three": `package three`})
- for _, test := range []struct {
- cwd, arg, want string
- }{
- {cwd: "/go/src/one", arg: "./two/three", want: "one/two/three"},
- {cwd: "/go/src/one", arg: "../one/two/three", want: "one/two/three"},
- {cwd: "/go/src/one", arg: "one/two/three", want: "one/two/three"},
- {cwd: "/go/src/one/two/three", arg: ".", want: "one/two/three"},
- {cwd: "/go/src/one", arg: "two/three", want: ""},
- } {
- conf := loader.Config{
- Cwd: test.cwd,
- Build: ctxt,
- }
- conf.Import(test.arg)
-
- var got string
- prog, err := conf.Load()
- if prog != nil {
- got = imported(prog)
- }
- if got != test.want {
- t.Errorf("Load(%s) from %s: Imported = %s, want %s",
- test.arg, test.cwd, got, test.want)
- if err != nil {
- t.Errorf("Load failed: %v", err)
- }
- }
- }
-}
-
-func TestLoad_vendor(t *testing.T) {
- pkgs := map[string]string{
- "a": `package a; import _ "x"`,
- "a/vendor": ``, // mkdir a/vendor
- "a/vendor/x": `package xa`,
- "b": `package b; import _ "x"`,
- "b/vendor": ``, // mkdir b/vendor
- "b/vendor/x": `package xb`,
- "c": `package c; import _ "x"`,
- "x": `package xc`,
- }
- conf := loader.Config{Build: fakeContext(pkgs)}
- conf.Import("a")
- conf.Import("b")
- conf.Import("c")
-
- prog, err := conf.Load()
- if err != nil {
- t.Fatal(err)
- }
-
- // Check that a, b, and c see different versions of x.
- for _, r := range "abc" {
- name := string(r)
- got := prog.Package(name).Pkg.Imports()[0]
- want := "x" + name
- if got.Name() != want {
- t.Errorf("package %s import %q = %s, want %s",
- name, "x", got.Name(), want)
- }
- }
-}
-
-func TestVendorCwd(t *testing.T) {
- // Test the interaction of cwd and vendor directories.
- ctxt := fakeContext(map[string]string{
- "net": ``, // mkdir net
- "net/http": `package http; import _ "hpack"`,
- "vendor": ``, // mkdir vendor
- "vendor/hpack": `package vendorhpack`,
- "hpack": `package hpack`,
- })
- for i, test := range []struct {
- cwd, arg, want string
- }{
- {cwd: "/go/src/net", arg: "http"}, // not found
- {cwd: "/go/src/net", arg: "./http", want: "net/http vendor/hpack"},
- {cwd: "/go/src/net", arg: "hpack", want: "vendor/hpack"},
- {cwd: "/go/src/vendor", arg: "hpack", want: "vendor/hpack"},
- {cwd: "/go/src/vendor", arg: "./hpack", want: "vendor/hpack"},
- } {
- conf := loader.Config{
- Cwd: test.cwd,
- Build: ctxt,
- }
- conf.Import(test.arg)
-
- var got string
- prog, err := conf.Load()
- if prog != nil {
- got = strings.Join(all(prog), " ")
- }
- if got != test.want {
- t.Errorf("#%d: Load(%s) from %s: got %s, want %s",
- i, test.arg, test.cwd, got, test.want)
- if err != nil {
- t.Errorf("Load failed: %v", err)
- }
- }
- }
-}
-
-func TestVendorCwdIssue16580(t *testing.T) {
- // Regression test for Go issue 16580.
- // Import decls in "created" packages were vendor-resolved
- // w.r.t. cwd, not the parent directory of the package's files.
- ctxt := fakeContext(map[string]string{
- "a": ``, // mkdir a
- "a/vendor": ``, // mkdir a/vendor
- "a/vendor/b": `package b; const X = true`,
- "b": `package b; const X = false`,
- })
- for _, test := range []struct {
- filename, cwd string
- want bool // expected value of b.X; depends on filename, not on cwd
- }{
- {filename: "c.go", cwd: "/go/src", want: false},
- {filename: "c.go", cwd: "/go/src/a", want: false},
- {filename: "c.go", cwd: "/go/src/a/b", want: false},
- {filename: "c.go", cwd: "/go/src/a/vendor/b", want: false},
-
- {filename: "/go/src/a/c.go", cwd: "/go/src", want: true},
- {filename: "/go/src/a/c.go", cwd: "/go/src/a", want: true},
- {filename: "/go/src/a/c.go", cwd: "/go/src/a/b", want: true},
- {filename: "/go/src/a/c.go", cwd: "/go/src/a/vendor/b", want: true},
-
- {filename: "/go/src/c/c.go", cwd: "/go/src", want: false},
- {filename: "/go/src/c/c.go", cwd: "/go/src/a", want: false},
- {filename: "/go/src/c/c.go", cwd: "/go/src/a/b", want: false},
- {filename: "/go/src/c/c.go", cwd: "/go/src/a/vendor/b", want: false},
- } {
- conf := loader.Config{
- Cwd: test.cwd,
- Build: ctxt,
- }
- f, err := conf.ParseFile(test.filename, `package dummy; import "b"; const X = b.X`)
- if err != nil {
- t.Fatal(f)
- }
- conf.CreateFromFiles("dummy", f)
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("%+v: Load failed: %v", test, err)
- continue
- }
-
- x := constant.BoolVal(prog.Created[0].Pkg.Scope().Lookup("X").(*types.Const).Val())
- if x != test.want {
- t.Errorf("%+v: b.X = %t", test, x)
- }
- }
-
- // TODO(adonovan): also test imports within XTestGoFiles.
-}
-
-// TODO(adonovan): more Load tests:
-//
-// failures:
-// - to parse package decl of *_test.go files
-// - to parse package decl of external *_test.go files
-// - to parse whole of *_test.go files
-// - to parse whole of external *_test.go files
-// - to open a *.go file during import scanning
-// - to import from binary
-
-// features:
-// - InitialPackages
-// - PackageCreated hook
-// - TypeCheckFuncBodies hook
-
-func TestTransitivelyErrorFreeFlag(t *testing.T) {
- // Create an minimal custom build.Context
- // that fakes the following packages:
- //
- // a --> b --> c! c has an error
- // \ d and e are transitively error-free.
- // e --> d
- //
- // Each package [a-e] consists of one file, x.go.
- pkgs := map[string]string{
- "a": `package a; import (_ "b"; _ "e")`,
- "b": `package b; import _ "c"`,
- "c": `package c; func f() { _ = int(false) }`, // type error within function body
- "d": `package d;`,
- "e": `package e; import _ "d"`,
- }
- conf := loader.Config{
- AllowErrors: true,
- Build: fakeContext(pkgs),
- }
- conf.Import("a")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed: %s", err)
- }
- if prog == nil {
- t.Fatalf("Load returned nil *Program")
- }
-
- for pkg, info := range prog.AllPackages {
- var wantErr, wantTEF bool
- switch pkg.Path() {
- case "a", "b":
- case "c":
- wantErr = true
- case "d", "e":
- wantTEF = true
- default:
- t.Errorf("unexpected package: %q", pkg.Path())
- continue
- }
-
- if (info.Errors != nil) != wantErr {
- if wantErr {
- t.Errorf("Package %q.Error = nil, want error", pkg.Path())
- } else {
- t.Errorf("Package %q has unexpected Errors: %v",
- pkg.Path(), info.Errors)
- }
- }
-
- if info.TransitivelyErrorFree != wantTEF {
- t.Errorf("Package %q.TransitivelyErrorFree=%t, want %t",
- pkg.Path(), info.TransitivelyErrorFree, wantTEF)
- }
- }
-}
-
-// Test that syntax (scan/parse), type, and loader errors are recorded
-// (in PackageInfo.Errors) and reported (via Config.TypeChecker.Error).
-func TestErrorReporting(t *testing.T) {
- pkgs := map[string]string{
- "a": `package a; import (_ "b"; _ "c"); var x int = false`,
- "b": `package b; 'syntax error!`,
- }
- conf := loader.Config{
- AllowErrors: true,
- Build: fakeContext(pkgs),
- }
- var mu sync.Mutex
- var allErrors []error
- conf.TypeChecker.Error = func(err error) {
- mu.Lock()
- allErrors = append(allErrors, err)
- mu.Unlock()
- }
- conf.Import("a")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed: %s", err)
- }
- if prog == nil {
- t.Fatalf("Load returned nil *Program")
- }
-
- // TODO(adonovan): test keys of ImportMap.
-
- // Check errors recorded in each PackageInfo.
- for pkg, info := range prog.AllPackages {
- switch pkg.Path() {
- case "a":
- if !hasError(info.Errors, "cannot convert false") {
- t.Errorf("a.Errors = %v, want bool conversion (type) error", info.Errors)
- }
- if !hasError(info.Errors, "could not import c") {
- t.Errorf("a.Errors = %v, want import (loader) error", info.Errors)
- }
- case "b":
- if !hasError(info.Errors, "rune literal not terminated") {
- t.Errorf("b.Errors = %v, want unterminated literal (syntax) error", info.Errors)
- }
- }
- }
-
- // Check errors reported via error handler.
- if !hasError(allErrors, "cannot convert false") ||
- !hasError(allErrors, "rune literal not terminated") ||
- !hasError(allErrors, "could not import c") {
- t.Errorf("allErrors = %v, want syntax, type and loader errors", allErrors)
- }
-}
-
-func TestCycles(t *testing.T) {
- for _, test := range []struct {
- descr string
- ctxt *build.Context
- wantErr string
- }{
- {
- "self-cycle",
- fakeContext(map[string]string{
- "main": `package main; import _ "selfcycle"`,
- "selfcycle": `package selfcycle; import _ "selfcycle"`,
- }),
- `import cycle: selfcycle -> selfcycle`,
- },
- {
- "three-package cycle",
- fakeContext(map[string]string{
- "main": `package main; import _ "a"`,
- "a": `package a; import _ "b"`,
- "b": `package b; import _ "c"`,
- "c": `package c; import _ "a"`,
- }),
- `import cycle: c -> a -> b -> c`,
- },
- {
- "self-cycle in dependency of test file",
- buildutil.FakeContext(map[string]map[string]string{
- "main": {
- "main.go": `package main`,
- "main_test.go": `package main; import _ "a"`,
- },
- "a": {
- "a.go": `package a; import _ "a"`,
- },
- }),
- `import cycle: a -> a`,
- },
- // TODO(adonovan): fix: these fail
- // {
- // "two-package cycle in dependency of test file",
- // buildutil.FakeContext(map[string]map[string]string{
- // "main": {
- // "main.go": `package main`,
- // "main_test.go": `package main; import _ "a"`,
- // },
- // "a": {
- // "a.go": `package a; import _ "main"`,
- // },
- // }),
- // `import cycle: main -> a -> main`,
- // },
- // {
- // "self-cycle in augmented package",
- // buildutil.FakeContext(map[string]map[string]string{
- // "main": {
- // "main.go": `package main`,
- // "main_test.go": `package main; import _ "main"`,
- // },
- // }),
- // `import cycle: main -> main`,
- // },
- } {
- conf := loader.Config{
- AllowErrors: true,
- Build: test.ctxt,
- }
- var mu sync.Mutex
- var allErrors []error
- conf.TypeChecker.Error = func(err error) {
- mu.Lock()
- allErrors = append(allErrors, err)
- mu.Unlock()
- }
- conf.ImportWithTests("main")
-
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("%s: Load failed: %s", test.descr, err)
- }
- if prog == nil {
- t.Fatalf("%s: Load returned nil *Program", test.descr)
- }
-
- if !hasError(allErrors, test.wantErr) {
- t.Errorf("%s: Load() errors = %q, want %q",
- test.descr, allErrors, test.wantErr)
- }
- }
-
- // TODO(adonovan):
- // - Test that in a legal test cycle, none of the symbols
- // defined by augmentation are visible via import.
-}
-
-// ---- utilities ----
-
-// Simplifying wrapper around buildutil.FakeContext for single-file packages.
-func fakeContext(pkgs map[string]string) *build.Context {
- pkgs2 := make(map[string]map[string]string)
- for path, content := range pkgs {
- pkgs2[path] = map[string]string{"x.go": content}
- }
- return buildutil.FakeContext(pkgs2)
-}
-
-func hasError(errors []error, substr string) bool {
- for _, err := range errors {
- if strings.Contains(err.Error(), substr) {
- return true
- }
- }
- return false
-}
-
-func keys(m map[string]bool) (keys []string) {
- for key := range m {
- keys = append(keys, key)
- }
- sort.Strings(keys)
- return
-}
-
-// Returns all loaded packages.
-func all(prog *loader.Program) []string {
- var pkgs []string
- for _, info := range prog.AllPackages {
- pkgs = append(pkgs, info.Pkg.Path())
- }
- sort.Strings(pkgs)
- return pkgs
-}
-
-// Returns initially imported packages, as a string.
-func imported(prog *loader.Program) string {
- var pkgs []string
- for _, info := range prog.Imported {
- pkgs = append(pkgs, info.Pkg.Path())
- }
- sort.Strings(pkgs)
- return strings.Join(pkgs, " ")
-}
-
-// Returns initially created packages, as a string.
-func created(prog *loader.Program) string {
- var pkgs []string
- for _, info := range prog.Created {
- pkgs = append(pkgs, info.Pkg.Path())
- }
- return strings.Join(pkgs, " ")
-}
-
-// Load package "io" twice in parallel.
-// When run with -race, this is a regression test for Go issue 20718, in
-// which the global "unsafe" package was modified concurrently.
-func TestLoad1(t *testing.T) { loadIO(t) }
-func TestLoad2(t *testing.T) { loadIO(t) }
-
-func loadIO(t *testing.T) {
- t.Parallel()
- conf := &loader.Config{ImportPkgs: map[string]bool{"io": false}}
- if _, err := conf.Load(); err != nil {
- t.Fatal(err)
- }
-}
diff --git a/vendor/golang.org/x/tools/go/loader/stdlib_test.go b/vendor/golang.org/x/tools/go/loader/stdlib_test.go
deleted file mode 100644
index 2cd066f..0000000
--- a/vendor/golang.org/x/tools/go/loader/stdlib_test.go
+++ /dev/null
@@ -1,201 +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_test
-
-// This file enumerates all packages beneath $GOROOT, loads them, plus
-// their external tests if any, runs the type checker on them, and
-// prints some summary information.
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/build"
- "go/token"
- "go/types"
- "io/ioutil"
- "path/filepath"
- "runtime"
- "strings"
- "testing"
- "time"
-
- "golang.org/x/tools/go/buildutil"
- "golang.org/x/tools/go/loader"
-)
-
-func TestStdlib(t *testing.T) {
- if runtime.GOOS == "android" {
- t.Skipf("incomplete std lib on %s", runtime.GOOS)
- }
- if testing.Short() {
- t.Skip("skipping in short mode; uses tons of memory (golang.org/issue/14113)")
- }
-
- runtime.GC()
- t0 := time.Now()
- var memstats runtime.MemStats
- runtime.ReadMemStats(&memstats)
- alloc := memstats.Alloc
-
- // Load, parse and type-check the program.
- ctxt := build.Default // copy
- ctxt.GOPATH = "" // disable GOPATH
- conf := loader.Config{Build: &ctxt}
- for _, path := range buildutil.AllPackages(conf.Build) {
- conf.ImportWithTests(path)
- }
-
- prog, err := conf.Load()
- if err != nil {
- t.Fatalf("Load failed: %v", err)
- }
-
- t1 := time.Now()
- runtime.GC()
- runtime.ReadMemStats(&memstats)
-
- numPkgs := len(prog.AllPackages)
- if want := 205; numPkgs < want {
- t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
- }
-
- // Dump package members.
- if false {
- for pkg := range prog.AllPackages {
- fmt.Printf("Package %s:\n", pkg.Path())
- scope := pkg.Scope()
- qualifier := types.RelativeTo(pkg)
- for _, name := range scope.Names() {
- if ast.IsExported(name) {
- fmt.Printf("\t%s\n", types.ObjectString(scope.Lookup(name), qualifier))
- }
- }
- fmt.Println()
- }
- }
-
- // Check that Test functions for io/ioutil, regexp and
- // compress/bzip2 are all simultaneously present.
- // (The apparent cycle formed when augmenting all three of
- // these packages by their tests was the original motivation
- // for reporting b/7114.)
- //
- // compress/bzip2.TestBitReader in bzip2_test.go imports io/ioutil
- // io/ioutil.TestTempFile in tempfile_test.go imports regexp
- // regexp.TestRE2Search in exec_test.go imports compress/bzip2
- for _, test := range []struct{ pkg, fn string }{
- {"io/ioutil", "TestTempFile"},
- {"regexp", "TestRE2Search"},
- {"compress/bzip2", "TestBitReader"},
- } {
- info := prog.Imported[test.pkg]
- if info == nil {
- t.Errorf("failed to load package %q", test.pkg)
- continue
- }
- obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)
- if obj == nil {
- t.Errorf("package %q has no func %q", test.pkg, test.fn)
- continue
- }
- }
-
- // Dump some statistics.
-
- // determine line count
- var lineCount int
- prog.Fset.Iterate(func(f *token.File) bool {
- lineCount += f.LineCount()
- return true
- })
-
- t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
- t.Log("#Source lines: ", lineCount)
- t.Log("Load/parse/typecheck: ", t1.Sub(t0))
- t.Log("#MB: ", int64(memstats.Alloc-alloc)/1000000)
-}
-
-func TestCgoOption(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping in short mode; uses tons of memory (golang.org/issue/14113)")
- }
- switch runtime.GOOS {
- // On these systems, the net and os/user packages don't use cgo
- // or the std library is incomplete (Android).
- case "android", "plan9", "solaris", "windows":
- t.Skipf("no cgo or incomplete std lib on %s", runtime.GOOS)
- }
- // In nocgo builds (e.g. linux-amd64-nocgo),
- // there is no "runtime/cgo" package,
- // so cgo-generated Go files will have a failing import.
- if !build.Default.CgoEnabled {
- return
- }
- // Test that we can load cgo-using packages with
- // CGO_ENABLED=[01], which causes go/build to select pure
- // Go/native implementations, respectively, based on build
- // tags.
- //
- // Each entry specifies a package-level object and the generic
- // file expected to define it when cgo is disabled.
- // When cgo is enabled, the exact file is not specified (since
- // it varies by platform), but must differ from the generic one.
- //
- // The test also loads the actual file to verify that the
- // object is indeed defined at that location.
- for _, test := range []struct {
- pkg, name, genericFile string
- }{
- {"net", "cgoLookupHost", "cgo_stub.go"},
- {"os/user", "current", "lookup_stubs.go"},
- } {
- ctxt := build.Default
- for _, ctxt.CgoEnabled = range []bool{false, true} {
- conf := loader.Config{Build: &ctxt}
- conf.Import(test.pkg)
- prog, err := conf.Load()
- if err != nil {
- t.Errorf("Load failed: %v", err)
- continue
- }
- info := prog.Imported[test.pkg]
- if info == nil {
- t.Errorf("package %s not found", test.pkg)
- continue
- }
- obj := info.Pkg.Scope().Lookup(test.name)
- if obj == nil {
- t.Errorf("no object %s.%s", test.pkg, test.name)
- continue
- }
- posn := prog.Fset.Position(obj.Pos())
- t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled)
-
- gotFile := filepath.Base(posn.Filename)
- filesMatch := gotFile == test.genericFile
-
- if ctxt.CgoEnabled && filesMatch {
- t.Errorf("CGO_ENABLED=1: %s found in %s, want native file",
- obj, gotFile)
- } else if !ctxt.CgoEnabled && !filesMatch {
- t.Errorf("CGO_ENABLED=0: %s found in %s, want %s",
- obj, gotFile, test.genericFile)
- }
-
- // Load the file and check the object is declared at the right place.
- b, err := ioutil.ReadFile(posn.Filename)
- if err != nil {
- t.Errorf("can't read %s: %s", posn.Filename, err)
- continue
- }
- line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
- ident := line[posn.Column-1:]
- if !strings.HasPrefix(ident, test.name) {
- t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident)
- }
- }
- }
-}
diff --git a/vendor/golang.org/x/tools/go/loader/testdata/a.go b/vendor/golang.org/x/tools/go/loader/testdata/a.go
deleted file mode 100644
index bae3955..0000000
--- a/vendor/golang.org/x/tools/go/loader/testdata/a.go
+++ /dev/null
@@ -1 +0,0 @@
-package P
diff --git a/vendor/golang.org/x/tools/go/loader/testdata/b.go b/vendor/golang.org/x/tools/go/loader/testdata/b.go
deleted file mode 100644
index bae3955..0000000
--- a/vendor/golang.org/x/tools/go/loader/testdata/b.go
+++ /dev/null
@@ -1 +0,0 @@
-package P
diff --git a/vendor/golang.org/x/tools/go/loader/testdata/badpkgdecl.go b/vendor/golang.org/x/tools/go/loader/testdata/badpkgdecl.go
deleted file mode 100644
index 1e39359..0000000
--- a/vendor/golang.org/x/tools/go/loader/testdata/badpkgdecl.go
+++ /dev/null
@@ -1 +0,0 @@
-// this file has no package decl
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 7f38dd7..0000000
--- 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()
-}