Skip to content

Commit

Permalink
feat: add handler for document prepare rename requests
Browse files Browse the repository at this point in the history
  • Loading branch information
fr3shw3b committed Jun 24, 2024
1 parent b32eb8a commit d4647d1
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions lsp_3_17/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type Handler struct {
documentRangeFormatting DocumentRangeFormattingHandlerFunc
documentOnTypeFormatting DocumentOnTypeFormattingHandlerFunc
documentRename DocumentRenameHandlerFunc
documentPrepareRename DocumentPrepareRenameHandlerFunc

isInitialized bool
// Provides a mapping of method names to the respective handlers
Expand Down
34 changes: 34 additions & 0 deletions lsp_3_17/handler_language_features.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,14 @@ func WithDocumentRenameHandler(handler DocumentRenameHandlerFunc) HandlerOption
}
}

// WithDocumentPrepareRenameHandler sets the handler for the
// `textDocument/prepareRename` request.
func WithDocumentPrepareRenameHandler(handler DocumentPrepareRenameHandlerFunc) HandlerOption {
return func(root *Handler) {
root.SetDocumentPrepareRenameHandler(handler)
}
}

// SetGotoDeclarationHandler sets the handler for the `textDocument/declaration` request.
func (h *Handler) SetGotoDeclarationHandler(handler GotoDeclarationHandlerFunc) {
h.mu.Lock()
Expand Down Expand Up @@ -611,6 +619,14 @@ func (h *Handler) SetDocumentRenameHandler(handler DocumentRenameHandlerFunc) {
h.messageHandlers[MethodDocumentRename] = createDocumentRenameHandler(h)
}

// SetDocumentPrepareRenameHandler sets the handler for the `textDocument/prepareRename` request.
func (h *Handler) SetDocumentPrepareRenameHandler(handler DocumentPrepareRenameHandlerFunc) {
h.mu.Lock()
defer h.mu.Unlock()
h.documentPrepareRename = handler
h.messageHandlers[MethodDocumentPrepareRename] = createDocumentPrepareRenameHandler(h)
}

func createGotoDeclarationHandler(root *Handler) common.Handler {
return common.HandlerFunc(
func(
Expand Down Expand Up @@ -1330,3 +1346,21 @@ func createDocumentRenameHandler(root *Handler) common.Handler {
},
)
}

func createDocumentPrepareRenameHandler(root *Handler) common.Handler {
return common.HandlerFunc(
func(
ctx *common.LSPContext,
) (r any, validMethod bool, validParams bool, err error) {
validMethod = true
if root.documentPrepareRename != nil {
var params PrepareRenameParams
if err = json.Unmarshal(ctx.Params, &params); err == nil {
validParams = true
r, err = root.documentPrepareRename(ctx, &params)
}
}
return
},
)
}
59 changes: 59 additions & 0 deletions lsp_3_17/handler_language_features_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2547,3 +2547,62 @@ func (s *HandlerTestSuite) Test_calls_document_rename_request_handler() {
s.Require().NoError(err)
s.Require().Equal(workspaceEdit, returnedWorkspaceEdit)
}

func (s *HandlerTestSuite) Test_calls_document_prepare_rename_request_handler() {
logger, err := zap.NewDevelopment()
s.Require().NoError(err)

ctx, cancel := context.WithTimeout(context.Background(), server.DefaultTimeout)
defer cancel()

rangeWithPlaceholder := RangeWithPlaceholder{
Range: Range{
Start: Position{
Line: 300,
Character: 24,
},
End: Position{
Line: 300,
Character: 115,
},
},
Placeholder: "user.go",
}
serverHandler := NewHandler(
WithDocumentPrepareRenameHandler(
func(ctx *common.LSPContext, params *PrepareRenameParams) (any, error) {
return rangeWithPlaceholder, nil
},
),
)
// Emulate the LSP initialisation process.
serverHandler.SetInitialized(true)
srv := server.NewServer(serverHandler, true, nil, nil)

container := createTestConnectionsContainer(srv.NewHandler())

go srv.Serve(container.serverConn, logger)

clientLSPContext := server.NewLSPContext(ctx, container.clientConn, nil)

prepareRenameParams := &PrepareRenameParams{
TextDocumentPositionParams: TextDocumentPositionParams{
TextDocument: TextDocumentIdentifier{
URI: "file:///test_doc_prepare_rename.go",
},
Position: Position{
Line: 320,
Character: 24,
},
},
}

returnedRangeWithPlaceholder := RangeWithPlaceholder{}
err = clientLSPContext.Call(
MethodDocumentPrepareRename,
prepareRenameParams,
&returnedRangeWithPlaceholder,
)
s.Require().NoError(err)
s.Require().Equal(rangeWithPlaceholder, returnedRangeWithPlaceholder)
}
33 changes: 33 additions & 0 deletions lsp_3_17/language_features.go
Original file line number Diff line number Diff line change
Expand Up @@ -2946,3 +2946,36 @@ type RenameParams struct {
// appropriate message set.
NewName string `json:"newName"`
}

// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename

const MethodDocumentPrepareRename = Method("textDocument/prepareRename")

// DocumentPrepareRenameHandlerFunc is the function signature for the textDocument/prepareRename
// request handler that can be registered for a language server.
//
// Returns: Range | RangeWithPlaceholder | PrepareRenameDefaultBehavior | nil
type DocumentPrepareRenameHandlerFunc func(
ctx *common.LSPContext,
params *PrepareRenameParams,
) (any, error)

// PrepareRenameParams contains parameters for the textDocument/prepareRename requests.
type PrepareRenameParams struct {
TextDocumentPositionParams
WorkDoneProgressParams
}

// RangeWithPlaceholder is a range with a placeholder
// which can be returned in the response for a textDocument/prepareRename
// request.
type RangeWithPlaceholder struct {
Range Range `json:"range"`
Placeholder string `json:"placeholder"`
}

// PrepareRenameDefaultBehavior is a default behavior which can be returned in the response
// for a textDocument/prepareRename request.
type PrepareRenameDefaultBehavior struct {
DefaultBehavior bool `json:"defaultBehavior"`
}

0 comments on commit d4647d1

Please sign in to comment.