diff options
author | Mathias Fussenegger <f.mathias@zignar.net> | 2025-02-14 14:06:47 +0100 |
---|---|---|
committer | Mathias Fußenegger <mfussenegger@users.noreply.github.com> | 2025-02-14 19:49:08 +0100 |
commit | f20335a54ce7f240902d4ee14d726620a38f95bc (patch) | |
tree | 40531a7feae68d6410b90a4bc2c30c93da1e1325 | |
parent | c091bc3b9abc220fa5d512966d89893f56f20691 (diff) | |
download | rneovim-f20335a54ce7f240902d4ee14d726620a38f95bc.tar.gz rneovim-f20335a54ce7f240902d4ee14d726620a38f95bc.tar.bz2 rneovim-f20335a54ce7f240902d4ee14d726620a38f95bc.zip |
feat(lsp): add support for completionItem.command resolving
`command` was already resolved via a `completionItem/resolve` request
but only if `additionalTextEdits` were also present, and the
`resolveSupport` capability wasn't listed.
Closes https://github.com/neovim/neovim/issues/32406
-rw-r--r-- | runtime/lua/vim/lsp/completion.lua | 7 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/protocol.lua | 1 | ||||
-rw-r--r-- | test/functional/plugin/lsp/completion_spec.lua | 70 |
3 files changed, 69 insertions, 9 deletions
diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index f287304508..d99b1ffd0d 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -610,13 +610,14 @@ local function on_complete_done() clear_word() if err then vim.notify_once(err.message, vim.log.levels.WARN) - elseif result and result.additionalTextEdits then - lsp.util.apply_text_edits(result.additionalTextEdits, bufnr, position_encoding) + elseif result then + if result.additionalTextEdits then + lsp.util.apply_text_edits(result.additionalTextEdits, bufnr, position_encoding) + end if result.command then completion_item.command = result.command end end - apply_snippet_and_command() end, bufnr) else diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index fbfd0cd6b0..33d029420b 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -458,6 +458,7 @@ function protocol.make_client_capabilities() resolveSupport = { properties = { 'additionalTextEdits', + 'command', }, }, tagSupport = { diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 33c025daba..d101e68273 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -770,20 +770,25 @@ end) --- @param name string --- @param completion_result lsp.CompletionList ---- @param trigger_chars? string[] +--- @param opts? {trigger_chars?: string[], resolve_result?: lsp.CompletionItem} --- @return integer -local function create_server(name, completion_result, trigger_chars) +local function create_server(name, completion_result, opts) + opts = opts or {} return exec_lua(function() local server = _G._create_server({ capabilities = { completionProvider = { - triggerCharacters = trigger_chars or { '.' }, + triggerCharacters = opts.trigger_chars or { '.' }, + resolveProvider = opts.resolve_result ~= nil, }, }, handlers = { ['textDocument/completion'] = function(_, _, callback) callback(nil, completion_result) end, + ['completionItem/resolve'] = function(_, _, callback) + callback(nil, opts.resolve_result) + end, }, }) @@ -794,7 +799,7 @@ local function create_server(name, completion_result, trigger_chars) cmd = server.cmd, on_attach = function(client, bufnr0) vim.lsp.completion.enable(true, client.id, bufnr0, { - autotrigger = trigger_chars ~= nil, + autotrigger = opts.trigger_chars ~= nil, convert = function(item) return { abbr = item.label:gsub('%b()', '') } end, @@ -968,7 +973,7 @@ describe('vim.lsp.completion: protocol', function() }, }, } - create_server('dummy1', results1, { 'e' }) + create_server('dummy1', results1, { trigger_chars = { 'e' } }) local results2 = { isIncomplete = false, items = { @@ -977,7 +982,7 @@ describe('vim.lsp.completion: protocol', function() }, }, } - create_server('dummy2', results2, { 'h' }) + create_server('dummy2', results2, { trigger_chars = { 'h' } }) feed('h') exec_lua(function() @@ -1042,6 +1047,59 @@ describe('vim.lsp.completion: protocol', function() end) end) + it('resolves and executes commands', function() + local completion_list = { + isIncomplete = false, + items = { + { + label = 'hello', + }, + }, + } + local client_id = create_server('dummy', completion_list, { + resolve_result = { + label = 'hello', + command = { + arguments = { '1', '0' }, + command = 'dummy', + title = '', + }, + }, + }) + exec_lua(function() + _G.called = false + local client = assert(vim.lsp.get_client_by_id(client_id)) + client.commands.dummy = function() + _G.called = true + end + end) + + feed('ih') + trigger_at_pos({ 1, 1 }) + + local item = completion_list.items[1] + exec_lua(function() + vim.v.completed_item = { + user_data = { + nvim = { + lsp = { + client_id = client_id, + completion_item = item, + }, + }, + }, + } + end) + + feed('<C-x><C-o><C-y>') + + assert_matches(function(matches) + eq(1, #matches) + eq('hello', matches[1].word) + eq(true, exec_lua('return _G.called')) + end) + end) + it('enable(…,{convert=fn}) custom word/abbr format', function() create_server('dummy', { isIncomplete = false, |