aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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) {