perf(lsp): don't copy completion items in filter pass

This commit is contained in:
Mathias Fussenegger
2024-05-30 10:24:54 +02:00
committed by Mathias Fußenegger
parent 1d091e52f0
commit cc1f2d2ca6

View File

@ -201,6 +201,24 @@ local function get_items(result)
end end
end end
---@param item lsp.CompletionItem
---@return string
local function get_doc(item)
local doc = item.documentation
if not doc then
return ''
end
if type(doc) == 'string' then
return doc
end
if type(doc) == 'table' and type(doc.value) == 'string' then
return doc.value
end
vim.notify('invalid documentation value: ' .. vim.inspect(doc), vim.log.levels.WARN)
return ''
end
--- Turns the result of a `textDocument/completion` request into vim-compatible --- Turns the result of a `textDocument/completion` request into vim-compatible
--- |complete-items|. --- |complete-items|.
--- ---
@ -216,44 +234,24 @@ function M._lsp_to_complete_items(result, prefix, client_id)
return {} return {}
end end
if prefix ~= '' then local matches = prefix == '' and function()
---@param item lsp.CompletionItem return true
local function match_prefix(item) end or function(item)
if item.filterText then if item.filterText then
return next(vim.fn.matchfuzzy({ item.filterText }, prefix)) return next(vim.fn.matchfuzzy({ item.filterText }, prefix))
end end
return true return true
end end
local candidates = {}
items = vim.tbl_filter(match_prefix, items) --[[@as lsp.CompletionItem[]|]]
end
table.sort(items, function(a, b)
return (a.sortText or a.label) < (b.sortText or b.label)
end)
local matches = {}
for _, item in ipairs(items) do for _, item in ipairs(items) do
local info = '' if matches(item) then
local documentation = item.documentation
if documentation then
if type(documentation) == 'string' and documentation ~= '' then
info = documentation
elseif type(documentation) == 'table' and type(documentation.value) == 'string' then
info = documentation.value
else
vim.notify(
('invalid documentation value %s'):format(vim.inspect(documentation)),
vim.log.levels.WARN
)
end
end
local word = get_completion_word(item) local word = get_completion_word(item)
table.insert(matches, { table.insert(candidates, {
word = word, word = word,
abbr = item.label, abbr = item.label,
kind = protocol.CompletionItemKind[item.kind] or 'Unknown', kind = protocol.CompletionItemKind[item.kind] or 'Unknown',
menu = item.detail or '', menu = item.detail or '',
info = #info > 0 and info or '', info = get_doc(item),
icase = 1, icase = 1,
dup = 1, dup = 1,
empty = 1, empty = 1,
@ -267,7 +265,17 @@ function M._lsp_to_complete_items(result, prefix, client_id)
}, },
}) })
end end
return matches end
---@diagnostic disable-next-line: no-unknown
table.sort(candidates, function(a, b)
---@type lsp.CompletionItem
local itema = a.user_data.nvim.lsp.completion_item
---@type lsp.CompletionItem
local itemb = b.user_data.nvim.lsp.completion_item
return (itema.sortText or itema.label) < (itemb.sortText or itemb.label)
end)
return candidates
end end
--- @param lnum integer 0-indexed --- @param lnum integer 0-indexed