Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Implement the 'textDocument/rename' command #337

Merged
merged 2 commits into from
Nov 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions langserver/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,15 @@ func (h *LangHandler) Handle(ctx context.Context, conn jsonrpc2.JSONRPC2, req *j
}
return h.handleWorkspaceReferences(ctx, conn, req, params)

case "textDocument/rename":
if req.Params == nil {
return nil, &jsonrpc2.Error{Code: jsonrpc2.CodeInvalidParams}
}
var params lsp.RenameParams
if err := json.Unmarshal(*req.Params, &params); err != nil {
return nil, err
}
return h.handleRename(ctx, conn, req, params)
default:
if isFileSystemRequest(req.Method) {
uri, fileChanged, err := h.handleFileSystemRequest(ctx, req)
Expand Down
69 changes: 69 additions & 0 deletions langserver/langserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,35 @@ func main() {
},
},
},
"renaming": {
rootURI: "file:///src/test/pkg",
fs: map[string]string{
"a.go": `package p
import "fmt"

func main() {
str := A()
fmt.Println(str)
}

func A() string {
return "test"
}
`,
},
cases: lspTestCases{
wantRenames: map[string]map[string]string{
"a.go:5:5": map[string]string{
"4:4-4:7": "/src/test/pkg/a.go",
"5:16-5:19": "/src/test/pkg/a.go",
},
"a.go:9:6": map[string]string{
"4:11-4:12": "/src/test/pkg/a.go",
"8:5-8:6": "/src/test/pkg/a.go",
},
},
},
},
}

func TestServer(t *testing.T) {
Expand Down Expand Up @@ -1314,6 +1343,7 @@ type lspTestCases struct {
wantSignatures map[string]string
wantWorkspaceReferences map[*lspext.WorkspaceReferencesParams][]string
wantFormatting map[string]map[string]string
wantRenames map[string]map[string]string
}

func copyFileToOS(ctx context.Context, fs *AtomicFS, targetFile, srcFile string) error {
Expand Down Expand Up @@ -1495,6 +1525,12 @@ func lspTests(t testing.TB, ctx context.Context, h *LangHandler, c *jsonrpc2.Con
formattingTest(t, ctx, c, rootURI, file, want)
})
}

for pos, want := range cases.wantRenames {
tbRun(t, fmt.Sprintf("renaming-%s", strings.Replace(pos, "/", "-", -1)), func(t testing.TB) {
renamingTest(t, ctx, c, rootURI, pos, want)
})
}
}

// tbRun calls (testing.T).Run or (testing.B).Run.
Expand Down Expand Up @@ -1716,6 +1752,29 @@ func formattingTest(t testing.TB, ctx context.Context, c *jsonrpc2.Conn, rootURI
}
}

func renamingTest(t testing.TB, ctx context.Context, c *jsonrpc2.Conn, rootURI lsp.DocumentURI, pos string, want map[string]string) {
file, line, char, err := parsePos(pos)
if err != nil {
t.Fatal(err)
}

workspaceEdit, err := callRenaming(ctx, c, uriJoin(rootURI, file), line, char, "")
if err != nil {
t.Fatal(err)
}

got := map[string]string{}
for file, edits := range workspaceEdit.Changes {
for _, edit := range edits {
got[edit.Range.String()] = util.UriToPath(lsp.DocumentURI(file))
}
}

if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want: %v", got, want)
}
}

func parsePos(s string) (file string, line, char int, err error) {
parts := strings.Split(s, ":")
if len(parts) != 3 {
Expand Down Expand Up @@ -1970,6 +2029,16 @@ func callFormatting(ctx context.Context, c *jsonrpc2.Conn, uri lsp.DocumentURI)
return edits, err
}

func callRenaming(ctx context.Context, c *jsonrpc2.Conn, uri lsp.DocumentURI, line, char int, newName string) (lsp.WorkspaceEdit, error) {
var edit lsp.WorkspaceEdit
err := c.Call(ctx, "textDocument/rename", lsp.RenameParams{
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
Position: lsp.Position{Line: line, Character: char},
NewName: newName,
}, &edit)
return edit, err
}

type markedStrings []lsp.MarkedString

func (v *markedStrings) UnmarshalJSON(data []byte) error {
Expand Down
45 changes: 45 additions & 0 deletions langserver/rename.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package langserver

import (
"context"

lsp "github.com/sourcegraph/go-lsp"
"github.com/sourcegraph/jsonrpc2"
)

func (h *LangHandler) handleRename(ctx context.Context, conn jsonrpc2.JSONRPC2,
req *jsonrpc2.Request, params lsp.RenameParams) (lsp.WorkspaceEdit, error) {
rp := lsp.ReferenceParams{
TextDocumentPositionParams: lsp.TextDocumentPositionParams{
TextDocument: params.TextDocument,
Position: params.Position,
},
Context: lsp.ReferenceContext{
IncludeDeclaration: true,
XLimit: 0,
},
}

references, err := h.handleTextDocumentReferences(ctx, conn, req, rp)
if err != nil {
return lsp.WorkspaceEdit{}, err
}

result := lsp.WorkspaceEdit{}
if result.Changes == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: result.Changes will always be nil here. Rather just initialize it

result.Changes = make(map[string][]lsp.TextEdit)
}
for _, ref := range references {
edit := lsp.TextEdit{
Range: ref.Range,
NewText: params.NewName,
}
edits := result.Changes[string(ref.URI)]
if edits == nil {
edits = []lsp.TextEdit{}
}
edits = append(edits, edit)
result.Changes[string(ref.URI)] = edits
}
return result, nil
}