diff options
-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) { |