diff options
author | Robert Findley <rfindley@google.com> | 2023-02-15 22:26:54 -0500 |
---|---|---|
committer | Robert Findley <rfindley@google.com> | 2023-02-16 19:20:28 +0000 |
commit | e5b9948177182e5083e76b4a18cb01b37640b8f4 (patch) | |
tree | 4e9b1084f83dc446edc55b0a7217ed625a6ab179 | |
parent | ad4fc28a4696a54c1b9f08de1ca944cb9c180471 (diff) | |
download | golang-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.go | 40 | ||||
-rw-r--r-- | gopls/internal/lsp/cache/symbols.go | 10 | ||||
-rw-r--r-- | gopls/internal/lsp/source/view.go | 2 | ||||
-rw-r--r-- | gopls/internal/lsp/source/workspace_symbol.go | 7 |
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) { |