Skip to content

Commit

Permalink
internal/lsp/cache: fix GOPATH vendoring
Browse files Browse the repository at this point in the history
We treat package IDs and import paths as semi-interchangeable, which is
wrong when GOPATH vendoring is in use. The only place it hurts us is
during import resolution, which is fixed here. We should always have the
package loaded, so it's just a matter of finding it by searching each
possible vendor location.

Fixes golang/go#36155.

Change-Id: If789092d16fa3d3294b6d8a2bcb980264506c161
Reviewed-on: https://go-review.googlesource.com/c/tools/+/215904
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
  • Loading branch information
heschi committed Jan 24, 2020
1 parent ce9bf56 commit 5ecc164
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
19 changes: 19 additions & 0 deletions internal/lsp/cache/check.go
Expand Up @@ -11,6 +11,7 @@ import (
"go/ast"
"go/token"
"go/types"
"path"
"sort"
"sync"

Expand Down Expand Up @@ -309,6 +310,24 @@ func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode sourc
},
Importer: importerFunc(func(pkgPath string) (*types.Package, error) {
dep := deps[packagePath(pkgPath)]
if dep == nil {
// We may be in GOPATH mode, in which case we need to check vendor dirs.
searchDir := path.Dir(pkg.PkgPath())
for {
vdir := packagePath(path.Join(searchDir, "vendor", pkgPath))
if vdep := deps[vdir]; vdep != nil {
dep = vdep
break
}

// Search until Dir doesn't take us anywhere new, e.g. "." or "/".
next := path.Dir(searchDir)
if searchDir == next {
break
}
searchDir = next
}
}
if dep == nil {
return nil, errors.Errorf("no package for import %s", pkgPath)
}
Expand Down
5 changes: 5 additions & 0 deletions internal/lsp/cache/load.go
Expand Up @@ -42,6 +42,9 @@ func (s *snapshot) load(ctx context.Context, scopes ...interface{}) ([]*metadata
for _, scope := range scopes {
switch scope := scope.(type) {
case []packagePath:
// The only time we pass package paths is when we're doing a
// partial workspace load. In those cases, the paths came back from
// go list and should already be GOPATH-vendorized when appropriate.
for _, p := range scope {
query = append(query, string(p))
}
Expand All @@ -59,6 +62,8 @@ func (s *snapshot) load(ctx context.Context, scopes ...interface{}) ([]*metadata
q = "./..."
}
query = append(query, q)
default:
panic(fmt.Sprintf("unknown scope type %T", scope))
}
}
ctx, done := trace.StartSpan(ctx, "cache.view.load", telemetry.Query.Of(query))
Expand Down

0 comments on commit 5ecc164

Please sign in to comment.