mirror of
https://github.com/golang/go
synced 2024-11-18 16:54:43 -07:00
go/loader: support relative imports like the go tool does
Config.Cwd sets the base directory; os.Getwd is its default. +Test. Change-Id: I213abfb30085cd1306719ed6f94aeae6a3170bc0 Reviewed-on: https://go-review.googlesource.com/7502 Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
bf80246757
commit
8cc1c75580
@ -268,6 +268,11 @@ type Config struct {
|
||||
// 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
|
||||
@ -640,8 +645,24 @@ func (conf *Config) Load() (*Program, error) {
|
||||
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 = defaultFindPackage
|
||||
conf.FindPackage = func(ctxt *build.Context, path string) (*build.Package, error) {
|
||||
bp, err := ctxt.Import(path, conf.Cwd, 0)
|
||||
if _, ok := err.(*build.NoGoError); ok {
|
||||
return bp, nil // empty directory is not an error
|
||||
}
|
||||
return bp, err
|
||||
}
|
||||
}
|
||||
|
||||
prog := &Program{
|
||||
@ -843,17 +864,6 @@ func (conf *Config) build() *build.Context {
|
||||
return &build.Default
|
||||
}
|
||||
|
||||
// defaultFindPackage locates the specified (possibly empty) package
|
||||
// using go/build logic. It returns an error if not found.
|
||||
func defaultFindPackage(ctxt *build.Context, path string) (*build.Package, error) {
|
||||
// Import(srcDir="") disables local imports, e.g. import "./foo".
|
||||
bp, err := ctxt.Import(path, "", 0)
|
||||
if _, ok := err.(*build.NoGoError); ok {
|
||||
return bp, nil // empty directory is not an error
|
||||
}
|
||||
return bp, err
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -1084,7 +1094,7 @@ func (imp *importer) loadFromSource(path string) (*PackageInfo, error) {
|
||||
if err != nil {
|
||||
return nil, err // package not found
|
||||
}
|
||||
info := imp.newPackageInfo(path)
|
||||
info := imp.newPackageInfo(bp.ImportPath)
|
||||
info.Importable = true
|
||||
files, errs := imp.conf.parsePackageFiles(bp, 'g')
|
||||
for _, err := range errs {
|
||||
|
@ -356,6 +356,38 @@ func TestLoad_BadDependency_AllowErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(adonovan): more Load tests:
|
||||
//
|
||||
// failures:
|
||||
|
Loading…
Reference in New Issue
Block a user