Skip to content

Commit 6128030

Browse files
committed
gopls/internal: support renaming packages with int. test variants
We need to search intermediate test variants to find all imports of a renamed package, but were missing them because we only considered "active packages". Fix this by building up the set of renamed packages based on metadata alone: it is unnecessary and potentially too costly to request all (typechecked) known packages, when we only need access to the metadata graph to determine which packages must be renamed. In doing so, it becomes possible that we produce duplicate edits by renaming through a test variant. Avoid this by keeping track of import path changes that we have already processed. While at it, add a few more checks for package renaming: - check for valid identifiers - disallow renaming x_test packages - disallow renaming to x_test packages Also refactor package renaming slightly to pass around an edit map. This fixes a bug where nested import paths were not renamed in the original renaming package. Fix some testing bugs that were exercised by new tests. For golang/go#41567 Change-Id: I18ab442b33a3ee5bf527f078dcaa81d47f0220c7 Reviewed-on: https://go-review.googlesource.com/c/tools/+/443637 Reviewed-by: Dylan Le <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Robert Findley <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent 649df2e commit 6128030

File tree

11 files changed

+501
-113
lines changed

11 files changed

+501
-113
lines changed

gopls/internal/lsp/cache/check.go

-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ func (s *snapshot) buildPackageHandle(ctx context.Context, id PackageID, mode so
150150
experimentalKey := s.View().Options().ExperimentalPackageCacheKey
151151
phKey := computePackageKey(m.ID, compiledGoFiles, m, depKey, mode, experimentalKey)
152152
promise, release := s.store.Promise(phKey, func(ctx context.Context, arg interface{}) interface{} {
153-
154153
pkg, err := typeCheckImpl(ctx, arg.(*snapshot), goFiles, compiledGoFiles, m.Metadata, mode, deps)
155154
return typeCheckResult{pkg, err}
156155
})

gopls/internal/lsp/cache/snapshot.go

+22
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,28 @@ func (s *snapshot) KnownPackages(ctx context.Context) ([]source.Package, error)
11951195
return pkgs, nil
11961196
}
11971197

