github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/loader/loader.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package loader loads, parses and type-checks packages of Go code
     6  // plus their transitive closure, and retains both the ASTs and the
     7  // derived facts.
     8  //
     9  // THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE.
    10  //
    11  // The package defines two primary types: Config, which specifies a
    12  // set of initial packages to load and various other options; and
    13  // Program, which is the result of successfully loading the packages
    14  // specified by a configuration.
    15  //
    16  // The configuration can be set directly, but *Config provides various
    17  // convenience methods to simplify the common cases, each of which can
    18  // be called any number of times.  Finally, these are followed by a
    19  // call to Load() to actually load and type-check the program.
    20  //
    21  //      var conf loader.Config
    22  //
    23  //      // Use the command-line arguments to specify
    24  //      // a set of initial packages to load from source.
    25  //      // See FromArgsUsage for help.
    26  //      rest, err := conf.FromArgs(os.Args[1:], wantTests)
    27  //
    28  //      // Parse the specified files and create an ad-hoc package with path "foo".
    29  //      // All files must have the same 'package' declaration.
    30  //      conf.CreateFromFilenames("foo", "foo.go", "bar.go")
    31  //
    32  //      // Create an ad-hoc package with path "foo" from
    33  //      // the specified already-parsed files.
    34  //      // All ASTs must have the same 'package' declaration.
    35  //      conf.CreateFromFiles("foo", parsedFiles)
    36  //
    37  //      // Add "runtime" to the set of packages to be loaded.
    38  //      conf.Import("runtime")
    39  //
    40  //      // Adds "fmt" and "fmt_test" to the set of packages
    41  //      // to be loaded.  "fmt" will include *_test.go files.
    42  //      conf.ImportWithTests("fmt")
    43  //
    44  //      // Finally, load all the packages specified by the configuration.
    45  //      prog, err := conf.Load()
    46  //
    47  //
    48  // CONCEPTS AND TERMINOLOGY
    49  //
    50  // An AD-HOC package is one specified as a set of source files on the
    51  // command line.  In the simplest case, it may consist of a single file
    52  // such as $GOROOT/src/net/http/triv.go.
    53  //
    54  // EXTERNAL TEST packages are those comprised of a set of *_test.go
    55  // files all with the same 'package foo_test' declaration, all in the
    56  // same directory.  (go/build.Package calls these files XTestFiles.)
    57  //
    58  // An IMPORTABLE package is one that can be referred to by some import
    59  // spec.  The Path() of each importable package is unique within a
    60  // Program.
    61  //
    62  // Ad-hoc packages and external test packages are NON-IMPORTABLE.  The
    63  // Path() of an ad-hoc package is inferred from the package
    64  // declarations of its files and is therefore not a unique package key.
    65  // For example, Config.CreatePkgs may specify two initial ad-hoc
    66  // packages both called "main".
    67  //
    68  // An AUGMENTED package is an importable package P plus all the
    69  // *_test.go files with same 'package foo' declaration as P.
    70  // (go/build.Package calls these files TestFiles.)
    71  //
    72  // The INITIAL packages are those specified in the configuration.  A
    73  // DEPENDENCY is a package loaded to satisfy an import in an initial
    74  // package or another dependency.
    75  //
    76  package loader
    77  
    78  // 'go test', in-package test files, and import cycles
    79  // ---------------------------------------------------
    80  //
    81  // An external test package may depend upon members of the augmented
    82  // package that are not in the unaugmented package, such as functions
    83  // that expose internals.  (See bufio/export_test.go for an example.)
    84  // So, the loader must ensure that for each external test package
    85  // it loads, it also augments the corresponding non-test package.
    86  //
    87  // The import graph over n unaugmented packages must be acyclic; the
    88  // import graph over n-1 unaugmented packages plus one augmented
    89  // package must also be acyclic.  ('go test' relies on this.)  But the
    90  // import graph over n augmented packages may contain cycles.
    91  //
    92  // First, all the (unaugmented) non-test packages and their
    93  // dependencies are imported in the usual way; the loader reports an
    94  // error if it detects an import cycle.
    95  //
    96  // Then, each package P for which testing is desired is augmented by
    97  // the list P' of its in-package test files, by calling
    98  // (*types.Checker).Files.  This arrangement ensures that P' may
    99  // reference definitions within P, but P may not reference definitions
   100  // within P'.  Furthermore, P' may import any other package, including
   101  // ones that depend upon P, without an import cycle error.
   102  //
   103  // Consider two packages A and B, both of which have lists of
   104  // in-package test files we'll call A' and B', and which have the
   105  // following import graph edges:
   106  //    B  imports A
   107  //    B' imports A
   108  //    A' imports B
   109  // This last edge would be expected to create an error were it not
   110  // for the special type-checking discipline above.
   111  // Cycles of size greater than two are possible.  For example:
   112  //   compress/bzip2/bzip2_test.go (package bzip2)  imports "io/ioutil"
   113  //   io/ioutil/tempfile_test.go   (package ioutil) imports "regexp"
   114  //   regexp/exec_test.go          (package regexp) imports "compress/bzip2"
   115  //
   116  //
   117  // Concurrency
   118  // -----------
   119  //
   120  // Let us define the import dependency graph as follows.  Each node is a
   121  // list of files passed to (Checker).Files at once.  Many of these lists
   122  // are the production code of an importable Go package, so those nodes
   123  // are labelled by the package's import path.  The remaining nodes are
   124  // ad-hoc packages and lists of in-package *_test.go files that augment
   125  // an importable package; those nodes have no label.
   126  //
   127  // The edges of the graph represent import statements appearing within a
   128  // file.  An edge connects a node (a list of files) to the node it
   129  // imports, which is importable and thus always labelled.
   130  //
   131  // Loading is controlled by this dependency graph.
   132  //
   133  // To reduce I/O latency, we start loading a package's dependencies
   134  // asynchronously as soon as we've parsed its files and enumerated its
   135  // imports (scanImports).  This performs a preorder traversal of the
   136  // import dependency graph.
   137  //
   138  // To exploit hardware parallelism, we type-check unrelated packages in
   139  // parallel, where "unrelated" means not ordered by the partial order of
   140  // the import dependency graph.
   141  //
   142  // We use a concurrency-safe blocking cache (importer.imported) to
   143  // record the results of type-checking, whether success or failure.  An
   144  // entry is created in this cache by startLoad the first time the
   145  // package is imported.  The first goroutine to request an entry becomes
   146  // responsible for completing the task and broadcasting completion to
   147  // subsequent requestors, which block until then.
   148  //
   149  // Type checking occurs in (parallel) postorder: we cannot type-check a
   150  // set of files until we have loaded and type-checked all of their
   151  // immediate dependencies (and thus all of their transitive
   152  // dependencies). If the input were guaranteed free of import cycles,
   153  // this would be trivial: we could simply wait for completion of the
   154  // dependencies and then invoke the typechecker.
   155  //
   156  // But as we saw in the 'go test' section above, some cycles in the
   157  // import graph over packages are actually legal, so long as the
   158  // cycle-forming edge originates in the in-package test files that
   159  // augment the package.  This explains why the nodes of the import
   160  // dependency graph are not packages, but lists of files: the unlabelled
   161  // nodes avoid the cycles.  Consider packages A and B where B imports A
   162  // and A's in-package tests AT import B.  The naively constructed import
   163  // graph over packages would contain a cycle (A+AT) --> B --> (A+AT) but
   164  // the graph over lists of files is AT --> B --> A, where AT is an
   165  // unlabelled node.
   166  //
   167  // Awaiting completion of the dependencies in a cyclic graph would
   168  // deadlock, so we must materialize the import dependency graph (as
   169  // importer.graph) and check whether each import edge forms a cycle.  If
   170  // x imports y, and the graph already contains a path from y to x, then
   171  // there is an import cycle, in which case the processing of x must not
   172  // wait for the completion of processing of y.
   173  //
   174  // When the type-checker makes a callback (doImport) to the loader for a
   175  // given import edge, there are two possible cases.  In the normal case,
   176  // the dependency has already been completely type-checked; doImport
   177  // does a cache lookup and returns it.  In the cyclic case, the entry in
   178  // the cache is still necessarily incomplete, indicating a cycle.  We
   179  // perform the cycle check again to obtain the error message, and return
   180  // the error.
   181  //
   182  // The result of using concurrency is about a 2.5x speedup for stdlib_test.
   183  
   184  // TODO(adonovan):
   185  // - cache the calls to build.Import so we don't do it three times per
   186  //   test package.
   187  // - Thorough overhaul of package documentation.
   188  
   189  import (
   190  	"errors"
   191  	"fmt"
   192  	"go/ast"
   193  	"go/build"
   194  	"go/parser"
   195  	"go/token"
   196  	"os"
   197  	"sort"
   198  	"strings"
   199  	"sync"
   200  	"time"
   201  
   202  	"llvm.org/llgo/third_party/gotools/go/ast/astutil"
   203  	"llvm.org/llgo/third_party/gotools/go/gcimporter"
   204  	"llvm.org/llgo/third_party/gotools/go/types"
   205  )
   206  
   207  const trace = false // show timing info for type-checking
   208  
   209  // Config specifies the configuration for a program to load.
   210  // The zero value for Config is a ready-to-use default configuration.
   211  type Config struct {
   212  	// Fset is the file set for the parser to use when loading the
   213  	// program.  If nil, it may be lazily initialized by any
   214  	// method of Config.
   215  	Fset *token.FileSet
   216  
   217  	// ParserMode specifies the mode to be used by the parser when
   218  	// loading source packages.
   219  	ParserMode parser.Mode
   220  
   221  	// TypeChecker contains options relating to the type checker.
   222  	//
   223  	// The supplied IgnoreFuncBodies is not used; the effective
   224  	// value comes from the TypeCheckFuncBodies func below.
   225  	//
   226  	// TypeChecker.Packages is lazily initialized during Load.
   227  	TypeChecker types.Config
   228  
   229  	// TypeCheckFuncBodies is a predicate over package import
   230  	// paths.  A package for which the predicate is false will
   231  	// have its package-level declarations type checked, but not
   232  	// its function bodies; this can be used to quickly load
   233  	// dependencies from source.  If nil, all func bodies are type
   234  	// checked.
   235  	TypeCheckFuncBodies func(string) bool
   236  
   237  	// ImportFromBinary determines whether to satisfy dependencies by
   238  	// loading gc export data instead of Go source code.
   239  	//
   240  	// If false, the entire program---the initial packages and their
   241  	// transitive closure of dependencies---will be loaded from
   242  	// source, parsed, and type-checked.  This is required for
   243  	// whole-program analyses such as pointer analysis.
   244  	//
   245  	// If true, the go/gcimporter mechanism is used instead to read
   246  	// the binary export-data files written by the gc toolchain.
   247  	// They supply only the types of package-level declarations and
   248  	// values of constants, but no code, this option will not yield
   249  	// a whole program.  It is intended for analyses that perform
   250  	// modular analysis of a single package, e.g. traditional
   251  	// compilation.
   252  	//
   253  	// No check is made that the export data files are up-to-date.
   254  	//
   255  	// The initial packages (CreatePkgs and ImportPkgs) are always
   256  	// loaded from Go source, regardless of this flag's setting.
   257  	//
   258  	// NB: there is a bug when loading multiple initial packages with
   259  	// this flag enabled: https://github.com/golang/go/issues/9955.
   260  	ImportFromBinary bool
   261  
   262  	// If Build is non-nil, it is used to locate source packages.
   263  	// Otherwise &build.Default is used.
   264  	//
   265  	// By default, cgo is invoked to preprocess Go files that
   266  	// import the fake package "C".  This behaviour can be
   267  	// disabled by setting CGO_ENABLED=0 in the environment prior
   268  	// to startup, or by setting Build.CgoEnabled=false.
   269  	Build *build.Context
   270  
   271  	// The current directory, used for resolving relative package
   272  	// references such as "./go/loader".  If empty, os.Getwd will be
   273  	// used instead.
   274  	Cwd string
   275  
   276  	// If DisplayPath is non-nil, it is used to transform each
   277  	// file name obtained from Build.Import().  This can be used
   278  	// to prevent a virtualized build.Config's file names from
   279  	// leaking into the user interface.
   280  	DisplayPath func(path string) string
   281  
   282  	// If AllowErrors is true, Load will return a Program even
   283  	// if some of the its packages contained I/O, parser or type
   284  	// errors; such errors are accessible via PackageInfo.Errors.  If
   285  	// false, Load will fail if any package had an error.
   286  	AllowErrors bool
   287  
   288  	// CreatePkgs specifies a list of non-importable initial
   289  	// packages to create.  The resulting packages will appear in
   290  	// the corresponding elements of the Program.Created slice.
   291  	CreatePkgs []PkgSpec
   292  
   293  	// ImportPkgs specifies a set of initial packages to load from
   294  	// source.  The map keys are package import paths, used to
   295  	// locate the package relative to $GOROOT.
   296  	//
   297  	// The map value indicates whether to load tests.  If true, Load
   298  	// will add and type-check two lists of files to the package:
   299  	// non-test files followed by in-package *_test.go files.  In
   300  	// addition, it will append the external test package (if any)
   301  	// to Program.Created.
   302  	ImportPkgs map[string]bool
   303  
   304  	// FindPackage is called during Load to create the build.Package
   305  	// for a given import path.  If nil, a default implementation
   306  	// based on ctxt.Import is used.  A client may use this hook to
   307  	// adapt to a proprietary build system that does not follow the
   308  	// "go build" layout conventions, for example.
   309  	//
   310  	// It must be safe to call concurrently from multiple goroutines.
   311  	FindPackage func(ctxt *build.Context, importPath string) (*build.Package, error)
   312  
   313  	// PackageCreated is a hook called when a types.Package
   314  	// is created but before it has been populated.
   315  	//
   316  	// The package's import Path() and Scope() are defined,
   317  	// but not its Name() since no package declaration has
   318  	// been seen yet.
   319  	//
   320  	// Clients may use this to insert synthetic items into
   321  	// the package scope, for example.
   322  	//
   323  	// It must be safe to call concurrently from multiple goroutines.
   324  	PackageCreated func(*types.Package)
   325  }
   326  
   327  // A PkgSpec specifies a non-importable package to be created by Load.
   328  // Files are processed first, but typically only one of Files and
   329  // Filenames is provided.  The path needn't be globally unique.
   330  //
   331  type PkgSpec struct {
   332  	Path      string      // import path ("" => use package declaration)
   333  	Files     []*ast.File // ASTs of already-parsed files
   334  	Filenames []string    // names of files to be parsed
   335  }
   336  
   337  // A Program is a Go program loaded from source or binary
   338  // as specified by a Config.
   339  type Program struct {
   340  	Fset *token.FileSet // the file set for this program
   341  
   342  	// Created[i] contains the initial package whose ASTs or
   343  	// filenames were supplied by Config.CreatePkgs[i], followed by
   344  	// the external test package, if any, of each package in
   345  	// Config.ImportPkgs ordered by ImportPath.
   346  	Created []*PackageInfo
   347  
   348  	// Imported contains the initially imported packages,
   349  	// as specified by Config.ImportPkgs.
   350  	Imported map[string]*PackageInfo
   351  
   352  	// ImportMap is the canonical mapping of import paths to
   353  	// packages used by the type-checker (Config.TypeChecker.Packages).
   354  	// It contains all Imported initial packages, but not Created
   355  	// ones, and all imported dependencies.
   356  	ImportMap map[string]*types.Package
   357  
   358  	// AllPackages contains the PackageInfo of every package
   359  	// encountered by Load: all initial packages and all
   360  	// dependencies, including incomplete ones.
   361  	AllPackages map[*types.Package]*PackageInfo
   362  }
   363  
   364  // PackageInfo holds the ASTs and facts derived by the type-checker
   365  // for a single package.
   366  //
   367  // Not mutated once exposed via the API.
   368  //
   369  type PackageInfo struct {
   370  	Pkg                   *types.Package
   371  	Importable            bool        // true if 'import "Pkg.Path()"' would resolve to this
   372  	TransitivelyErrorFree bool        // true if Pkg and all its dependencies are free of errors
   373  	Files                 []*ast.File // syntax trees for the package's files
   374  	Errors                []error     // non-nil if the package had errors
   375  	types.Info                        // type-checker deductions.
   376  
   377  	checker   *types.Checker // transient type-checker state
   378  	errorFunc func(error)
   379  }
   380  
   381  func (info *PackageInfo) String() string { return info.Pkg.Path() }
   382  
   383  func (info *PackageInfo) appendError(err error) {
   384  	if info.errorFunc != nil {
   385  		info.errorFunc(err)
   386  	} else {
   387  		fmt.Fprintln(os.Stderr, err)
   388  	}
   389  	info.Errors = append(info.Errors, err)
   390  }
   391  
   392  func (conf *Config) fset() *token.FileSet {
   393  	if conf.Fset == nil {
   394  		conf.Fset = token.NewFileSet()
   395  	}
   396  	return conf.Fset
   397  }
   398  
   399  // ParseFile is a convenience function (intended for testing) that invokes
   400  // the parser using the Config's FileSet, which is initialized if nil.
   401  //
   402  // src specifies the parser input as a string, []byte, or io.Reader, and
   403  // filename is its apparent name.  If src is nil, the contents of
   404  // filename are read from the file system.
   405  //
   406  func (conf *Config) ParseFile(filename string, src interface{}) (*ast.File, error) {
   407  	// TODO(adonovan): use conf.build() etc like parseFiles does.
   408  	return parser.ParseFile(conf.fset(), filename, src, conf.ParserMode)
   409  }
   410  
   411  // FromArgsUsage is a partial usage message that applications calling
   412  // FromArgs may wish to include in their -help output.
   413  const FromArgsUsage = `
   414  <args> is a list of arguments denoting a set of initial packages.
   415  It may take one of two forms:
   416  
   417  1. A list of *.go source files.
   418  
   419     All of the specified files are loaded, parsed and type-checked
   420     as a single package.  All the files must belong to the same directory.
   421  
   422  2. A list of import paths, each denoting a package.
   423  
   424     The package's directory is found relative to the $GOROOT and
   425     $GOPATH using similar logic to 'go build', and the *.go files in
   426     that directory are loaded, parsed and type-checked as a single
   427     package.
   428  
   429     In addition, all *_test.go files in the directory are then loaded
   430     and parsed.  Those files whose package declaration equals that of
   431     the non-*_test.go files are included in the primary package.  Test
   432     files whose package declaration ends with "_test" are type-checked
   433     as another package, the 'external' test package, so that a single
   434     import path may denote two packages.  (Whether this behaviour is
   435     enabled is tool-specific, and may depend on additional flags.)
   436  
   437  A '--' argument terminates the list of packages.
   438  `
   439  
   440  // FromArgs interprets args as a set of initial packages to load from
   441  // source and updates the configuration.  It returns the list of
   442  // unconsumed arguments.
   443  //
   444  // It is intended for use in command-line interfaces that require a
   445  // set of initial packages to be specified; see FromArgsUsage message
   446  // for details.
   447  //
   448  // Only superficial errors are reported at this stage; errors dependent
   449  // on I/O are detected during Load.
   450  //
   451  func (conf *Config) FromArgs(args []string, xtest bool) ([]string, error) {
   452  	var rest []string
   453  	for i, arg := range args {
   454  		if arg == "--" {
   455  			rest = args[i+1:]
   456  			args = args[:i]
   457  			break // consume "--" and return the remaining args
   458  		}
   459  	}
   460  
   461  	if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
   462  		// Assume args is a list of a *.go files
   463  		// denoting a single ad-hoc package.
   464  		for _, arg := range args {
   465  			if !strings.HasSuffix(arg, ".go") {
   466  				return nil, fmt.Errorf("named files must be .go files: %s", arg)
   467  			}
   468  		}
   469  		conf.CreateFromFilenames("", args...)
   470  	} else {
   471  		// Assume args are directories each denoting a
   472  		// package and (perhaps) an external test, iff xtest.
   473  		for _, arg := range args {
   474  			if xtest {
   475  				conf.ImportWithTests(arg)
   476  			} else {
   477  				conf.Import(arg)
   478  			}
   479  		}
   480  	}
   481  
   482  	return rest, nil
   483  }
   484  
   485  // CreateFromFilenames is a convenience function that adds
   486  // a conf.CreatePkgs entry to create a package of the specified *.go
   487  // files.
   488  //
   489  func (conf *Config) CreateFromFilenames(path string, filenames ...string) {
   490  	conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Filenames: filenames})
   491  }
   492  
   493  // CreateFromFiles is a convenience function that adds a conf.CreatePkgs
   494  // entry to create package of the specified path and parsed files.
   495  //
   496  func (conf *Config) CreateFromFiles(path string, files ...*ast.File) {
   497  	conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Files: files})
   498  }
   499  
   500  // ImportWithTests is a convenience function that adds path to
   501  // ImportPkgs, the set of initial source packages located relative to
   502  // $GOPATH.  The package will be augmented by any *_test.go files in
   503  // its directory that contain a "package x" (not "package x_test")
   504  // declaration.
   505  //
   506  // In addition, if any *_test.go files contain a "package x_test"
   507  // declaration, an additional package comprising just those files will
   508  // be added to CreatePkgs.
   509  //
   510  func (conf *Config) ImportWithTests(path string) { conf.addImport(path, true) }
   511  
   512  // Import is a convenience function that adds path to ImportPkgs, the
   513  // set of initial packages that will be imported from source.
   514  //
   515  func (conf *Config) Import(path string) { conf.addImport(path, false) }
   516  
   517  func (conf *Config) addImport(path string, tests bool) {
   518  	if path == "unsafe" {
   519  		return // ignore; not a real package
   520  	}
   521  	if conf.ImportPkgs == nil {
   522  		conf.ImportPkgs = make(map[string]bool)
   523  	}
   524  	conf.ImportPkgs[path] = conf.ImportPkgs[path] || tests
   525  }
   526  
   527  // PathEnclosingInterval returns the PackageInfo and ast.Node that
   528  // contain source interval [start, end), and all the node's ancestors
   529  // up to the AST root.  It searches all ast.Files of all packages in prog.
   530  // exact is defined as for astutil.PathEnclosingInterval.
   531  //
   532  // The zero value is returned if not found.
   533  //
   534  func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {
   535  	for _, info := range prog.AllPackages {
   536  		for _, f := range info.Files {
   537  			if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) {
   538  				continue
   539  			}
   540  			if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {
   541  				return info, path, exact
   542  			}
   543  		}
   544  	}
   545  	return nil, nil, false
   546  }
   547  
   548  // InitialPackages returns a new slice containing the set of initial
   549  // packages (Created + Imported) in unspecified order.
   550  //
   551  func (prog *Program) InitialPackages() []*PackageInfo {
   552  	infos := make([]*PackageInfo, 0, len(prog.Created)+len(prog.Imported))
   553  	infos = append(infos, prog.Created...)
   554  	for _, info := range prog.Imported {
   555  		infos = append(infos, info)
   556  	}
   557  	return infos
   558  }
   559  
   560  // ---------- Implementation ----------
   561  
   562  // importer holds the working state of the algorithm.
   563  type importer struct {
   564  	conf  *Config   // the client configuration
   565  	prog  *Program  // resulting program
   566  	start time.Time // for logging
   567  
   568  	// This mutex serializes access to prog.ImportMap (aka
   569  	// TypeChecker.Packages); we also use it for AllPackages.
   570  	//
   571  	// The TypeChecker.Packages map is not really used by this
   572  	// package, but may be used by the client's Import function,
   573  	// and by clients of the returned Program.
   574  	typecheckerMu sync.Mutex
   575  
   576  	importedMu sync.Mutex
   577  	imported   map[string]*importInfo // all imported packages (incl. failures) by import path
   578  
   579  	// import dependency graph: graph[x][y] => x imports y
   580  	//
   581  	// Since non-importable packages cannot be cyclic, we ignore
   582  	// their imports, thus we only need the subgraph over importable
   583  	// packages.  Nodes are identified by their import paths.
   584  	graphMu sync.Mutex
   585  	graph   map[string]map[string]bool
   586  }
   587  
   588  // importInfo tracks the success or failure of a single import.
   589  //
   590  // Upon completion, exactly one of info and err is non-nil:
   591  // info on successful creation of a package, err otherwise.
   592  // A successful package may still contain type errors.
   593  //
   594  type importInfo struct {
   595  	path     string       // import path
   596  	mu       sync.Mutex   // guards the following fields prior to completion
   597  	info     *PackageInfo // results of typechecking (including errors)
   598  	err      error        // reason for failure to create a package
   599  	complete sync.Cond    // complete condition is that one of info, err is non-nil.
   600  }
   601  
   602  // awaitCompletion blocks until ii is complete,
   603  // i.e. the info and err fields are safe to inspect without a lock.
   604  // It is concurrency-safe and idempotent.
   605  func (ii *importInfo) awaitCompletion() {
   606  	ii.mu.Lock()
   607  	for ii.info == nil && ii.err == nil {
   608  		ii.complete.Wait()
   609  	}
   610  	ii.mu.Unlock()
   611  }
   612  
   613  // Complete marks ii as complete.
   614  // Its info and err fields will not be subsequently updated.
   615  func (ii *importInfo) Complete(info *PackageInfo, err error) {
   616  	ii.mu.Lock()
   617  	ii.info = info
   618  	ii.err = err
   619  	ii.complete.Broadcast()
   620  	ii.mu.Unlock()
   621  }
   622  
   623  // Load creates the initial packages specified by conf.{Create,Import}Pkgs,
   624  // loading their dependencies packages as needed.
   625  //
   626  // On success, Load returns a Program containing a PackageInfo for
   627  // each package.  On failure, it returns an error.
   628  //
   629  // If AllowErrors is true, Load will return a Program even if some
   630  // packages contained I/O, parser or type errors, or if dependencies
   631  // were missing.  (Such errors are accessible via PackageInfo.Errors.  If
   632  // false, Load will fail if any package had an error.
   633  //
   634  // It is an error if no packages were loaded.
   635  //
   636  func (conf *Config) Load() (*Program, error) {
   637  	// Initialize by setting the conf's copy, so all copies of
   638  	// TypeChecker agree on the identity of the map.
   639  	if conf.TypeChecker.Packages == nil {
   640  		conf.TypeChecker.Packages = make(map[string]*types.Package)
   641  	}
   642  
   643  	// Create a simple default error handler for parse/type errors.
   644  	if conf.TypeChecker.Error == nil {
   645  		conf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) }
   646  	}
   647  
   648  	// Set default working directory for relative package references.
   649  	if conf.Cwd == "" {
   650  		var err error
   651  		conf.Cwd, err = os.Getwd()
   652  		if err != nil {
   653  			return nil, err
   654  		}
   655  	}
   656  
   657  	// Install default FindPackage hook using go/build logic.
   658  	if conf.FindPackage == nil {
   659  		conf.FindPackage = func(ctxt *build.Context, path string) (*build.Package, error) {
   660  			bp, err := ctxt.Import(path, conf.Cwd, 0)
   661  			if _, ok := err.(*build.NoGoError); ok {
   662  				return bp, nil // empty directory is not an error
   663  			}
   664  			return bp, err
   665  		}
   666  	}
   667  
   668  	prog := &Program{
   669  		Fset:        conf.fset(),
   670  		Imported:    make(map[string]*PackageInfo),
   671  		ImportMap:   conf.TypeChecker.Packages,
   672  		AllPackages: make(map[*types.Package]*PackageInfo),
   673  	}
   674  
   675  	imp := importer{
   676  		conf:     conf,
   677  		prog:     prog,
   678  		imported: make(map[string]*importInfo),
   679  		start:    time.Now(),
   680  		graph:    make(map[string]map[string]bool),
   681  	}
   682  
   683  	// -- loading proper (concurrent phase) --------------------------------
   684  
   685  	var errpkgs []string // packages that contained errors
   686  
   687  	// Load the initially imported packages and their dependencies,
   688  	// in parallel.
   689  	for _, ii := range imp.loadAll("", conf.ImportPkgs) {
   690  		if ii.err != nil {
   691  			conf.TypeChecker.Error(ii.err) // failed to create package
   692  			errpkgs = append(errpkgs, ii.path)
   693  			continue
   694  		}
   695  		prog.Imported[ii.info.Pkg.Path()] = ii.info
   696  	}
   697  
   698  	// Augment the designated initial packages by their tests.
   699  	// Dependencies are loaded in parallel.
   700  	var xtestPkgs []*build.Package
   701  	for path, augment := range conf.ImportPkgs {
   702  		if !augment {
   703  			continue
   704  		}
   705  
   706  		bp, err := conf.FindPackage(conf.build(), path)
   707  		if err != nil {
   708  			// Package not found, or can't even parse package declaration.
   709  			// Already reported by previous loop; ignore it.
   710  			continue
   711  		}
   712  
   713  		// Needs external test package?
   714  		if len(bp.XTestGoFiles) > 0 {
   715  			xtestPkgs = append(xtestPkgs, bp)
   716  		}
   717  
   718  		imp.importedMu.Lock()           // (unnecessary, we're sequential here)
   719  		info := imp.imported[path].info // must be non-nil, see above
   720  		imp.importedMu.Unlock()
   721  
   722  		// Parse the in-package test files.
   723  		files, errs := imp.conf.parsePackageFiles(bp, 't')
   724  		for _, err := range errs {
   725  			info.appendError(err)
   726  		}
   727  
   728  		// The test files augmenting package P cannot be imported,
   729  		// but may import packages that import P,
   730  		// so we must disable the cycle check.
   731  		imp.addFiles(info, files, false)
   732  	}
   733  
   734  	createPkg := func(path string, files []*ast.File, errs []error) {
   735  		info := imp.newPackageInfo(path)
   736  		for _, err := range errs {
   737  			info.appendError(err)
   738  		}
   739  
   740  		// Ad-hoc packages are non-importable,
   741  		// so no cycle check is needed.
   742  		// addFiles loads dependencies in parallel.
   743  		imp.addFiles(info, files, false)
   744  		prog.Created = append(prog.Created, info)
   745  	}
   746  
   747  	// Create packages specified by conf.CreatePkgs.
   748  	for _, cp := range conf.CreatePkgs {
   749  		files, errs := parseFiles(conf.fset(), conf.build(), nil, ".", cp.Filenames, conf.ParserMode)
   750  		files = append(files, cp.Files...)
   751  
   752  		path := cp.Path
   753  		if path == "" {
   754  			if len(files) > 0 {
   755  				path = files[0].Name.Name
   756  			} else {
   757  				path = "(unnamed)"
   758  			}
   759  		}
   760  		createPkg(path, files, errs)
   761  	}
   762  
   763  	// Create external test packages.
   764  	sort.Sort(byImportPath(xtestPkgs))
   765  	for _, bp := range xtestPkgs {
   766  		files, errs := imp.conf.parsePackageFiles(bp, 'x')
   767  		createPkg(bp.ImportPath+"_test", files, errs)
   768  	}
   769  
   770  	// -- finishing up (sequential) ----------------------------------------
   771  
   772  	if len(prog.Imported)+len(prog.Created) == 0 {
   773  		return nil, errors.New("no initial packages were loaded")
   774  	}
   775  
   776  	// Create infos for indirectly imported packages.
   777  	// e.g. incomplete packages without syntax, loaded from export data.
   778  	for _, obj := range prog.ImportMap {
   779  		info := prog.AllPackages[obj]
   780  		if info == nil {
   781  			prog.AllPackages[obj] = &PackageInfo{Pkg: obj, Importable: true}
   782  		} else {
   783  			// finished
   784  			info.checker = nil
   785  			info.errorFunc = nil
   786  		}
   787  	}
   788  
   789  	if !conf.AllowErrors {
   790  		// Report errors in indirectly imported packages.
   791  		for _, info := range prog.AllPackages {
   792  			if len(info.Errors) > 0 {
   793  				errpkgs = append(errpkgs, info.Pkg.Path())
   794  			}
   795  		}
   796  		if errpkgs != nil {
   797  			var more string
   798  			if len(errpkgs) > 3 {
   799  				more = fmt.Sprintf(" and %d more", len(errpkgs)-3)
   800  				errpkgs = errpkgs[:3]
   801  			}
   802  			return nil, fmt.Errorf("couldn't load packages due to errors: %s%s",
   803  				strings.Join(errpkgs, ", "), more)
   804  		}
   805  	}
   806  
   807  	markErrorFreePackages(prog.AllPackages)
   808  
   809  	return prog, nil
   810  }
   811  
   812  type byImportPath []*build.Package
   813  
   814  func (b byImportPath) Len() int           { return len(b) }
   815  func (b byImportPath) Less(i, j int) bool { return b[i].ImportPath < b[j].ImportPath }
   816  func (b byImportPath) Swap(i, j int)      { b[i], b[j] = b[j], b[i] }
   817  
   818  // markErrorFreePackages sets the TransitivelyErrorFree flag on all
   819  // applicable packages.
   820  func markErrorFreePackages(allPackages map[*types.Package]*PackageInfo) {
   821  	// Build the transpose of the import graph.
   822  	importedBy := make(map[*types.Package]map[*types.Package]bool)
   823  	for P := range allPackages {
   824  		for _, Q := range P.Imports() {
   825  			clients, ok := importedBy[Q]
   826  			if !ok {
   827  				clients = make(map[*types.Package]bool)
   828  				importedBy[Q] = clients
   829  			}
   830  			clients[P] = true
   831  		}
   832  	}
   833  
   834  	// Find all packages reachable from some error package.
   835  	reachable := make(map[*types.Package]bool)
   836  	var visit func(*types.Package)
   837  	visit = func(p *types.Package) {
   838  		if !reachable[p] {
   839  			reachable[p] = true
   840  			for q := range importedBy[p] {
   841  				visit(q)
   842  			}
   843  		}
   844  	}
   845  	for _, info := range allPackages {
   846  		if len(info.Errors) > 0 {
   847  			visit(info.Pkg)
   848  		}
   849  	}
   850  
   851  	// Mark the others as "transitively error-free".
   852  	for _, info := range allPackages {
   853  		if !reachable[info.Pkg] {
   854  			info.TransitivelyErrorFree = true
   855  		}
   856  	}
   857  }
   858  
   859  // build returns the effective build context.
   860  func (conf *Config) build() *build.Context {
   861  	if conf.Build != nil {
   862  		return conf.Build
   863  	}
   864  	return &build.Default
   865  }
   866  
   867  // parsePackageFiles enumerates the files belonging to package path,
   868  // then loads, parses and returns them, plus a list of I/O or parse
   869  // errors that were encountered.
   870  //
   871  // 'which' indicates which files to include:
   872  //    'g': include non-test *.go source files (GoFiles + processed CgoFiles)
   873  //    't': include in-package *_test.go source files (TestGoFiles)
   874  //    'x': include external *_test.go source files. (XTestGoFiles)
   875  //
   876  func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {
   877  	var filenames []string
   878  	switch which {
   879  	case 'g':
   880  		filenames = bp.GoFiles
   881  	case 't':
   882  		filenames = bp.TestGoFiles
   883  	case 'x':
   884  		filenames = bp.XTestGoFiles
   885  	default:
   886  		panic(which)
   887  	}
   888  
   889  	files, errs := parseFiles(conf.fset(), conf.build(), conf.DisplayPath, bp.Dir, filenames, conf.ParserMode)
   890  
   891  	// Preprocess CgoFiles and parse the outputs (sequentially).
   892  	if which == 'g' && bp.CgoFiles != nil {
   893  		cgofiles, err := processCgoFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode)
   894  		if err != nil {
   895  			errs = append(errs, err)
   896  		} else {
   897  			files = append(files, cgofiles...)
   898  		}
   899  	}
   900  
   901  	return files, errs
   902  }
   903  
   904  // doImport imports the package denoted by path.
   905  // It implements the types.Importer signature.
   906  //
   907  // imports is the type-checker's package canonicalization map.
   908  //
   909  // It returns an error if a package could not be created
   910  // (e.g. go/build or parse error), but type errors are reported via
   911  // the types.Config.Error callback (the first of which is also saved
   912  // in the package's PackageInfo).
   913  //
   914  // Idempotent.
   915  //
   916  func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) {
   917  	// Package unsafe is handled specially, and has no PackageInfo.
   918  	// TODO(adonovan): move this check into go/types?
   919  	if to == "unsafe" {
   920  		return types.Unsafe, nil
   921  	}
   922  
   923  	imp.importedMu.Lock()
   924  	ii := imp.imported[to]
   925  	imp.importedMu.Unlock()
   926  	if ii == nil {
   927  		panic("internal error: unexpected import: " + to)
   928  	}
   929  	if ii.err != nil {
   930  		return nil, ii.err
   931  	}
   932  	if ii.info != nil {
   933  		return ii.info.Pkg, nil
   934  	}
   935  
   936  	// Import of incomplete package: this indicates a cycle.
   937  	fromPath := from.Pkg.Path()
   938  	if cycle := imp.findPath(to, fromPath); cycle != nil {
   939  		cycle = append([]string{fromPath}, cycle...)
   940  		return nil, fmt.Errorf("import cycle: %s", strings.Join(cycle, " -> "))
   941  	}
   942  
   943  	panic("internal error: import of incomplete (yet acyclic) package: " + fromPath)
   944  }
   945  
   946  // loadAll loads, parses, and type-checks the specified packages in
   947  // parallel and returns their completed importInfos in unspecified order.
   948  //
   949  // fromPath is the import path of the importing package, if it is
   950  // importable, "" otherwise.  It is used for cycle detection.
   951  //
   952  func (imp *importer) loadAll(fromPath string, paths map[string]bool) []*importInfo {
   953  	result := make([]*importInfo, 0, len(paths))
   954  	for path := range paths {
   955  		result = append(result, imp.startLoad(path))
   956  	}
   957  
   958  	if fromPath != "" {
   959  		// We're loading a set of imports.
   960  		//
   961  		// We must record graph edges from the importing package
   962  		// to its dependencies, and check for cycles.
   963  		imp.graphMu.Lock()
   964  		deps, ok := imp.graph[fromPath]
   965  		if !ok {
   966  			deps = make(map[string]bool)
   967  			imp.graph[fromPath] = deps
   968  		}
   969  		for path := range paths {
   970  			deps[path] = true
   971  		}
   972  		imp.graphMu.Unlock()
   973  	}
   974  
   975  	for _, ii := range result {
   976  		if fromPath != "" {
   977  			if cycle := imp.findPath(ii.path, fromPath); cycle != nil {
   978  				// Cycle-forming import: we must not await its
   979  				// completion since it would deadlock.
   980  				//
   981  				// We don't record the error in ii since
   982  				// the error is really associated with the
   983  				// cycle-forming edge, not the package itself.
   984  				// (Also it would complicate the
   985  				// invariants of importPath completion.)
   986  				if trace {
   987  					fmt.Fprintln(os.Stderr, "import cycle: %q", cycle)
   988  				}
   989  				continue
   990  			}
   991  		}
   992  		ii.awaitCompletion()
   993  
   994  	}
   995  	return result
   996  }
   997  
   998  // findPath returns an arbitrary path from 'from' to 'to' in the import
   999  // graph, or nil if there was none.
  1000  func (imp *importer) findPath(from, to string) []string {
  1001  	imp.graphMu.Lock()
  1002  	defer imp.graphMu.Unlock()
  1003  
  1004  	seen := make(map[string]bool)
  1005  	var search func(stack []string, importPath string) []string
  1006  	search = func(stack []string, importPath string) []string {
  1007  		if !seen[importPath] {
  1008  			seen[importPath] = true
  1009  			stack = append(stack, importPath)
  1010  			if importPath == to {
  1011  				return stack
  1012  			}
  1013  			for x := range imp.graph[importPath] {
  1014  				if p := search(stack, x); p != nil {
  1015  					return p
  1016  				}
  1017  			}
  1018  		}
  1019  		return nil
  1020  	}
  1021  	return search(make([]string, 0, 20), from)
  1022  }
  1023  
  1024  // startLoad initiates the loading, parsing and type-checking of the
  1025  // specified package and its dependencies, if it has not already begun.
  1026  //
  1027  // It returns an importInfo, not necessarily in a completed state.  The
  1028  // caller must call awaitCompletion() before accessing its info and err
  1029  // fields.
  1030  //
  1031  // startLoad is concurrency-safe and idempotent.
  1032  //
  1033  // Precondition: path != "unsafe".
  1034  //
  1035  func (imp *importer) startLoad(path string) *importInfo {
  1036  	imp.importedMu.Lock()
  1037  	ii, ok := imp.imported[path]
  1038  	if !ok {
  1039  		ii = &importInfo{path: path}
  1040  		ii.complete.L = &ii.mu
  1041  		imp.imported[path] = ii
  1042  
  1043  		go imp.load(path, ii)
  1044  	}
  1045  	imp.importedMu.Unlock()
  1046  
  1047  	return ii
  1048  }
  1049  
  1050  func (imp *importer) load(path string, ii *importInfo) {
  1051  	var info *PackageInfo
  1052  	var err error
  1053  	// Find and create the actual package.
  1054  	if _, ok := imp.conf.ImportPkgs[path]; ok || !imp.conf.ImportFromBinary {
  1055  		info, err = imp.loadFromSource(path)
  1056  	} else {
  1057  		info, err = imp.importFromBinary(path)
  1058  	}
  1059  	ii.Complete(info, err)
  1060  }
  1061  
  1062  // importFromBinary implements package loading from the client-supplied
  1063  // external source, e.g. object files from the gc compiler.
  1064  //
  1065  func (imp *importer) importFromBinary(path string) (*PackageInfo, error) {
  1066  	// Determine the caller's effective Import function.
  1067  	importfn := imp.conf.TypeChecker.Import
  1068  	if importfn == nil {
  1069  		importfn = gcimporter.Import
  1070  	}
  1071  	imp.typecheckerMu.Lock()
  1072  	pkg, err := importfn(imp.conf.TypeChecker.Packages, path)
  1073  	if pkg != nil {
  1074  		imp.conf.TypeChecker.Packages[path] = pkg
  1075  	}
  1076  	imp.typecheckerMu.Unlock()
  1077  	if err != nil {
  1078  		return nil, err
  1079  	}
  1080  	info := &PackageInfo{Pkg: pkg}
  1081  	info.Importable = true
  1082  	imp.typecheckerMu.Lock()
  1083  	imp.prog.AllPackages[pkg] = info
  1084  	imp.typecheckerMu.Unlock()
  1085  	return info, nil
  1086  }
  1087  
  1088  // loadFromSource implements package loading by parsing Go source files
  1089  // located by go/build.
  1090  // The returned PackageInfo's typeCheck function must be called.
  1091  //
  1092  func (imp *importer) loadFromSource(path string) (*PackageInfo, error) {
  1093  	bp, err := imp.conf.FindPackage(imp.conf.build(), path)
  1094  	if err != nil {
  1095  		return nil, err // package not found
  1096  	}
  1097  	info := imp.newPackageInfo(bp.ImportPath)
  1098  	info.Importable = true
  1099  	files, errs := imp.conf.parsePackageFiles(bp, 'g')
  1100  	for _, err := range errs {
  1101  		info.appendError(err)
  1102  	}
  1103  
  1104  	imp.addFiles(info, files, true)
  1105  
  1106  	imp.typecheckerMu.Lock()
  1107  	imp.conf.TypeChecker.Packages[path] = info.Pkg
  1108  	imp.typecheckerMu.Unlock()
  1109  
  1110  	return info, nil
  1111  }
  1112  
  1113  // addFiles adds and type-checks the specified files to info, loading
  1114  // their dependencies if needed.  The order of files determines the
  1115  // package initialization order.  It may be called multiple times on the
  1116  // same package.  Errors are appended to the info.Errors field.
  1117  //
  1118  // cycleCheck determines whether the imports within files create
  1119  // dependency edges that should be checked for potential cycles.
  1120  //
  1121  func (imp *importer) addFiles(info *PackageInfo, files []*ast.File, cycleCheck bool) {
  1122  	info.Files = append(info.Files, files...)
  1123  
  1124  	// Ensure the dependencies are loaded, in parallel.
  1125  	var fromPath string
  1126  	if cycleCheck {
  1127  		fromPath = info.Pkg.Path()
  1128  	}
  1129  	imp.loadAll(fromPath, scanImports(files))
  1130  
  1131  	if trace {
  1132  		fmt.Fprintf(os.Stderr, "%s: start %q (%d)\n",
  1133  			time.Since(imp.start), info.Pkg.Path(), len(files))
  1134  	}
  1135  
  1136  	// Ignore the returned (first) error since we
  1137  	// already collect them all in the PackageInfo.
  1138  	info.checker.Files(files)
  1139  
  1140  	if trace {
  1141  		fmt.Fprintf(os.Stderr, "%s: stop %q\n",
  1142  			time.Since(imp.start), info.Pkg.Path())
  1143  	}
  1144  }
  1145  
  1146  func (imp *importer) newPackageInfo(path string) *PackageInfo {
  1147  	pkg := types.NewPackage(path, "")
  1148  	if imp.conf.PackageCreated != nil {
  1149  		imp.conf.PackageCreated(pkg)
  1150  	}
  1151  	info := &PackageInfo{
  1152  		Pkg: pkg,
  1153  		Info: types.Info{
  1154  			Types:      make(map[ast.Expr]types.TypeAndValue),
  1155  			Defs:       make(map[*ast.Ident]types.Object),
  1156  			Uses:       make(map[*ast.Ident]types.Object),
  1157  			Implicits:  make(map[ast.Node]types.Object),
  1158  			Scopes:     make(map[ast.Node]*types.Scope),
  1159  			Selections: make(map[*ast.SelectorExpr]*types.Selection),
  1160  		},
  1161  		errorFunc: imp.conf.TypeChecker.Error,
  1162  	}
  1163  
  1164  	// Copy the types.Config so we can vary it across PackageInfos.
  1165  	tc := imp.conf.TypeChecker
  1166  	tc.IgnoreFuncBodies = false
  1167  	if f := imp.conf.TypeCheckFuncBodies; f != nil {
  1168  		tc.IgnoreFuncBodies = !f(path)
  1169  	}
  1170  	tc.Import = func(_ map[string]*types.Package, to string) (*types.Package, error) {
  1171  		return imp.doImport(info, to)
  1172  	}
  1173  	tc.Error = info.appendError // appendError wraps the user's Error function
  1174  
  1175  	info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info)
  1176  	imp.typecheckerMu.Lock()
  1177  	imp.prog.AllPackages[pkg] = info
  1178  	imp.typecheckerMu.Unlock()
  1179  	return info
  1180  }