зеркало из https://github.com/golang/tools.git
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 <dungtuanle@google.com> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> gopls-CI: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Родитель
f560bc877f
Коммит
9580c84d57
|
@ -8,9 +8,49 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/internal/lsp/protocol"
|
||||
. "golang.org/x/tools/internal/lsp/regtest"
|
||||
)
|
||||
|
||||
func TestPrepareRenamePackage(t *testing.T) {
|
||||
const files = `
|
||||
-- go.mod --
|
||||
module mod.com
|
||||
|
||||
go 1.18
|
||||
-- main.go --
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(1)
|
||||
}
|
||||
`
|
||||
const wantErr = "can't rename packages: LSP client does not support file renaming"
|
||||
Run(t, files, func(t *testing.T, env *Env) {
|
||||
env.OpenFile("main.go")
|
||||
pos := env.RegexpSearch("main.go", `main`)
|
||||
tdpp := protocol.TextDocumentPositionParams{
|
||||
TextDocument: env.Editor.TextDocumentIdentifier("main.go"),
|
||||
Position: pos.ToProtocolPosition(),
|
||||
}
|
||||
params := &protocol.PrepareRenameParams{
|
||||
TextDocumentPositionParams: tdpp,
|
||||
}
|
||||
_, err := env.Editor.Server.PrepareRename(env.Ctx, params)
|
||||
if err == nil {
|
||||
t.Errorf("missing can't rename package error from PrepareRename")
|
||||
}
|
||||
|
||||
if err.Error() != wantErr {
|
||||
t.Errorf("got %v, want %v", err.Error(), wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Test for golang/go#47564.
|
||||
func TestRenameInTestVariant(t *testing.T) {
|
||||
const files = `
|
||||
|
|
|
@ -428,7 +428,7 @@ func (e *Editor) CloseBuffer(ctx context.Context, path string) error {
|
|||
|
||||
if e.Server != nil {
|
||||
if err := e.Server.DidClose(ctx, &protocol.DidCloseTextDocumentParams{
|
||||
TextDocument: e.textDocumentIdentifier(path),
|
||||
TextDocument: e.TextDocumentIdentifier(path),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("DidClose: %w", err)
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ func (e *Editor) CloseBuffer(ctx context.Context, path string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *Editor) textDocumentIdentifier(path string) protocol.TextDocumentIdentifier {
|
||||
func (e *Editor) TextDocumentIdentifier(path string) protocol.TextDocumentIdentifier {
|
||||
return protocol.TextDocumentIdentifier{
|
||||
URI: e.sandbox.Workdir.URI(path),
|
||||
}
|
||||
|
@ -471,7 +471,7 @@ func (e *Editor) SaveBufferWithoutActions(ctx context.Context, path string) erro
|
|||
includeText = syncOptions.Save.IncludeText
|
||||
}
|
||||
|
||||
docID := e.textDocumentIdentifier(buf.path)
|
||||
docID := e.TextDocumentIdentifier(buf.path)
|
||||
if e.Server != nil {
|
||||
if err := e.Server.WillSave(ctx, &protocol.WillSaveTextDocumentParams{
|
||||
TextDocument: docID,
|
||||
|
@ -693,7 +693,7 @@ func (e *Editor) setBufferContentLocked(ctx context.Context, path string, dirty
|
|||
params := &protocol.DidChangeTextDocumentParams{
|
||||
TextDocument: protocol.VersionedTextDocumentIdentifier{
|
||||
Version: int32(buf.version),
|
||||
TextDocumentIdentifier: e.textDocumentIdentifier(buf.path),
|
||||
TextDocumentIdentifier: e.TextDocumentIdentifier(buf.path),
|
||||
},
|
||||
ContentChanges: evts,
|
||||
}
|
||||
|
@ -1008,7 +1008,7 @@ func (e *Editor) CodeLens(ctx context.Context, path string) ([]protocol.CodeLens
|
|||
return nil, fmt.Errorf("buffer %q is not open", path)
|
||||
}
|
||||
params := &protocol.CodeLensParams{
|
||||
TextDocument: e.textDocumentIdentifier(path),
|
||||
TextDocument: e.TextDocumentIdentifier(path),
|
||||
}
|
||||
lens, err := e.Server.CodeLens(ctx, params)
|
||||
if err != nil {
|
||||
|
@ -1030,7 +1030,7 @@ func (e *Editor) Completion(ctx context.Context, path string, pos Pos) (*protoco
|
|||
}
|
||||
params := &protocol.CompletionParams{
|
||||
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
|
||||
TextDocument: e.textDocumentIdentifier(path),
|
||||
TextDocument: e.TextDocumentIdentifier(path),
|
||||
Position: pos.ToProtocolPosition(),
|
||||
},
|
||||
}
|
||||
|
@ -1080,7 +1080,7 @@ func (e *Editor) InlayHint(ctx context.Context, path string) ([]protocol.InlayHi
|
|||
return nil, fmt.Errorf("buffer %q is not open", path)
|
||||
}
|
||||
params := &protocol.InlayHintParams{
|
||||
TextDocument: e.textDocumentIdentifier(path),
|
||||
TextDocument: e.TextDocumentIdentifier(path),
|
||||
}
|
||||
hints, err := e.Server.InlayHint(ctx, params)
|
||||
if err != nil {
|
||||
|
@ -1102,7 +1102,7 @@ func (e *Editor) References(ctx context.Context, path string, pos Pos) ([]protoc
|
|||
}
|
||||
params := &protocol.ReferenceParams{
|
||||
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
|
||||
TextDocument: e.textDocumentIdentifier(path),
|
||||
TextDocument: e.TextDocumentIdentifier(path),
|
||||
Position: pos.ToProtocolPosition(),
|
||||
},
|
||||
Context: protocol.ReferenceContext{
|
||||
|
@ -1121,7 +1121,7 @@ func (e *Editor) Rename(ctx context.Context, path string, pos Pos, newName strin
|
|||
return nil
|
||||
}
|
||||
params := &protocol.RenameParams{
|
||||
TextDocument: e.textDocumentIdentifier(path),
|
||||
TextDocument: e.TextDocumentIdentifier(path),
|
||||
Position: pos.ToProtocolPosition(),
|
||||
NewName: newName,
|
||||
}
|
||||
|
@ -1195,7 +1195,7 @@ func (e *Editor) CodeAction(ctx context.Context, path string, rng *protocol.Rang
|
|||
return nil, fmt.Errorf("buffer %q is not open", path)
|
||||
}
|
||||
params := &protocol.CodeActionParams{
|
||||
TextDocument: e.textDocumentIdentifier(path),
|
||||
TextDocument: e.TextDocumentIdentifier(path),
|
||||
Context: protocol.CodeActionContext{
|
||||
Diagnostics: diagnostics,
|
||||
},
|
||||
|
|
|
@ -204,6 +204,7 @@ type ClientOptions struct {
|
|||
RelatedInformationSupported bool
|
||||
CompletionTags bool
|
||||
CompletionDeprecated bool
|
||||
SupportedResourceOperations []protocol.ResourceOperationKind
|
||||
}
|
||||
|
||||
// ServerOptions holds LSP-specific configuration that is provided by the
|
||||
|
@ -701,6 +702,9 @@ func SetOptions(options *Options, opts interface{}) OptionResults {
|
|||
|
||||
func (o *Options) ForClientCapabilities(caps protocol.ClientCapabilities) {
|
||||
// Check if the client supports snippets in completion items.
|
||||
if caps.Workspace.WorkspaceEdit != nil {
|
||||
o.SupportedResourceOperations = caps.Workspace.WorkspaceEdit.ResourceOperations
|
||||
}
|
||||
if c := caps.TextDocument.Completion; c.CompletionItem.SnippetSupport {
|
||||
o.InsertTextFormat = protocol.SnippetTextFormat
|
||||
}
|
||||
|
|
|
@ -49,6 +49,29 @@ type PrepareItem struct {
|
|||
// the prepare fails. Probably we could eliminate the redundancy in returning
|
||||
// two errors, but for now this is done defensively.
|
||||
func PrepareRename(ctx context.Context, snapshot Snapshot, f FileHandle, pp protocol.Position) (_ *PrepareItem, usererr, err error) {
|
||||
fileRenameSupported := false
|
||||
for _, op := range snapshot.View().Options().SupportedResourceOperations {
|
||||
if op == protocol.Rename {
|
||||
fileRenameSupported = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find position of the package name declaration
|
||||
pgf, err := snapshot.ParseGo(ctx, f, ParseFull)
|
||||
if err != nil {
|
||||
return nil, err, err
|
||||
}
|
||||
inPackageName, err := isInPackageName(ctx, snapshot, f, pgf, pp)
|
||||
if err != nil {
|
||||
return nil, err, err
|
||||
}
|
||||
|
||||
if inPackageName && !fileRenameSupported {
|
||||
err := errors.New("can't rename packages: LSP client does not support file renaming")
|
||||
return nil, err, err
|
||||
}
|
||||
|
||||
ctx, done := event.Start(ctx, "source.PrepareRename")
|
||||
defer done()
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче