1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:54:43 -07:00

go/loader: resolve imports in "created" packages w.r.t. parent dir not cwd

Fixes golang/go#16580

Change-Id: Id891f40659257eac9dbb0d70dae17f725e911f9b
Reviewed-on: https://go-review.googlesource.com/33589
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Alan Donovan 2016-11-28 16:48:17 -05:00
parent c060f04f93
commit 6c803ab014
2 changed files with 68 additions and 5 deletions

View File

@ -17,6 +17,7 @@ import (
"go/token"
"go/types"
"os"
"path/filepath"
"sort"
"strings"
"sync"
@ -132,6 +133,8 @@ type Config struct {
// 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
@ -586,9 +589,8 @@ func (conf *Config) Load() (*Program, error) {
imp.addFiles(info, files, false)
}
createPkg := func(path string, files []*ast.File, errs []error) {
// TODO(adonovan): fix: use dirname of files, not cwd.
info := imp.newPackageInfo(path, conf.Cwd)
createPkg := func(path, dir string, files []*ast.File, errs []error) {
info := imp.newPackageInfo(path, dir)
for _, err := range errs {
info.appendError(err)
}
@ -613,14 +615,19 @@ func (conf *Config) Load() (*Program, error) {
path = "(unnamed)"
}
}
createPkg(path, files, errs)
dir := "."
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", files, errs)
createPkg(bp.ImportPath+"_test", bp.Dir, files, errs)
}
// -- finishing up (sequential) ----------------------------------------

View File

@ -13,6 +13,8 @@ package loader_test
import (
"fmt"
"go/build"
"go/constant"
"go/types"
"path/filepath"
"reflect"
"sort"
@ -477,6 +479,60 @@ func TestVendorCwd(t *testing.T) {
}
}
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: