aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Fußenegger <mfussenegger@users.noreply.github.com>2023-10-02 22:14:19 +0200
committerGitHub <noreply@github.com>2023-10-02 22:14:19 +0200
commit4a09c178a19097c295521892c889f1f196fff100 (patch)
treeaaf1d51961f674e08cb9f52d57d1b733b7695224
parent09a17f91d0d362c6e58bfdbe3ccdeacffb0b44b9 (diff)
downloadrneovim-4a09c178a19097c295521892c889f1f196fff100.tar.gz
rneovim-4a09c178a19097c295521892c889f1f196fff100.tar.bz2
rneovim-4a09c178a19097c295521892c889f1f196fff100.zip
feat(lsp): fallback to code-action command on resolve failure (#25464)
The haskell-language-server supports resolve only for a subset of code actions. For many code actions trying to resolve the `edit` property results in an error, but the unresolved action already contains a command that can be executed without issue. The protocol specification is unfortunately a bit vague about this, and what the haskell-language-server does seems to be valid. Example: newtype Dummy = Dummy Int instance Num Dummy where Triggering code actions on "Num Dummy" and choosing "Add placeholders for all missing methods" resulted in: -32601: No plugin enabled for SMethod_CodeActionResolve, potentially available: explicit-fields, importLens, hlint, overloaded-record-dot With this change it will insert the missing methods: instance Num Dummy where (+) = _ (-) = _ (*) = _ negate = _ abs = _ signum = _ fromInteger = _
-rw-r--r--runtime/lua/vim/lsp/buf.lua12
-rw-r--r--test/functional/plugin/lsp_spec.lua44
2 files changed, 52 insertions, 4 deletions
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 8a29fac2b5..a906512e24 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -652,7 +652,7 @@ local function on_code_action_results(results, ctx, options)
-- arguments?: any[]
--
---@type lsp.Client
- local client = vim.lsp.get_client_by_id(action_tuple[1])
+ local client = assert(vim.lsp.get_client_by_id(action_tuple[1]))
local action = action_tuple[2]
local reg = client.dynamic_capabilities:get(ms.textDocument_codeAction, { bufnr = ctx.bufnr })
@@ -663,10 +663,14 @@ local function on_code_action_results(results, ctx, options)
if not action.edit and client and supports_resolve then
client.request(ms.codeAction_resolve, action, function(err, resolved_action)
if err then
- vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
- return
+ if action.command then
+ apply_action(action, client)
+ else
+ vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
+ end
+ else
+ apply_action(resolved_action, client)
end
- apply_action(resolved_action, client)
end, ctx.bufnr)
else
apply_action(action, client)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 155c9ad96c..ef08860f10 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -3483,6 +3483,50 @@ describe('LSP', function()
end
}
end)
+ it("Fallback to command execution on resolve error", function()
+ clear()
+ exec_lua(create_server_definition)
+ local result = exec_lua([[
+ local server = _create_server({
+ capabilities = {
+ executeCommandProvider = {
+ commands = {"command:1"},
+ },
+ codeActionProvider = {
+ resolveProvider = true
+ }
+ },
+ handlers = {
+ ["textDocument/codeAction"] = function()
+ return {
+ {
+ title = "Code Action 1",
+ command = {
+ title = "Command 1",
+ command = "command:1",
+ }
+ }
+ }
+ end,
+ ["codeAction/resolve"] = function()
+ return nil, "resolve failed"
+ end,
+ }
+ })
+
+ local client_id = vim.lsp.start({
+ name = "dummy",
+ cmd = server.cmd,
+ })
+
+ vim.lsp.buf.code_action({ apply = true })
+ vim.lsp.stop_client(client_id)
+ return server.messages
+ ]])
+ eq("codeAction/resolve", result[4].method)
+ eq("workspace/executeCommand", result[5].method)
+ eq("command:1", result[5].params.command)
+ end)
end)
describe('vim.lsp.commands', function()
it('Accepts only string keys', function()