gopls/internal/lsp/source: use PackageFromFile in Identifier
When searching for declaration information about a position, it should
suffice to search the narrowest fully type-checked package containing
the file.
This should significantly improve performance when there are many test
variants of the current package, that have not yet been type-checked in
the ParseFull mode (as reported in golang/go#55293).
For golang/go#55293
Change-Id: I89a1999f9fe82dea51dd47db769c90b69be5e454
Reviewed-on: https://go-review.googlesource.com/c/tools/+/438496
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
diff --git a/gopls/internal/lsp/source/identifier.go b/gopls/internal/lsp/source/identifier.go
index 7e856b5..91c7b6b 100644
--- a/gopls/internal/lsp/source/identifier.go
+++ b/gopls/internal/lsp/source/identifier.go
@@ -12,7 +12,6 @@
"go/parser"
"go/token"
"go/types"
- "sort"
"strconv"
"golang.org/x/tools/go/ast/astutil"
@@ -81,42 +80,22 @@
ctx, done := event.Start(ctx, "source.Identifier")
defer done()
- // TODO(rfindley): Why isn't this PackageForFile? A single package should
- // suffice to find identifier info.
- pkgs, err := snapshot.PackagesForFile(ctx, fh.URI(), TypecheckAll, false)
+ pkg, err := snapshot.PackageForFile(ctx, fh.URI(), TypecheckFull, NarrowestPackage)
if err != nil {
return nil, err
}
- if len(pkgs) == 0 {
- return nil, fmt.Errorf("no packages for file %v", fh.URI())
+ pgf, err := pkg.File(fh.URI())
+ if err != nil {
+ // We shouldn't get a package from PackagesForFile that doesn't actually
+ // contain the file.
+ bug.Report("missing package file", bug.Data{"pkg": pkg.ID(), "file": fh.URI()})
+ return nil, err
}
- sort.Slice(pkgs, func(i, j int) bool {
- // Prefer packages with a more complete parse mode.
- if pkgs[i].ParseMode() != pkgs[j].ParseMode() {
- return pkgs[i].ParseMode() > pkgs[j].ParseMode()
- }
- return len(pkgs[i].CompiledGoFiles()) < len(pkgs[j].CompiledGoFiles())
- })
- var findErr error
- for _, pkg := range pkgs {
- pgf, err := pkg.File(fh.URI())
- if err != nil {
- // We shouldn't get a package from PackagesForFile that doesn't actually
- // contain the file.
- bug.Report("missing package file", bug.Data{"pkg": pkg.ID(), "file": fh.URI()})
- return nil, err
- }
- pos, err := pgf.Mapper.Pos(position)
- if err != nil {
- return nil, err
- }
- var ident *IdentifierInfo
- ident, findErr = findIdentifier(ctx, snapshot, pkg, pgf, pos)
- if findErr == nil {
- return ident, nil
- }
+ pos, err := pgf.Mapper.Pos(position)
+ if err != nil {
+ return nil, err
}
- return nil, findErr
+ return findIdentifier(ctx, snapshot, pkg, pgf, pos)
}
// ErrNoIdentFound is error returned when no identifier is found at a particular position