]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Add support for adding custom handlers for LSP code-action commands
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 6 Nov 2022 01:11:44 +0000 (18:11 -0700)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 6 Nov 2022 01:11:44 +0000 (18:11 -0700)
autoload/lsp/codeaction.vim
autoload/lsp/lsp.vim
autoload/lsp/textedit.vim
autoload/lsp/util.vim
doc/lsp.txt
plugin/lsp.vim

index 02bf7cd8ce7e6433b73f4f39fa9fd9f030ccbe3d..862c4ac23005832a3149d550cf32281a0c4884b1 100644 (file)
@@ -6,6 +6,21 @@ import './util.vim'
 import './textedit.vim'
 import './options.vim' as opt
 
+var CommandHandlers: dict<func>
+
+export def RegisterCmdHandler(cmd: string, Handler: func)
+  CommandHandlers[cmd] = Handler
+enddef
+
+def DoCommand(lspserver: dict<any>, cmd: dict<any>)
+  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<any>, selAction: dict<any>)
   # 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<any>, selAction: dict<any>)
       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
 
index 80a42bf017465022220ad046ec45cabc61af2057..4f62aafd48cc66c20f94953a8d47c023bf332970 100644 (file)
@@ -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<dict<any>> = []
@@ -999,4 +1000,8 @@ export def TagFunc(pat: string, flags: string, info: dict<any>): 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
index 22f54856e9a366b66a7470134adeb4790779cff3..31bc3685af669746823a3c208783353199d7dd7d 100644 (file)
@@ -210,10 +210,9 @@ export def ApplyWorkspaceEdit(workspaceEdit: dict<any>)
 
   var save_cursor: list<number> = 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
 
index 25701e38bcb7c3a254dd3e31ac1dc702d39dde69..d98253617d115e01c5c6ab3d3f16fdcb4ffef2be 100644 (file)
@@ -69,6 +69,13 @@ export def LspUriToFile(uri: string): string
   return uri_decoded
 enddef
 
+# Convert a LSP file URI (file://<absolute_path>) 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
index 57c1e1155f06f7e6e68615c09e0f4b0b772f4276..e060637c8a20b0318035bbac124c559354bf177d 100644 (file)
@@ -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<any>)
+      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:
index 27b6250530d810c5e06333f5796d31b4d37abe01..936fdc3bc22c5e618304f2c18d6caad12a489a98 100644 (file)
@@ -18,6 +18,10 @@ def g:LspAddServer(serverList: list<dict<any>>)
   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