Skip to content

Commit

Permalink
gopls/internal/lsp/source: use metadata files for workspace symbols
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
findleyr committed Feb 16, 2023
1 parent ad4fc28 commit e5b9948
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 20 deletions.
40 changes: 26 additions & 14 deletions gopls/internal/lsp/cache/snapshot.go
Expand Up @@ -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
Expand All @@ -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
})
Expand All @@ -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) {
Expand Down
10 changes: 7 additions & 3 deletions gopls/internal/lsp/cache/symbols.go
Expand Up @@ -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)
Expand All @@ -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{} {
Expand Down
2 changes: 1 addition & 1 deletion gopls/internal/lsp/source/view.go
Expand Up @@ -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.
Expand Down
7 changes: 5 additions & 2 deletions gopls/internal/lsp/source/workspace_symbol.go
Expand Up @@ -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
Expand All @@ -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) {
Expand Down

0 comments on commit e5b9948

Please sign in to comment.