1198+
func (s *snapshot) AllValidMetadata(ctx context.Context) ([]source.Metadata, error) {
1199+
if err := s.awaitLoaded(ctx); err != nil {
1200+
return nil, err
1201+
}
1202+
1203+
s.mu.Lock()
1204+
defer s.mu.Unlock()
1205+
1206+
var meta []source.Metadata
1207+
for _, m := range s.meta.metadata {
1208+
if m.Valid {
1209+
meta = append(meta, m)
1210+
}
1211+
}
1212+
return meta, nil
1213+
}
1214+
1215+
func (s *snapshot) WorkspacePackageByID(ctx context.Context, id string) (source.Package, error) {
1216+
packageID := PackageID(id)
1217+
return s.checkedPackage(ctx, packageID, s.workspaceParseMode(packageID))
1218+
}
1219+
11981220
func (s *snapshot) CachedImportPaths(ctx context.Context) (map[string]source.Package, error) {
11991221
// Don't reload workspace package metadata.
12001222
// This function is meant to only return currently cached information.

gopls/internal/lsp/fake/editor.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,12 @@ func (e *Editor) onFileChanges(ctx context.Context, evts []FileEvent) {
366366
}
367367

368368
// OpenFile creates a buffer for the given workdir-relative file.
369+
//
370+
// If the file is already open, it is a no-op.
369371
func (e *Editor) OpenFile(ctx context.Context, path string) error {
372+
if e.HasBuffer(path) {
373+
return nil
374+
}
370375
content, err := e.sandbox.Workdir.ReadFile(path)
371376
if err != nil {
372377
return err
@@ -383,6 +388,11 @@ func (e *Editor) CreateBuffer(ctx context.Context, path, content string) error {
383388
func (e *Editor) createBuffer(ctx context.Context, path string, dirty bool, content string) error {
384389
e.mu.Lock()
385390

391+
if _, ok := e.buffers[path]; ok {
392+
e.mu.Unlock()
393+
return fmt.Errorf("buffer %q already exists", path)
394+
}
395+
386396
buf := buffer{
387397
windowsLineEndings: e.config.WindowsLineEndings,
388398
version: 1,
@@ -712,7 +722,7 @@ func (e *Editor) editBufferLocked(ctx context.Context, path string, edits []Edit
712722
}
713723
content, err := applyEdits(buf.lines, edits)
714724
if err != nil {
715-
return err
725+
return fmt.Errorf("editing %q: %v; edits:\n%v", path, err, edits)
716726
}
717727
return e.setBufferContentLocked(ctx, path, true, content, edits)
718728
}
@@ -1171,6 +1181,15 @@ func (e *Editor) Rename(ctx context.Context, path string, pos Pos, newName strin
11711181
if e.Server == nil {
11721182
return nil
11731183
}
1184+
1185+
// Verify that PrepareRename succeeds.
1186+
prepareParams := &protocol.PrepareRenameParams{}
1187+
prepareParams.TextDocument = e.TextDocumentIdentifier(path)
1188+
prepareParams.Position = pos.ToProtocolPosition()
1189+
if _, err := e.Server.PrepareRename(ctx, prepareParams); err != nil {
1190+
return fmt.Errorf("preparing rename: %v", err)
1191+
}
1192+
11741193
params := &protocol.RenameParams{
11751194
TextDocument: e.TextDocumentIdentifier(path),
11761195
Position: pos.ToProtocolPosition(),

gopls/internal/lsp/fake/workdir.go

+17
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"os"
1414
"path/filepath"
1515
"runtime"
16+
"sort"
1617
"strings"
1718
"sync"
1819
"time"
@@ -349,6 +350,22 @@ func (w *Workdir) RenameFile(ctx context.Context, oldPath, newPath string) error
349350
return nil
350351
}
351352

353+
// ListFiles returns a new sorted list of the relative paths of files in dir,
354+
// recursively.
355+
func (w *Workdir) ListFiles(dir string) ([]string, error) {
356+
m, err := w.listFiles(dir)
357+
if err != nil {
358+
return nil, err
359+
}
360+
361+
var paths []string
362+
for p := range m {
363+
paths = append(paths, p)
364+
}
365+
sort.Strings(paths)
366+
return paths, nil
367+
}
368+
352369
// listFiles lists files in the given directory, returning a map of relative
353370
// path to contents and modification time.
354371
func (w *Workdir) listFiles(dir string) (map[string]fileID, error) {

gopls/internal/lsp/regtest/wrappers.go

+11
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@ func (e *Env) WriteWorkspaceFiles(files map[string]string) {
5858
}
5959
}
6060

61+
// ListFiles lists relative paths to files in the given directory.
62+
// It calls t.Fatal on any error.
63+
func (e *Env) ListFiles(dir string) []string {
64+
e.T.Helper()
65+
paths, err := e.Sandbox.Workdir.ListFiles(dir)
66+
if err != nil {
67+
e.T.Fatal(err)
68+
}
69+
return paths
70+
}
71+
6172
// OpenFile opens a file in the editor, calling t.Fatal on any error.
6273
func (e *Env) OpenFile(name string) {
6374
e.T.Helper()

gopls/internal/lsp/source/references.go

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ func References(ctx context.Context, s Snapshot, f FileHandle, pp protocol.Posit
6262
}
6363

6464
if inPackageName {
65+
// TODO(rfindley): this is inaccurate, excluding test variants, and
66+
// redundant with package renaming. Refactor to share logic.
6567
renamingPkg, err := s.PackageForFile(ctx, f.URI(), TypecheckWorkspace, NarrowestPackage)
6668
if err != nil {
6769
return nil, err

0 commit comments

Comments
 (0)