From: Yegappan Lakshmanan Date: Sun, 6 Nov 2022 01:11:44 +0000 (-0700) Subject: Add support for adding custom handlers for LSP code-action commands X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=a575feb8d48d461b463b6604e842711c392c0d62;p=vim-lsp.git Add support for adding custom handlers for LSP code-action commands --- diff --git a/autoload/lsp/codeaction.vim b/autoload/lsp/codeaction.vim index 02bf7cd..862c4ac 100644 --- a/autoload/lsp/codeaction.vim +++ b/autoload/lsp/codeaction.vim @@ -6,6 +6,21 @@ import './util.vim' import './textedit.vim' import './options.vim' as opt +var CommandHandlers: dict + +export def RegisterCmdHandler(cmd: string, Handler: func) + CommandHandlers[cmd] = Handler +enddef + +def DoCommand(lspserver: dict, cmd: dict) + if CommandHandlers->has_key(cmd.command) + var CmdHandler: func = CommandHandlers[cmd.command] + call CmdHandler(cmd) + else + lspserver.executeCommand(cmd) + endif +enddef + export def HandleCodeAction(lspserver: dict, selAction: dict) # textDocument/codeAction can return either Command[] or CodeAction[]. # If it is a CodeAction, it can have either an edit, a command or both. @@ -20,11 +35,11 @@ export def HandleCodeAction(lspserver: dict, selAction: dict) textedit.ApplyWorkspaceEdit(selAction.edit) endif if selAction->has_key('command') - lspserver.executeCommand(selAction.command) + DoCommand(lspserver, selAction.command) endif else # selAction is a Command instance, apply it directly - lspserver.executeCommand(selAction) + DoCommand(lspserver, selAction) endif enddef diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index 80a42bf..4f62aaf 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -16,6 +16,7 @@ import './diag.vim' import './symbol.vim' import './outline.vim' import './signature.vim' +import './codeaction.vim' # LSP server information var lspServers: list> = [] @@ -999,4 +1000,8 @@ export def TagFunc(pat: string, flags: string, info: dict): any return lspserver.tagFunc(pat, flags, info) enddef +export def RegisterCmdHandler(cmd: string, Handler: func) + codeaction.RegisterCmdHandler(cmd, Handler) +enddef + # vim: tabstop=8 shiftwidth=2 softtabstop=2 diff --git a/autoload/lsp/textedit.vim b/autoload/lsp/textedit.vim index 22f5485..31bc368 100644 --- a/autoload/lsp/textedit.vim +++ b/autoload/lsp/textedit.vim @@ -210,10 +210,9 @@ export def ApplyWorkspaceEdit(workspaceEdit: dict) var save_cursor: list = getcurpos() for [uri, changes] in workspaceEdit.changes->items() - var fname: string = util.LspUriToFile(uri) - var bnr: number = fname->bufnr() - if bnr == -1 - # file is already removed + var bnr: number = util.LspUriToBufnr(uri) + if bnr == 0 + # file is not present continue endif diff --git a/autoload/lsp/util.vim b/autoload/lsp/util.vim index 25701e3..d982536 100644 --- a/autoload/lsp/util.vim +++ b/autoload/lsp/util.vim @@ -69,6 +69,13 @@ export def LspUriToFile(uri: string): string return uri_decoded enddef +# Convert a LSP file URI (file://) to a Vim buffer number. +# If the file is not in a Vim buffer, then adds the buffer. +# Returns 0 on error. +export def LspUriToBufnr(uri: string): number + return LspUriToFile(uri)->bufadd() +enddef + # Returns if the URI refers to a remote file (e.g. ssh://) # Credit: vim-lsp plugin export def LspUriRemote(uri: string): bool diff --git a/doc/lsp.txt b/doc/lsp.txt index 57c1e11..e060637 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -761,4 +761,30 @@ use the :LspServerTrace command to set the trace value: > :LspServerTrace { off | messages | verbose } < +============================================================================== +11. Custom Command Handlers *lsp-custom-commands* + +When applying a code action, the language server may issue a non-standard +command. For example, the Java language server uses non-standard commands +(e.g. java.apply.workspaceEdit). To handle these commands, you can register a +callback function for each command using the LspRegisterCmdHandler() function. +For example: > + + vim9script + import "../../lsp/autoload/lsp/textedit.vim" + + def WorkspaceEdit(cmd: dict) + for editAct in cmd.arguments + textedit.ApplyWorkspaceEdit(editAct) + endfor + enddef + g:LspRegisterCmdHandler('java.apply.worksspaceEdit', WorkspaceEdit) +< +Place the above code in a file named lsp_java/plugin/lsp_java.vim and load +this plugin. + +The callback function should accept a Dict argument. The Dict argument +contains the LSP Command interface fields. Refer to the LSP specification for +more information about the "Command" interface. + vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/plugin/lsp.vim b/plugin/lsp.vim index 27b6250..936fdc3 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -18,6 +18,10 @@ def g:LspAddServer(serverList: list>) lsp.AddServer(serverList) enddef +def g:LspRegisterCmdHandler(cmd: string, Handler: func) + lsp.RegisterCmdHandler(cmd, Handler) +enddef + # Returns true if the language server for the current buffer is initialized # and ready to accept requests. def g:LspServerReady(): bool