go/loader: define a FindPackage hook for build systems not compatible with "go build".

Google's proprietary build system, for example, does not use the
_test.go suffix to distinguish test from non-test files; this
information is stated explicitly in another form.

Change-Id: I3a8e919dbc556b6d5cfea1d2123da2616bd934d4
Reviewed-on: https://go-review.googlesource.com/5450
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Alan Donovan 2015-02-20 11:23:27 -05:00
parent f96426939c
commit 51931f86bf
1 changed files with 18 additions and 6 deletions

View File

@ -290,6 +290,15 @@ type Config struct {
// to Program.Created.
ImportPkgs map[string]bool
// FindPackage is called during Load to create the build.Package
// for a given import path. If nil, a default implementation
// based on ctxt.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 string) (*build.Package, error)
// PackageCreated is a hook called when a types.Package
// is created but before it has been populated.
//
@ -625,6 +634,10 @@ func (conf *Config) Load() (*Program, error) {
conf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) }
}
if conf.FindPackage == nil {
conf.FindPackage = defaultFindPackage
}
prog := &Program{
Fset: conf.fset(),
Imported: make(map[string]*PackageInfo),
@ -663,7 +676,7 @@ func (conf *Config) Load() (*Program, error) {
continue
}
bp, err := conf.findSourcePackage(path)
bp, err := conf.FindPackage(conf.build(), path)
if err != nil {
// Package not found, or can't even parse package declaration.
// Already reported by previous loop; ignore it.
@ -820,12 +833,11 @@ func (conf *Config) build() *build.Context {
return &build.Default
}
// findSourcePackage locates the specified (possibly empty) package
// defaultFindPackage locates the specified (possibly empty) package
// using go/build logic. It returns an error if not found.
//
func (conf *Config) findSourcePackage(path string) (*build.Package, error) {
func defaultFindPackage(ctxt *build.Context, path string) (*build.Package, error) {
// Import(srcDir="") disables local imports, e.g. import "./foo".
bp, err := conf.build().Import(path, "", 0)
bp, err := ctxt.Import(path, "", 0)
if _, ok := err.(*build.NoGoError); ok {
return bp, nil // empty directory is not an error
}
@ -1058,7 +1070,7 @@ func (imp *importer) importFromBinary(path string) (*PackageInfo, error) {
// The returned PackageInfo's typeCheck function must be called.
//
func (imp *importer) loadFromSource(path string) (*PackageInfo, error) {
bp, err := imp.conf.findSourcePackage(path)
bp, err := imp.conf.FindPackage(imp.conf.build(), path)
if err != nil {
return nil, err // package not found
}