aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Findley <rfindley@google.com>2023-02-15 22:26:54 -0500
committerRobert Findley <rfindley@google.com>2023-02-16 19:20:28 +0000
commite5b9948177182e5083e76b4a18cb01b37640b8f4 (patch)
tree4e9b1084f83dc446edc55b0a7217ed625a6ab179
parentad4fc28a4696a54c1b9f08de1ca944cb9c180471 (diff)
downloadgolang-x-tools-e5b9948177182e5083e76b4a18cb01b37640b8f4.tar.gz
gopls/internal/lsp/source: use metadata files for workspace symbols
The workspace symbol handler was walking the files map ("seen files") rather than the package graph. In golang/go#57558, we endeavor to avoid any dependency on seen files, and pragmatically we will soon no longer read the entire workspace during loading. For golang/go#57558 Change-Id: Ie95a333842af24ab801bb3e314f5c00e1e5e1b0b Reviewed-on: https://go-review.googlesource.com/c/tools/+/468775 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>
-rw-r--r--gopls/internal/lsp/cache/snapshot.go40
-rw-r--r--gopls/internal/lsp/cache/symbols.go10
-rw-r--r--gopls/internal/lsp/source/view.go2
-rw-r--r--gopls/internal/lsp/source/workspace_symbol.go7
4 files changed, 39 insertions, 20 deletions
diff --git a/gopls/internal/lsp/cache/snapshot.go b/gopls/internal/lsp/cache/snapshot.go
index dd18018ab..ab4255655 100644
--- a/gopls/internal/lsp/cache/snapshot.go
+++ b/gopls/internal/lsp/cache/snapshot.go
@@ -1022,18 +1022,30 @@ func (s *snapshot) ActiveMetadata(ctx context.Context) ([]*source.Metadata, erro
return active, nil
}
-// Symbols extracts and returns the symbols for each file in all the snapshot's views.
-func (s *snapshot) Symbols(ctx context.Context) map[span.URI][]source.Symbol {
- // Read the set of Go files out of the snapshot.
- var goFiles []source.FileHandle
+// Symbols extracts and returns symbol information for every file contained in
+// a loaded package. It awaits snapshot loading.
+//
+// TODO(rfindley): move this to the top of cache/symbols.go
+func (s *snapshot) Symbols(ctx context.Context) (map[span.URI][]source.Symbol, error) {
+ if err := s.awaitLoaded(ctx); err != nil {
+ return nil, err
+ }
+
+ // Build symbols for all loaded Go files.
s.mu.Lock()
- s.files.Range(func(uri span.URI, f source.FileHandle) {
- if s.View().FileKind(f) == source.Go {
- goFiles = append(goFiles, f)
- }
- })
+ meta := s.meta
s.mu.Unlock()
+ goFiles := make(map[span.URI]struct{})
+ for _, m := range meta.metadata {
+ for _, uri := range m.GoFiles {
+ goFiles[uri] = struct{}{}
+ }
+ for _, uri := range m.CompiledGoFiles {
+ goFiles[uri] = struct{}{}
+ }
+ }
+
// Symbolize them in parallel.
var (
group errgroup.Group
@@ -1042,15 +1054,15 @@ func (s *snapshot) Symbols(ctx context.Context) map[span.URI][]source.Symbol {
result = make(map[span.URI][]source.Symbol)
)
group.SetLimit(nprocs)
- for _, f := range goFiles {
- f := f
+ for uri := range goFiles {
+ uri := uri
group.Go(func() error {
- symbols, err := s.symbolize(ctx, f)
+ symbols, err := s.symbolize(ctx, uri)
if err != nil {
return err
}
resultMu.Lock()
- result[f.URI()] = symbols
+ result[uri] = symbols
resultMu.Unlock()
return nil
})
@@ -1060,7 +1072,7 @@ func (s *snapshot) Symbols(ctx context.Context) map[span.URI][]source.Symbol {
if err := group.Wait(); err != nil {
event.Error(ctx, "getting snapshot symbols", err)
}
- return result
+ return result, nil
}
func (s *snapshot) AllMetadata(ctx context.Context) ([]*source.Metadata, error) {
diff --git a/gopls/internal/lsp/cache/symbols.go b/gopls/internal/lsp/cache/symbols.go
index 8cdb147a9..7fa3584d5 100644
--- a/gopls/internal/lsp/cache/symbols.go
+++ b/gopls/internal/lsp/cache/symbols.go
@@ -14,12 +14,12 @@ import (
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
+ "golang.org/x/tools/gopls/internal/span"
"golang.org/x/tools/internal/memoize"
)
-// symbolize returns the result of symbolizing the file identified by fh, using a cache.
-func (s *snapshot) symbolize(ctx context.Context, fh source.FileHandle) ([]source.Symbol, error) {
- uri := fh.URI()
+// symbolize returns the result of symbolizing the file identified by uri, using a cache.
+func (s *snapshot) symbolize(ctx context.Context, uri span.URI) ([]source.Symbol, error) {
s.mu.Lock()
entry, hit := s.symbolizeHandles.Get(uri)
@@ -32,6 +32,10 @@ func (s *snapshot) symbolize(ctx context.Context, fh source.FileHandle) ([]sourc
// Cache miss?
if !hit {
+ fh, err := s.GetFile(ctx, uri)
+ if err != nil {
+ return nil, err
+ }
type symbolHandleKey source.Hash
key := symbolHandleKey(fh.FileIdentity().Hash)
promise, release := s.store.Promise(key, func(_ context.Context, arg interface{}) interface{} {
diff --git a/gopls/internal/lsp/source/view.go b/gopls/internal/lsp/source/view.go
index 172a4fb27..1bfca022a 100644
--- a/gopls/internal/lsp/source/view.go
+++ b/gopls/internal/lsp/source/view.go
@@ -175,7 +175,7 @@ type Snapshot interface {
AllMetadata(ctx context.Context) ([]*Metadata, error)
// Symbols returns all symbols in the snapshot.
- Symbols(ctx context.Context) map[span.URI][]Symbol
+ Symbols(ctx context.Context) (map[span.URI][]Symbol, error)
// Metadata returns the metadata for the specified package,
// or nil if it was not found.
diff --git a/gopls/internal/lsp/source/workspace_symbol.go b/gopls/internal/lsp/source/workspace_symbol.go
index 1b157c6a5..17c3a24fb 100644
--- a/gopls/internal/lsp/source/workspace_symbol.go
+++ b/gopls/internal/lsp/source/workspace_symbol.go
@@ -298,7 +298,6 @@ func (c comboMatcher) match(chunks []string) (int, float64) {
// - A symbolizer determines how we extract the symbol for an object. This
// enables the 'symbolStyle' configuration option.
func collectSymbols(ctx context.Context, views []View, matcherType SymbolMatcher, symbolizer symbolizer, query string) ([]protocol.SymbolInformation, error) {
-
// Extract symbols from all files.
var work []symbolFile
var roots []string
@@ -318,7 +317,11 @@ func collectSymbols(ctx context.Context, views []View, matcherType SymbolMatcher
filters := v.Options().DirectoryFilters
filterer := NewFilterer(filters)
folder := filepath.ToSlash(v.Folder().Filename())
- for uri, syms := range snapshot.Symbols(ctx) {
+ symbols, err := snapshot.Symbols(ctx)
+ if err != nil {
+ return nil, err
+ }
+ for uri, syms := range symbols {
norm := filepath.ToSlash(uri.Filename())
nm := strings.TrimPrefix(norm, folder)
if filterer.Disallow(nm) {