feat(lsp): completion opts support custom item conversion (#30060)

Problem: Some items of completion results include function signatures that can
cause the pum to be very long when a function has many params, because pum
scales with the longest word/abbr.

Solution: add custom covert function that can customise abbr to remove params.
This commit is contained in:
glepnir 2024-08-23 03:42:27 +08:00 committed by GitHub
parent e48179f31e
commit 1f5bcc7c4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 38 additions and 6 deletions

View File

@ -1630,6 +1630,9 @@ Lua module: vim.lsp.completion *lsp-completion*
Fields: ~ Fields: ~
• {autotrigger}? (`boolean`) Whether to trigger completion • {autotrigger}? (`boolean`) Whether to trigger completion
automatically. Default: false automatically. Default: false
• {convert}? (`fun(item: lsp.CompletionItem): table`) An optional
function used to customize the transformation of an
LSP CompletionItem to |complete-items|.
*vim.lsp.completion.enable()* *vim.lsp.completion.enable()*

View File

@ -65,7 +65,9 @@ EVENTS
LSP LSP
• TODO • Add convert field in |vim.lsp.completion.BufferOpts| of
|vim.lsp.completion.enable()| an optional function used to customize the
transformation of an Lsp CompletionItem to |complete-items|.
LUA LUA

View File

@ -23,6 +23,7 @@ local ns_to_ms = 0.000001
--- @class vim.lsp.completion.BufHandle --- @class vim.lsp.completion.BufHandle
--- @field clients table<integer, vim.lsp.Client> --- @field clients table<integer, vim.lsp.Client>
--- @field triggers table<string, vim.lsp.Client[]> --- @field triggers table<string, vim.lsp.Client[]>
--- @field convert? fun(item: lsp.CompletionItem): table
--- @type table<integer, vim.lsp.completion.BufHandle> --- @type table<integer, vim.lsp.completion.BufHandle>
local buf_handles = {} local buf_handles = {}
@ -250,6 +251,8 @@ function M._lsp_to_complete_items(result, prefix, client_id)
end end
local candidates = {} local candidates = {}
local bufnr = api.nvim_get_current_buf()
local user_convert = vim.tbl_get(buf_handles, bufnr, 'convert')
for _, item in ipairs(items) do for _, item in ipairs(items) do
if matches(item) then if matches(item) then
local word = get_completion_word(item) local word = get_completion_word(item)
@ -260,7 +263,7 @@ function M._lsp_to_complete_items(result, prefix, client_id)
then then
hl_group = 'DiagnosticDeprecated' hl_group = 'DiagnosticDeprecated'
end end
table.insert(candidates, { local completion_item = {
word = word, word = word,
abbr = item.label, abbr = item.label,
kind = protocol.CompletionItemKind[item.kind] or 'Unknown', kind = protocol.CompletionItemKind[item.kind] or 'Unknown',
@ -278,7 +281,11 @@ function M._lsp_to_complete_items(result, prefix, client_id)
}, },
}, },
}, },
}) }
if user_convert then
completion_item = vim.tbl_extend('keep', user_convert(item), completion_item)
end
table.insert(candidates, completion_item)
end end
end end
---@diagnostic disable-next-line: no-unknown ---@diagnostic disable-next-line: no-unknown
@ -590,14 +597,15 @@ end
--- @class vim.lsp.completion.BufferOpts --- @class vim.lsp.completion.BufferOpts
--- @field autotrigger? boolean Whether to trigger completion automatically. Default: false --- @field autotrigger? boolean Whether to trigger completion automatically. Default: false
--- @field convert? fun(item: lsp.CompletionItem): table An optional function used to customize the transformation of an LSP CompletionItem to |complete-items|.
--- @param client_id integer ---@param client_id integer
---@param bufnr integer ---@param bufnr integer
---@param opts vim.lsp.completion.BufferOpts ---@param opts vim.lsp.completion.BufferOpts
local function enable_completions(client_id, bufnr, opts) local function enable_completions(client_id, bufnr, opts)
local buf_handle = buf_handles[bufnr] local buf_handle = buf_handles[bufnr]
if not buf_handle then if not buf_handle then
buf_handle = { clients = {}, triggers = {} } buf_handle = { clients = {}, triggers = {}, convert = opts.convert }
buf_handles[bufnr] = buf_handle buf_handles[bufnr] = buf_handle
-- Attach to buffer events. -- Attach to buffer events.

View File

@ -495,7 +495,9 @@ describe('vim.lsp.completion: protocol', function()
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr) vim.api.nvim_win_set_buf(0, bufnr)
return vim.lsp.start({ name = 'dummy', cmd = server.cmd, on_attach = function(client, bufnr) return vim.lsp.start({ name = 'dummy', cmd = server.cmd, on_attach = function(client, bufnr)
vim.lsp.completion.enable(true, client.id, bufnr) vim.lsp.completion.enable(true, client.id, bufnr, { convert = function(item)
return { abbr = item.label:gsub('%b()', '')}
end})
end}) end})
]], ]],
completion_result completion_result
@ -700,4 +702,21 @@ describe('vim.lsp.completion: protocol', function()
eq(true, exec_lua('return _G.called')) eq(true, exec_lua('return _G.called'))
end) end)
end) end)
it('custom word/abbar format', function()
create_server({
isIncomplete = false,
items = {
{
label = 'foo(bar)',
},
},
})
feed('ifo')
trigger_at_pos({ 1, 1 })
assert_matches(function(matches)
eq('foo', matches[1].abbr)
end)
end)
end) end)