mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
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
This commit is contained in:

committed by
Mathias Fußenegger

parent
c091bc3b9a
commit
f20335a54c
@@ -610,13 +610,14 @@ local function on_complete_done()
|
|||||||
clear_word()
|
clear_word()
|
||||||
if err then
|
if err then
|
||||||
vim.notify_once(err.message, vim.log.levels.WARN)
|
vim.notify_once(err.message, vim.log.levels.WARN)
|
||||||
elseif result and result.additionalTextEdits then
|
elseif result then
|
||||||
|
if result.additionalTextEdits then
|
||||||
lsp.util.apply_text_edits(result.additionalTextEdits, bufnr, position_encoding)
|
lsp.util.apply_text_edits(result.additionalTextEdits, bufnr, position_encoding)
|
||||||
|
end
|
||||||
if result.command then
|
if result.command then
|
||||||
completion_item.command = result.command
|
completion_item.command = result.command
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
apply_snippet_and_command()
|
apply_snippet_and_command()
|
||||||
end, bufnr)
|
end, bufnr)
|
||||||
else
|
else
|
||||||
|
@@ -458,6 +458,7 @@ function protocol.make_client_capabilities()
|
|||||||
resolveSupport = {
|
resolveSupport = {
|
||||||
properties = {
|
properties = {
|
||||||
'additionalTextEdits',
|
'additionalTextEdits',
|
||||||
|
'command',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tagSupport = {
|
tagSupport = {
|
||||||
|
@@ -770,20 +770,25 @@ end)
|
|||||||
|
|
||||||
--- @param name string
|
--- @param name string
|
||||||
--- @param completion_result lsp.CompletionList
|
--- @param completion_result lsp.CompletionList
|
||||||
--- @param trigger_chars? string[]
|
--- @param opts? {trigger_chars?: string[], resolve_result?: lsp.CompletionItem}
|
||||||
--- @return integer
|
--- @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()
|
return exec_lua(function()
|
||||||
local server = _G._create_server({
|
local server = _G._create_server({
|
||||||
capabilities = {
|
capabilities = {
|
||||||
completionProvider = {
|
completionProvider = {
|
||||||
triggerCharacters = trigger_chars or { '.' },
|
triggerCharacters = opts.trigger_chars or { '.' },
|
||||||
|
resolveProvider = opts.resolve_result ~= nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
handlers = {
|
handlers = {
|
||||||
['textDocument/completion'] = function(_, _, callback)
|
['textDocument/completion'] = function(_, _, callback)
|
||||||
callback(nil, completion_result)
|
callback(nil, completion_result)
|
||||||
end,
|
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,
|
cmd = server.cmd,
|
||||||
on_attach = function(client, bufnr0)
|
on_attach = function(client, bufnr0)
|
||||||
vim.lsp.completion.enable(true, client.id, bufnr0, {
|
vim.lsp.completion.enable(true, client.id, bufnr0, {
|
||||||
autotrigger = trigger_chars ~= nil,
|
autotrigger = opts.trigger_chars ~= nil,
|
||||||
convert = function(item)
|
convert = function(item)
|
||||||
return { abbr = item.label:gsub('%b()', '') }
|
return { abbr = item.label:gsub('%b()', '') }
|
||||||
end,
|
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 = {
|
local results2 = {
|
||||||
isIncomplete = false,
|
isIncomplete = false,
|
||||||
items = {
|
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')
|
feed('h')
|
||||||
exec_lua(function()
|
exec_lua(function()
|
||||||
@@ -1042,6 +1047,59 @@ describe('vim.lsp.completion: protocol', function()
|
|||||||
end)
|
end)
|
||||||
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()
|
it('enable(…,{convert=fn}) custom word/abbr format', function()
|
||||||
create_server('dummy', {
|
create_server('dummy', {
|
||||||
isIncomplete = false,
|
isIncomplete = false,
|
||||||
|
Reference in New Issue
Block a user