Skip to content

Commit 9580c84

Browse files
author
Dylan Le
committed
internal/lsp: Check if user's editor support rename operation
Change-Id: Iadda768e93eda1d53fa00a5ff8a28013a575ef57 Reviewed-on: https://go-review.googlesource.com/c/tools/+/419774 Run-TryBot: Dylan Le <[email protected]> Reviewed-by: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent f560bc8 commit 9580c84

File tree

4 files changed

+77
-10
lines changed

4 files changed

+77
-10
lines changed

gopls/internal/regtest/misc/rename_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,49 @@ import (
88
"strings"
99
"testing"
1010

11+
"golang.org/x/tools/internal/lsp/protocol"
1112
. "golang.org/x/tools/internal/lsp/regtest"
1213
)
1314

15+
func TestPrepareRenamePackage(t *testing.T) {
16+
const files = `
17+
-- go.mod --
18+
module mod.com
19+
20+
go 1.18
21+
-- main.go --
22+
package main
23+
24+
import (
25+
"fmt"
26+
)
27+
28+
func main() {
29+
fmt.Println(1)
30+
}
31+
`
32+
const wantErr = "can't rename packages: LSP client does not support file renaming"
33+
Run(t, files, func(t *testing.T, env *Env) {
34+
env.OpenFile("main.go")
35+
pos := env.RegexpSearch("main.go", `main`)
36+
tdpp := protocol.TextDocumentPositionParams{
37+
TextDocument: env.Editor.TextDocumentIdentifier("main.go"),
38+
Position: pos.ToProtocolPosition(),
39+
}
40+
params := &protocol.PrepareRenameParams{
41+
TextDocumentPositionParams: tdpp,
42+
}
43+
_, err := env.Editor.Server.PrepareRename(env.Ctx, params)
44+
if err == nil {
45+
t.Errorf("missing can't rename package error from PrepareRename")
46+
}
47+
48+
if err.Error() != wantErr {
49+
t.Errorf("got %v, want %v", err.Error(), wantErr)
50+
}
51+
})
52+
}
53+
1454
// Test for golang/go#47564.
1555
func TestRenameInTestVariant(t *testing.T) {
1656
const files = `

internal/lsp/fake/editor.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ func (e *Editor) CloseBuffer(ctx context.Context, path string) error {
428428

429429
if e.Server != nil {
430430
if err := e.Server.DidClose(ctx, &protocol.DidCloseTextDocumentParams{
431-
TextDocument: e.textDocumentIdentifier(path),
431+
TextDocument: e.TextDocumentIdentifier(path),
432432
}); err != nil {
433433
return fmt.Errorf("DidClose: %w", err)
434434
}
@@ -439,7 +439,7 @@ func (e *Editor) CloseBuffer(ctx context.Context, path string) error {
439439
return nil
440440
}
441441

442-
func (e *Editor) textDocumentIdentifier(path string) protocol.TextDocumentIdentifier {
442+
func (e *Editor) TextDocumentIdentifier(path string) protocol.TextDocumentIdentifier {
443443
return protocol.TextDocumentIdentifier{
444444
URI: e.sandbox.Workdir.URI(path),
445445
}
@@ -471,7 +471,7 @@ func (e *Editor) SaveBufferWithoutActions(ctx context.Context, path string) erro
471471
includeText = syncOptions.Save.IncludeText
472472
}
473473

474-
docID := e.textDocumentIdentifier(buf.path)
474+
docID := e.TextDocumentIdentifier(buf.path)
475475
if e.Server != nil {
476476
if err := e.Server.WillSave(ctx, &protocol.WillSaveTextDocumentParams{
477477
TextDocument: docID,
@@ -693,7 +693,7 @@ func (e *Editor) setBufferContentLocked(ctx context.Context, path string, dirty
693693
params := &protocol.DidChangeTextDocumentParams{
694694
TextDocument: protocol.VersionedTextDocumentIdentifier{
695695
Version: int32(buf.version),
696-
TextDocumentIdentifier: e.textDocumentIdentifier(buf.path),
696+
TextDocumentIdentifier: e.TextDocumentIdentifier(buf.path),
697697
},
698698
ContentChanges: evts,
699699
}
@@ -1008,7 +1008,7 @@ func (e *Editor) CodeLens(ctx context.Context, path string) ([]protocol.CodeLens
10081008
return nil, fmt.Errorf("buffer %q is not open", path)
10091009
}
10101010
params := &protocol.CodeLensParams{
1011-
TextDocument: e.textDocumentIdentifier(path),
1011+
TextDocument: e.TextDocumentIdentifier(path),
10121012
}
10131013
lens, err := e.Server.CodeLens(ctx, params)
10141014
if err != nil {
@@ -1030,7 +1030,7 @@ func (e *Editor) Completion(ctx context.Context, path string, pos Pos) (*protoco
10301030
}
10311031
params := &protocol.CompletionParams{
10321032
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
1033-
TextDocument: e.textDocumentIdentifier(path),
1033+
TextDocument: e.TextDocumentIdentifier(path),
10341034
Position: pos.ToProtocolPosition(),
10351035
},
10361036
}
@@ -1080,7 +1080,7 @@ func (e *Editor) InlayHint(ctx context.Context, path string) ([]protocol.InlayHi
10801080
return nil, fmt.Errorf("buffer %q is not open", path)
10811081
}
10821082
params := &protocol.InlayHintParams{
1083-
TextDocument: e.textDocumentIdentifier(path),
1083+
TextDocument: e.TextDocumentIdentifier(path),
10841084
}
10851085
hints, err := e.Server.InlayHint(ctx, params)
10861086
if err != nil {
@@ -1102,7 +1102,7 @@ func (e *Editor) References(ctx context.Context, path string, pos Pos) ([]protoc
11021102
}
11031103
params := &protocol.ReferenceParams{
11041104
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
1105-
TextDocument: e.textDocumentIdentifier(path),
1105+
TextDocument: e.TextDocumentIdentifier(path),
11061106
Position: pos.ToProtocolPosition(),
11071107
},
11081108
Context: protocol.ReferenceContext{
@@ -1121,7 +1121,7 @@ func (e *Editor) Rename(ctx context.Context, path string, pos Pos, newName strin
11211121
return nil
11221122
}
11231123
params := &protocol.RenameParams{
1124-
TextDocument: e.textDocumentIdentifier(path),
1124+
TextDocument: e.TextDocumentIdentifier(path),
11251125
Position: pos.ToProtocolPosition(),
11261126
NewName: newName,
11271127
}
@@ -1195,7 +1195,7 @@ func (e *Editor) CodeAction(ctx context.Context, path string, rng *protocol.Rang
11951195
return nil, fmt.Errorf("buffer %q is not open", path)
11961196
}
11971197
params := &protocol.CodeActionParams{
1198-
TextDocument: e.textDocumentIdentifier(path),
1198+
TextDocument: e.TextDocumentIdentifier(path),
11991199
Context: protocol.CodeActionContext{
12001200
Diagnostics: diagnostics,
12011201
},

internal/lsp/source/options.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ type ClientOptions struct {
204204
RelatedInformationSupported bool
205205
CompletionTags bool
206206
CompletionDeprecated bool
207+
SupportedResourceOperations []protocol.ResourceOperationKind
207208
}
208209

209210
// ServerOptions holds LSP-specific configuration that is provided by the
@@ -701,6 +702,9 @@ func SetOptions(options *Options, opts interface{}) OptionResults {
701702

702703
func (o *Options) ForClientCapabilities(caps protocol.ClientCapabilities) {
703704
// Check if the client supports snippets in completion items.
705+
if caps.Workspace.WorkspaceEdit != nil {
706+
o.SupportedResourceOperations = caps.Workspace.WorkspaceEdit.ResourceOperations
707+
}
704708
if c := caps.TextDocument.Completion; c.CompletionItem.SnippetSupport {
705709
o.InsertTextFormat = protocol.SnippetTextFormat
706710
}

internal/lsp/source/rename.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,29 @@ type PrepareItem struct {
4949
// the prepare fails. Probably we could eliminate the redundancy in returning
5050
// two errors, but for now this is done defensively.
5151
func PrepareRename(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position) (_ *PrepareItem, usererr, err error) {
52+
fileRenameSupported := false
53+
for _, op := range snapshot.View().Options().SupportedResourceOperations {
54+
if op == protocol.Rename {
55+
fileRenameSupported = true
56+
break
57+
}
58+
}
59+
60+
// Find position of the package name declaration
61+
pgf, err := snapshot.ParseGo(ctx, f, ParseFull)
62+
if err != nil {
63+
return nil, err, err
64+
}
65+
inPackageName, err := isInPackageName(ctx, snapshot, f, pgf, pp)
66+
if err != nil {
67+
return nil, err, err
68+
}
69+
70+
if inPackageName && !fileRenameSupported {
71+
err := errors.New("can't rename packages: LSP client does not support file renaming")
72+
return nil, err, err
73+
}
74+
5275
ctx, done := event.Start(ctx, "source.PrepareRename")
5376
defer done()
5477

0 commit comments

Comments
 (0)