diff --git a/internal/lsp/cache/check.go b/internal/lsp/cache/check.go index fe9a0faed8..b75954551a 100644 --- a/internal/lsp/cache/check.go +++ b/internal/lsp/cache/check.go @@ -221,7 +221,7 @@ func (ph *packageHandle) cached() (*pkg, error) { func (s *snapshot) parseGoHandles(ctx context.Context, files []span.URI, mode source.ParseMode) ([]source.ParseGoHandle, error) { phs := make([]source.ParseGoHandle, 0, len(files)) for _, uri := range files { - fh, err := s.GetFile(ctx, uri) + fh, err := s.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/cache/errors.go b/internal/lsp/cache/errors.go index 7b0f07682f..9be9809253 100644 --- a/internal/lsp/cache/errors.go +++ b/internal/lsp/cache/errors.go @@ -247,6 +247,27 @@ func spanToRange(ctx context.Context, pkg *pkg, spn span.Span) (protocol.Range, return m.Range(spn) } +func findFileInPackage(pkg source.Package, uri span.URI) (source.ParseGoHandle, source.Package, error) { + queue := []source.Package{pkg} + seen := make(map[string]bool) + + for len(queue) > 0 { + pkg := queue[0] + queue = queue[1:] + seen[pkg.ID()] = true + + if f, err := pkg.File(uri); err == nil { + return f, pkg, nil + } + for _, dep := range pkg.Imports() { + if !seen[dep.ID()] { + queue = append(queue, dep) + } + } + } + return nil, nil, errors.Errorf("no file for %s in package %s", uri, pkg.ID()) +} + // parseGoListError attempts to parse a standard `go list` error message // by stripping off the trailing error message. // diff --git a/internal/lsp/cache/session.go b/internal/lsp/cache/session.go index 863e844132..6b4be1c5c3 100644 --- a/internal/lsp/cache/session.go +++ b/internal/lsp/cache/session.go @@ -273,7 +273,7 @@ func (s *session) DidModifyFile(ctx context.Context, c source.FileModification) return nil, errors.Errorf("ignored file %v", c.URI) } // Make sure to add the file to the view. - if _, err := view.getFileLocked(ctx, c.URI); err != nil { + if _, err := view.getFileLocked(c.URI); err != nil { return nil, err } snapshots = append(snapshots, view.invalidateContent(ctx, c.URI, kind, c.Action)) @@ -303,7 +303,7 @@ func (s *session) DidChangeOutOfBand(ctx context.Context, uri span.URI, action s return false } // Make sure that the file is part of the view. - if _, err := view.getFileLocked(ctx, uri); err != nil { + if _, err := view.getFileLocked(uri); err != nil { return false } // TODO(golang/go#31553): Remove this when this issue has been resolved. diff --git a/internal/lsp/cache/snapshot.go b/internal/lsp/cache/snapshot.go index c1f13d9c13..8a5dd2ac67 100644 --- a/internal/lsp/cache/snapshot.go +++ b/internal/lsp/cache/snapshot.go @@ -72,7 +72,7 @@ func (s *snapshot) ModFiles(ctx context.Context) (source.FileHandle, source.File if s.view.modfiles == nil { return nil, nil, nil } - realfh, err := s.GetFile(ctx, span.FileURI(s.view.modfiles.real)) + realfh, err := s.GetFile(span.FileURI(s.view.modfiles.real)) if err != nil { return nil, nil, err } @@ -523,25 +523,25 @@ func (s *snapshot) getFileURIs() []span.URI { } // FindFile returns the file if the given URI is already a part of the view. -func (s *snapshot) FindFile(ctx context.Context, uri span.URI) source.FileHandle { - f, err := s.view.findFileLocked(ctx, uri) +func (s *snapshot) FindFile(uri span.URI) source.FileHandle { + f, err := s.view.findFileLocked(uri) if f == nil || err != nil { return nil } - return s.getFileHandle(ctx, f) + return s.getFileHandle(f) } // GetFile returns a File for the given URI. It will always succeed because it // adds the file to the managed set if needed. -func (s *snapshot) GetFile(ctx context.Context, uri span.URI) (source.FileHandle, error) { - f, err := s.view.getFileLocked(ctx, uri) +func (s *snapshot) GetFile(uri span.URI) (source.FileHandle, error) { + f, err := s.view.getFileLocked(uri) if err != nil { return nil, err } - return s.getFileHandle(ctx, f), nil + return s.getFileHandle(f), nil } -func (s *snapshot) getFileHandle(ctx context.Context, f *fileBase) source.FileHandle { +func (s *snapshot) getFileHandle(f *fileBase) source.FileHandle { s.mu.Lock() defer s.mu.Unlock() diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go index a276805a74..16555e36a1 100644 --- a/internal/lsp/cache/view.go +++ b/internal/lsp/cache/view.go @@ -21,7 +21,6 @@ import ( "golang.org/x/tools/go/packages" "golang.org/x/tools/internal/imports" "golang.org/x/tools/internal/lsp/debug" - "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/span" "golang.org/x/tools/internal/telemetry/log" @@ -344,7 +343,7 @@ func basename(filename string) string { } // FindFile returns the file if the given URI is already a part of the view. -func (v *view) findFileLocked(ctx context.Context, uri span.URI) (*fileBase, error) { +func (v *view) findFileLocked(uri span.URI) (*fileBase, error) { v.mu.Lock() defer v.mu.Unlock() @@ -353,15 +352,15 @@ func (v *view) findFileLocked(ctx context.Context, uri span.URI) (*fileBase, err // getFileLocked returns a File for the given URI. It will always succeed because it // adds the file to the managed set if needed. -func (v *view) getFileLocked(ctx context.Context, uri span.URI) (*fileBase, error) { +func (v *view) getFileLocked(uri span.URI) (*fileBase, error) { v.mu.Lock() defer v.mu.Unlock() - return v.getFile(ctx, uri) + return v.getFile(uri) } // getFile is the unlocked internal implementation of GetFile. -func (v *view) getFile(ctx context.Context, uri span.URI) (*fileBase, error) { +func (v *view) getFile(uri span.URI) (*fileBase, error) { f, err := v.findFile(uri) if err != nil { return nil, err @@ -535,89 +534,6 @@ func (v *view) cancelBackground() { v.backgroundCtx, v.cancel = context.WithCancel(v.baseCtx) } -func (v *view) FindPosInPackage(searchpkg source.Package, pos token.Pos) (*ast.File, source.Package, error) { - tok := v.session.cache.fset.File(pos) - if tok == nil { - return nil, nil, errors.Errorf("no file for pos in package %s", searchpkg.ID()) - } - uri := span.FileURI(tok.Name()) - - // Special case for ignored files. - var ( - ph source.ParseGoHandle - pkg source.Package - err error - ) - if v.Ignore(uri) { - ph, pkg, err = v.findIgnoredFile(uri) - } else { - ph, pkg, err = findFileInPackage(searchpkg, uri) - } - if err != nil { - return nil, nil, err - } - file, _, _, err := ph.Cached() - if err != nil { - return nil, nil, err - } - if !(file.Pos() <= pos && pos <= file.End()) { - return nil, nil, fmt.Errorf("pos %v, apparently in file %q, is not between %v and %v", pos, ph.File().Identity().URI, file.Pos(), file.End()) - } - return file, pkg, nil -} - -func (v *view) FindMapperInPackage(searchpkg source.Package, uri span.URI) (*protocol.ColumnMapper, error) { - // Special case for ignored files. - var ( - ph source.ParseGoHandle - err error - ) - if v.Ignore(uri) { - ph, _, err = v.findIgnoredFile(uri) - } else { - ph, _, err = findFileInPackage(searchpkg, uri) - } - if err != nil { - return nil, err - } - _, m, _, err := ph.Cached() - if err != nil { - return nil, err - } - return m, nil -} - -func (v *view) findIgnoredFile(uri span.URI) (source.ParseGoHandle, source.Package, error) { - // Check the builtin package. - for _, h := range v.BuiltinPackage().CompiledGoFiles() { - if h.File().Identity().URI == uri { - return h, nil, nil - } - } - return nil, nil, errors.Errorf("no ignored file for %s", uri) -} - -func findFileInPackage(pkg source.Package, uri span.URI) (source.ParseGoHandle, source.Package, error) { - queue := []source.Package{pkg} - seen := make(map[string]bool) - - for len(queue) > 0 { - pkg := queue[0] - queue = queue[1:] - seen[pkg.ID()] = true - - if f, err := pkg.File(uri); err == nil { - return f, pkg, nil - } - for _, dep := range pkg.Imports() { - if !seen[dep.ID()] { - queue = append(queue, dep) - } - } - } - return nil, nil, errors.Errorf("no file for %s in package %s", uri, pkg.ID()) -} - func (v *view) getBuildCachePath(ctx context.Context) (string, error) { v.mu.Lock() defer v.mu.Unlock() diff --git a/internal/lsp/code_action.go b/internal/lsp/code_action.go index a7b8ea44a5..d78e53fd83 100644 --- a/internal/lsp/code_action.go +++ b/internal/lsp/code_action.go @@ -26,7 +26,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } @@ -228,7 +228,7 @@ func quickFixes(ctx context.Context, snapshot source.Snapshot, fh source.FileHan Edit: protocol.WorkspaceEdit{}, } for uri, edits := range fix.Edits { - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { log.Error(ctx, "no file", err, telemetry.URI.Of(uri)) continue diff --git a/internal/lsp/command.go b/internal/lsp/command.go index 235d25683e..85e237274c 100644 --- a/internal/lsp/command.go +++ b/internal/lsp/command.go @@ -21,7 +21,7 @@ func (s *Server) executeCommand(ctx context.Context, params *protocol.ExecuteCom if err != nil { return nil, err } - fh, err := view.Snapshot().GetFile(ctx, uri) + fh, err := view.Snapshot().GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index 7061ff9548..820e039b12 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -25,7 +25,7 @@ func (s *Server) completion(ctx context.Context, params *protocol.CompletionPara } snapshot := view.Snapshot() options := view.Options() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/definition.go b/internal/lsp/definition.go index 41617d3fba..a328800cc0 100644 --- a/internal/lsp/definition.go +++ b/internal/lsp/definition.go @@ -19,7 +19,7 @@ func (s *Server) definition(ctx context.Context, params *protocol.DefinitionPara return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } @@ -49,7 +49,7 @@ func (s *Server) typeDefinition(ctx context.Context, params *protocol.TypeDefini return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/folding_range.go b/internal/lsp/folding_range.go index 7a4bb9cb4b..19b28ebfaa 100644 --- a/internal/lsp/folding_range.go +++ b/internal/lsp/folding_range.go @@ -15,7 +15,7 @@ func (s *Server) foldingRange(ctx context.Context, params *protocol.FoldingRange return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/format.go b/internal/lsp/format.go index 248f92105e..f3abeb1a6c 100644 --- a/internal/lsp/format.go +++ b/internal/lsp/format.go @@ -19,7 +19,7 @@ func (s *Server) formatting(ctx context.Context, params *protocol.DocumentFormat return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/highlight.go b/internal/lsp/highlight.go index 2125534b02..45e374bd43 100644 --- a/internal/lsp/highlight.go +++ b/internal/lsp/highlight.go @@ -21,7 +21,7 @@ func (s *Server) documentHighlight(ctx context.Context, params *protocol.Documen return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/hover.go b/internal/lsp/hover.go index 2a60599e6e..a93a30ddf3 100644 --- a/internal/lsp/hover.go +++ b/internal/lsp/hover.go @@ -19,7 +19,7 @@ func (s *Server) hover(ctx context.Context, params *protocol.HoverParams) (*prot return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/implementation.go b/internal/lsp/implementation.go index 0a1877328b..bae2832d84 100644 --- a/internal/lsp/implementation.go +++ b/internal/lsp/implementation.go @@ -19,7 +19,7 @@ func (s *Server) implementation(ctx context.Context, params *protocol.Implementa return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/link.go b/internal/lsp/link.go index 1352727b30..ddcb334abc 100644 --- a/internal/lsp/link.go +++ b/internal/lsp/link.go @@ -26,7 +26,7 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink if err != nil { return nil, err } - fh, err := view.Snapshot().GetFile(ctx, uri) + fh, err := view.Snapshot().GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index 601e80a8b9..78a0d8f208 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -85,7 +85,7 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) { // TODO: Actually test the LSP diagnostics function in this test. func (r *runner) Diagnostics(t *testing.T, uri span.URI, want []source.Diagnostic) { v := r.server.session.View(viewName) - fh, err := v.Snapshot().GetFile(r.ctx, uri) + fh, err := v.Snapshot().GetFile(uri) if err != nil { t.Fatal(err) } @@ -339,7 +339,7 @@ func (r *runner) SuggestedFix(t *testing.T, spn span.Span) { t.Fatal(err) } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(r.ctx, spn.URI()) + fh, err := snapshot.GetFile(spn.URI()) if err != nil { t.Fatal(err) } diff --git a/internal/lsp/references.go b/internal/lsp/references.go index 3c4d66598f..47120173f6 100644 --- a/internal/lsp/references.go +++ b/internal/lsp/references.go @@ -19,7 +19,7 @@ func (s *Server) references(ctx context.Context, params *protocol.ReferenceParam return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/rename.go b/internal/lsp/rename.go index 6c1c223583..7725bc6b88 100644 --- a/internal/lsp/rename.go +++ b/internal/lsp/rename.go @@ -19,7 +19,7 @@ func (s *Server) rename(ctx context.Context, params *protocol.RenameParams) (*pr return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } @@ -36,7 +36,7 @@ func (s *Server) rename(ctx context.Context, params *protocol.RenameParams) (*pr } var docChanges []protocol.TextDocumentEdit for uri, e := range edits { - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } @@ -54,7 +54,7 @@ func (s *Server) prepareRename(ctx context.Context, params *protocol.PrepareRena return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/signature_help.go b/internal/lsp/signature_help.go index 096abe95a3..fab6453919 100644 --- a/internal/lsp/signature_help.go +++ b/internal/lsp/signature_help.go @@ -21,7 +21,7 @@ func (s *Server) signatureHelp(ctx context.Context, params *protocol.SignatureHe return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/source/completion_format.go b/internal/lsp/source/completion_format.go index 1d128a5e7b..77713dddfe 100644 --- a/internal/lsp/source/completion_format.go +++ b/internal/lsp/source/completion_format.go @@ -186,7 +186,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) { if cand.imp != nil && cand.imp.pkg != nil { searchPkg = cand.imp.pkg } - file, pkg, err := c.snapshot.View().FindPosInPackage(searchPkg, obj.Pos()) + file, pkg, err := findPosInPackage(c.snapshot.View(), searchPkg, obj.Pos()) if err != nil { return item, nil } diff --git a/internal/lsp/source/highlight.go b/internal/lsp/source/highlight.go index ba07546826..89c057db18 100644 --- a/internal/lsp/source/highlight.go +++ b/internal/lsp/source/highlight.go @@ -137,7 +137,7 @@ Outer: result := make(map[protocol.Range]bool) // Highlight the correct argument in the function declaration return types. if resultsList != nil && -1 < index && index < len(resultsList.List) { - rng, err := nodeToProtocolRange(ctx, snapshot.View(), m, resultsList.List[index]) + rng, err := nodeToProtocolRange(snapshot.View(), m, resultsList.List[index]) if err != nil { log.Error(ctx, "Error getting range for node", err) } else { @@ -174,7 +174,7 @@ Outer: toAdd = n.Results[index] } if toAdd != nil { - rng, err := nodeToProtocolRange(ctx, snapshot.View(), m, toAdd) + rng, err := nodeToProtocolRange(snapshot.View(), m, toAdd) if err != nil { log.Error(ctx, "Error getting range for node", err) } else { @@ -223,7 +223,7 @@ Outer: } // Add all branch statements in same scope as the identified one. if n, ok := n.(*ast.BranchStmt); ok { - rng, err := nodeToProtocolRange(ctx, snapshot.View(), m, n) + rng, err := nodeToProtocolRange(snapshot.View(), m, n) if err != nil { log.Error(ctx, "Error getting range for node", err) return false @@ -262,7 +262,7 @@ func highlightIdentifiers(ctx context.Context, snapshot Snapshot, m *protocol.Co if nObj := pkg.GetTypesInfo().ObjectOf(n); nObj != idObj { return false } - if rng, err := nodeToProtocolRange(ctx, snapshot.View(), m, n); err == nil { + if rng, err := nodeToProtocolRange(snapshot.View(), m, n); err == nil { result[rng] = true } else { log.Error(ctx, "Error getting range for node", err) diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go index 555c1a2080..e0761cb645 100644 --- a/internal/lsp/source/identifier.go +++ b/internal/lsp/source/identifier.go @@ -252,7 +252,7 @@ func hasErrorType(obj types.Object) bool { } func objToNode(v View, pkg Package, obj types.Object) (ast.Decl, error) { - declAST, _, err := v.FindPosInPackage(pkg, obj.Pos()) + declAST, _, err := findPosInPackage(v, pkg, obj.Pos()) if err != nil { return nil, err } diff --git a/internal/lsp/source/rename.go b/internal/lsp/source/rename.go index 64a25894d4..7187f14e41 100644 --- a/internal/lsp/source/rename.go +++ b/internal/lsp/source/rename.go @@ -155,7 +155,7 @@ func (i *IdentifierInfo) Rename(ctx context.Context, newName string) (map[span.U for uri, edits := range changes { // These edits should really be associated with FileHandles for maximal correctness. // For now, this is good enough. - fh, err := i.Snapshot.GetFile(ctx, uri) + fh, err := i.Snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index 51885d3e98..defab5e333 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -80,7 +80,7 @@ func testSource(t *testing.T, exporter packagestest.Exporter) { func (r *runner) Diagnostics(t *testing.T, uri span.URI, want []source.Diagnostic) { snapshot := r.view.Snapshot() - fh, err := snapshot.GetFile(r.ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { t.Fatal(err) } @@ -233,7 +233,7 @@ func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completi } func (r *runner) callCompletion(t *testing.T, src span.Span, options source.CompletionOptions) (string, []protocol.CompletionItem) { - fh, err := r.view.Snapshot().GetFile(r.ctx, src.URI()) + fh, err := r.view.Snapshot().GetFile(src.URI()) if err != nil { t.Fatal(err) } @@ -277,7 +277,7 @@ func (r *runner) callCompletion(t *testing.T, src span.Span, options source.Comp func (r *runner) FoldingRanges(t *testing.T, spn span.Span) { uri := spn.URI() - fh, err := r.view.Snapshot().GetFile(r.ctx, spn.URI()) + fh, err := r.view.Snapshot().GetFile(spn.URI()) if err != nil { t.Fatal(err) } @@ -417,7 +417,7 @@ func (r *runner) Format(t *testing.T, spn span.Span) { out, _ := cmd.Output() // ignore error, sometimes we have intentionally ungofmt-able files return out, nil })) - fh, err := r.view.Snapshot().GetFile(r.ctx, spn.URI()) + fh, err := r.view.Snapshot().GetFile(spn.URI()) if err != nil { t.Fatal(err) } @@ -447,7 +447,7 @@ func (r *runner) Format(t *testing.T, spn span.Span) { } func (r *runner) Import(t *testing.T, spn span.Span) { - fh, err := r.view.Snapshot().GetFile(r.ctx, spn.URI()) + fh, err := r.view.Snapshot().GetFile(spn.URI()) if err != nil { t.Fatal(err) } @@ -483,7 +483,7 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) { if err != nil { t.Fatal(err) } - fh, err := r.view.Snapshot().GetFile(r.ctx, spn.URI()) + fh, err := r.view.Snapshot().GetFile(spn.URI()) if err != nil { t.Fatal(err) } @@ -543,7 +543,7 @@ func (r *runner) Implementation(t *testing.T, spn span.Span, impls []span.Span) if err != nil { t.Fatalf("failed for %v: %v", spn, err) } - fh, err := r.view.Snapshot().GetFile(r.ctx, spn.URI()) + fh, err := r.view.Snapshot().GetFile(spn.URI()) if err != nil { t.Fatal(err) } @@ -587,7 +587,7 @@ func (r *runner) Highlight(t *testing.T, src span.Span, locations []span.Span) { if err != nil { t.Fatal(err) } - fh, err := r.view.Snapshot().GetFile(r.ctx, src.URI()) + fh, err := r.view.Snapshot().GetFile(src.URI()) if err != nil { t.Fatal(err) } @@ -625,7 +625,7 @@ func (r *runner) References(t *testing.T, src span.Span, itemList []span.Span) { if err != nil { t.Fatal(err) } - fh, err := r.view.Snapshot().GetFile(r.ctx, src.URI()) + fh, err := r.view.Snapshot().GetFile(src.URI()) if err != nil { t.Fatal(err) } @@ -669,7 +669,7 @@ func (r *runner) Rename(t *testing.T, spn span.Span, newText string) { if err != nil { t.Fatal(err) } - fh, err := r.view.Snapshot().GetFile(r.ctx, spn.URI()) + fh, err := r.view.Snapshot().GetFile(spn.URI()) if err != nil { t.Fatal(err) } @@ -691,7 +691,7 @@ func (r *runner) Rename(t *testing.T, spn span.Span, newText string) { var res []string for editURI, edits := range changes { - fh, err := r.view.Snapshot().GetFile(r.ctx, editURI) + fh, err := r.view.Snapshot().GetFile(editURI) if err != nil { t.Fatal(err) } @@ -756,7 +756,7 @@ func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.Prepare t.Fatal(err) } // Find the identifier at the position. - fh, err := r.view.Snapshot().GetFile(r.ctx, src.URI()) + fh, err := r.view.Snapshot().GetFile(src.URI()) if err != nil { t.Fatal(err) } @@ -798,7 +798,7 @@ func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.Prepare } func (r *runner) Symbols(t *testing.T, uri span.URI, expectedSymbols []protocol.DocumentSymbol) { - fh, err := r.view.Snapshot().GetFile(r.ctx, uri) + fh, err := r.view.Snapshot().GetFile(uri) if err != nil { t.Fatal(err) } @@ -863,7 +863,7 @@ func (r *runner) SignatureHelp(t *testing.T, spn span.Span, expectedSignature *s if err != nil { t.Fatal(err) } - fh, err := r.view.Snapshot().GetFile(r.ctx, spn.URI()) + fh, err := r.view.Snapshot().GetFile(spn.URI()) if err != nil { t.Fatal(err) } diff --git a/internal/lsp/source/symbols.go b/internal/lsp/source/symbols.go index eabd09ca53..609f430c6c 100644 --- a/internal/lsp/source/symbols.go +++ b/internal/lsp/source/symbols.go @@ -99,11 +99,11 @@ func funcSymbol(ctx context.Context, view View, m *protocol.ColumnMapper, decl * Kind: protocol.Function, } var err error - s.Range, err = nodeToProtocolRange(ctx, view, m, decl) + s.Range, err = nodeToProtocolRange(view, m, decl) if err != nil { return protocol.DocumentSymbol{}, err } - s.SelectionRange, err = nodeToProtocolRange(ctx, view, m, decl.Name) + s.SelectionRange, err = nodeToProtocolRange(view, m, decl.Name) if err != nil { return protocol.DocumentSymbol{}, err } @@ -165,11 +165,11 @@ func typeSymbol(ctx context.Context, view View, m *protocol.ColumnMapper, info * setKind(&s, obj.Type(), q) var err error - s.Range, err = nodeToProtocolRange(ctx, view, m, spec) + s.Range, err = nodeToProtocolRange(view, m, spec) if err != nil { return protocol.DocumentSymbol{}, err } - s.SelectionRange, err = nodeToProtocolRange(ctx, view, m, spec.Name) + s.SelectionRange, err = nodeToProtocolRange(view, m, spec.Name) if err != nil { return protocol.DocumentSymbol{}, err } @@ -185,10 +185,10 @@ func typeSymbol(ctx context.Context, view View, m *protocol.ColumnMapper, info * child.Detail, _ = formatType(f.Type(), q) spanNode, selectionNode := nodesForStructField(i, st) - if span, err := nodeToProtocolRange(ctx, view, m, spanNode); err == nil { + if span, err := nodeToProtocolRange(view, m, spanNode); err == nil { child.Range = span } - if span, err := nodeToProtocolRange(ctx, view, m, selectionNode); err == nil { + if span, err := nodeToProtocolRange(view, m, selectionNode); err == nil { child.SelectionRange = span } s.Children = append(s.Children, child) @@ -215,11 +215,11 @@ func typeSymbol(ctx context.Context, view View, m *protocol.ColumnMapper, info * } } } - child.Range, err = nodeToProtocolRange(ctx, view, m, spanNode) + child.Range, err = nodeToProtocolRange(view, m, spanNode) if err != nil { return protocol.DocumentSymbol{}, err } - child.SelectionRange, err = nodeToProtocolRange(ctx, view, m, selectionNode) + child.SelectionRange, err = nodeToProtocolRange(view, m, selectionNode) if err != nil { return protocol.DocumentSymbol{}, err } @@ -249,11 +249,11 @@ func typeSymbol(ctx context.Context, view View, m *protocol.ColumnMapper, info * break Embeddeds } } - child.Range, err = nodeToProtocolRange(ctx, view, m, spanNode) + child.Range, err = nodeToProtocolRange(view, m, spanNode) if err != nil { return protocol.DocumentSymbol{}, err } - child.SelectionRange, err = nodeToProtocolRange(ctx, view, m, selectionNode) + child.SelectionRange, err = nodeToProtocolRange(view, m, selectionNode) if err != nil { return protocol.DocumentSymbol{}, err } @@ -292,11 +292,11 @@ func varSymbol(ctx context.Context, view View, m *protocol.ColumnMapper, decl as s.Kind = protocol.Constant } var err error - s.Range, err = nodeToProtocolRange(ctx, view, m, decl) + s.Range, err = nodeToProtocolRange(view, m, decl) if err != nil { return protocol.DocumentSymbol{}, err } - s.SelectionRange, err = nodeToProtocolRange(ctx, view, m, name) + s.SelectionRange, err = nodeToProtocolRange(view, m, name) if err != nil { return protocol.DocumentSymbol{}, err } diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go index 91678b67a1..ce49b311e4 100644 --- a/internal/lsp/source/util.go +++ b/internal/lsp/source/util.go @@ -142,7 +142,7 @@ func SpecificPackageHandle(desiredID string) PackagePolicy { } func IsGenerated(ctx context.Context, view View, uri span.URI) bool { - fh, err := view.Snapshot().GetFile(ctx, uri) + fh, err := view.Snapshot().GetFile(uri) if err != nil { return false } @@ -168,7 +168,7 @@ func IsGenerated(ctx context.Context, view View, uri span.URI) bool { return false } -func nodeToProtocolRange(ctx context.Context, view View, m *protocol.ColumnMapper, n ast.Node) (protocol.Range, error) { +func nodeToProtocolRange(view View, m *protocol.ColumnMapper, n ast.Node) (protocol.Range, error) { mrng, err := nodeToMappedRange(view, m, n) if err != nil { return protocol.Range{}, err @@ -205,7 +205,7 @@ func nodeToMappedRange(view View, m *protocol.ColumnMapper, n ast.Node) (mappedR func posToMappedRange(v View, pkg Package, pos, end token.Pos) (mappedRange, error) { logicalFilename := v.Session().Cache().FileSet().File(pos).Position(pos).Filename - m, err := v.FindMapperInPackage(pkg, span.FileURI(logicalFilename)) + m, err := findMapperInPackage(v, pkg, span.FileURI(logicalFilename)) if err != nil { return mappedRange{}, err } @@ -512,7 +512,7 @@ func formatParams(s Snapshot, pkg Package, sig *types.Signature, qf types.Qualif } func formatFieldType(s Snapshot, srcpkg Package, obj types.Object, qf types.Qualifier) (string, error) { - file, pkg, err := s.View().FindPosInPackage(srcpkg, obj.Pos()) + file, pkg, err := findPosInPackage(s.View(), srcpkg, obj.Pos()) if err != nil { return "", err } @@ -628,3 +628,84 @@ func CompareDiagnostic(a, b Diagnostic) int { } return 1 } + +func findPosInPackage(v View, searchpkg Package, pos token.Pos) (*ast.File, Package, error) { + tok := v.Session().Cache().FileSet().File(pos) + if tok == nil { + return nil, nil, errors.Errorf("no file for pos in package %s", searchpkg.ID()) + } + uri := span.FileURI(tok.Name()) + + var ( + ph ParseGoHandle + pkg Package + err error + ) + // Special case for ignored files. + if v.Ignore(uri) { + ph, err = findIgnoredFile(v, uri) + } else { + ph, pkg, err = findFileInPackage(searchpkg, uri) + } + if err != nil { + return nil, nil, err + } + file, _, _, err := ph.Cached() + if err != nil { + return nil, nil, err + } + if !(file.Pos() <= pos && pos <= file.End()) { + return nil, nil, fmt.Errorf("pos %v, apparently in file %q, is not between %v and %v", pos, ph.File().Identity().URI, file.Pos(), file.End()) + } + return file, pkg, nil +} + +func findMapperInPackage(v View, searchpkg Package, uri span.URI) (*protocol.ColumnMapper, error) { + var ( + ph ParseGoHandle + err error + ) + // Special case for ignored files. + if v.Ignore(uri) { + ph, err = findIgnoredFile(v, uri) + } else { + ph, _, err = findFileInPackage(searchpkg, uri) + } + if err != nil { + return nil, err + } + _, m, _, err := ph.Cached() + if err != nil { + return nil, err + } + return m, nil +} + +func findIgnoredFile(v View, uri span.URI) (ParseGoHandle, error) { + fh, err := v.Snapshot().GetFile(uri) + if err != nil { + return nil, err + } + return v.Session().Cache().ParseGoHandle(fh, ParseFull), nil +} + +func findFileInPackage(pkg Package, uri span.URI) (ParseGoHandle, Package, error) { + queue := []Package{pkg} + seen := make(map[string]bool) + + for len(queue) > 0 { + pkg := queue[0] + queue = queue[1:] + seen[pkg.ID()] = true + + if f, err := pkg.File(uri); err == nil { + return f, pkg, nil + } + for _, dep := range pkg.Imports() { + if !seen[dep.ID()] { + queue = append(queue, dep) + } + } + } + return nil, nil, errors.Errorf("no file for %s in package %s", uri, pkg.ID()) +} diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go index 3dd8ec9626..4687c9880a 100644 --- a/internal/lsp/source/view.go +++ b/internal/lsp/source/view.go @@ -26,11 +26,11 @@ type Snapshot interface { // GetFile returns the file object for a given URI, initializing it // if it is not already part of the view. - GetFile(ctx context.Context, uri span.URI) (FileHandle, error) + GetFile(uri span.URI) (FileHandle, error) // FindFile returns the file object for a given URI if it is // already part of the view. - FindFile(ctx context.Context, uri span.URI) FileHandle + FindFile(uri span.URI) FileHandle // Analyze runs the analyses for the given package at this snapshot. Analyze(ctx context.Context, id string, analyzers []*analysis.Analyzer) ([]*Error, error) @@ -122,14 +122,6 @@ type View interface { // original one will be. SetOptions(context.Context, Options) (View, error) - // FindFileInPackage returns the AST and type information for a file that may - // belong to or be part of a dependency of the given package. - FindPosInPackage(pkg Package, pos token.Pos) (*ast.File, Package, error) - - // FindMapperInPackage returns the mapper associated with a file that may belong to - // the given package or one of its dependencies. - FindMapperInPackage(pkg Package, uri span.URI) (*protocol.ColumnMapper, error) - // WorkspacePackageIDs returns the ids of the packages at the top-level // of the snapshot's view. WorkspacePackageIDs(ctx context.Context) ([]string, error) diff --git a/internal/lsp/symbols.go b/internal/lsp/symbols.go index 4d6b20ab95..0e167d3e68 100644 --- a/internal/lsp/symbols.go +++ b/internal/lsp/symbols.go @@ -25,7 +25,7 @@ func (s *Server) documentSymbol(ctx context.Context, params *protocol.DocumentSy return nil, err } snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return nil, err } diff --git a/internal/lsp/text_synchronization.go b/internal/lsp/text_synchronization.go index 6d5732b4a3..6b4ff3058e 100644 --- a/internal/lsp/text_synchronization.go +++ b/internal/lsp/text_synchronization.go @@ -33,7 +33,7 @@ func (s *Server) didOpen(ctx context.Context, params *protocol.DidOpenTextDocume if err != nil { return err } - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return err } @@ -72,7 +72,7 @@ func (s *Server) didChange(ctx context.Context, params *protocol.DidChangeTextDo Type: protocol.Warning, }) } - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return err } diff --git a/internal/lsp/watched_files.go b/internal/lsp/watched_files.go index 537cd1d29d..f2c8b2f283 100644 --- a/internal/lsp/watched_files.go +++ b/internal/lsp/watched_files.go @@ -32,7 +32,7 @@ func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.Did // If we had been tracking the given file, // recompute diagnostics to reflect updated file contents. snapshot := view.Snapshot() - fh, err := snapshot.GetFile(ctx, uri) + fh, err := snapshot.GetFile(uri) if err != nil { return err } @@ -47,7 +47,7 @@ func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.Did } case source.Delete: snapshot := view.Snapshot() - fh := snapshot.FindFile(ctx, uri) + fh := snapshot.FindFile(uri) // If we have never seen this file before, there is nothing to do. if fh == nil { continue @@ -69,7 +69,7 @@ func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.Did if pgh.File().Identity().URI == fh.Identity().URI { continue } - if f := snapshot.FindFile(ctx, pgh.File().Identity().URI); f != nil && s.session.IsOpen(fh.Identity().URI) { + if f := snapshot.FindFile(pgh.File().Identity().URI); f != nil && s.session.IsOpen(fh.Identity().URI) { otherFile = f break }