mirror of
https://github.com/neovim/neovim.git
synced 2025-12-19 12:55:32 +00:00
lsp: fix textDocument/completion handling
fix: #11826 Some lanuguage servers return complementary candidates whose prefixes do not match are also returned. So we exclude completion candidates whose prefix does not match. ex) Microsoft python-language-server, rust-analyzer
This commit is contained in:
@@ -945,12 +945,14 @@ function lsp.omnifunc(findstart, base)
|
|||||||
|
|
||||||
-- Get the start position of the current keyword
|
-- Get the start position of the current keyword
|
||||||
local textMatch = vim.fn.match(line_to_cursor, '\\k*$')
|
local textMatch = vim.fn.match(line_to_cursor, '\\k*$')
|
||||||
|
local prefix = line_to_cursor:sub(textMatch+1)
|
||||||
|
|
||||||
local params = util.make_position_params()
|
local params = util.make_position_params()
|
||||||
|
|
||||||
local items = {}
|
local items = {}
|
||||||
lsp.buf_request(bufnr, 'textDocument/completion', params, function(err, _, result)
|
lsp.buf_request(bufnr, 'textDocument/completion', params, function(err, _, result)
|
||||||
if err or not result then return end
|
if err or not result then return end
|
||||||
local matches = util.text_document_completion_list_to_complete_items(result)
|
local matches = util.text_document_completion_list_to_complete_items(result, prefix)
|
||||||
-- TODO(ashkan): is this the best way to do this?
|
-- TODO(ashkan): is this the best way to do this?
|
||||||
vim.list_extend(items, matches)
|
vim.list_extend(items, matches)
|
||||||
vim.fn.complete(textMatch+1, items)
|
vim.fn.complete(textMatch+1, items)
|
||||||
|
|||||||
@@ -63,8 +63,9 @@ M['textDocument/completion'] = function(_, _, result)
|
|||||||
local line = assert(api.nvim_buf_get_lines(0, row-1, row, false)[1])
|
local line = assert(api.nvim_buf_get_lines(0, row-1, row, false)[1])
|
||||||
local line_to_cursor = line:sub(col+1)
|
local line_to_cursor = line:sub(col+1)
|
||||||
local textMatch = vim.fn.match(line_to_cursor, '\\k*$')
|
local textMatch = vim.fn.match(line_to_cursor, '\\k*$')
|
||||||
|
local prefix = line_to_cursor:sub(textMatch+1)
|
||||||
|
|
||||||
local matches = util.text_document_completion_list_to_complete_items(result)
|
local matches = util.text_document_completion_list_to_complete_items(result, prefix)
|
||||||
vim.fn.complete(textMatch+1, matches)
|
vim.fn.complete(textMatch+1, matches)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,19 @@ function M.extract_completion_items(result)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Some lanuguage servers return complementary candidates whose prefixes do not match are also returned.
|
||||||
|
-- So we exclude completion candidates whose prefix does not match.
|
||||||
|
function M.remove_unmatch_completion_items(items, prefix)
|
||||||
|
local matched_items = {}
|
||||||
|
for _, item in ipairs(items) do
|
||||||
|
local word = item.insertText or item.label
|
||||||
|
if vim.startswith(word, prefix) then
|
||||||
|
table.insert(matched_items, item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return matched_items
|
||||||
|
end
|
||||||
|
|
||||||
--- Apply the TextDocumentEdit response.
|
--- Apply the TextDocumentEdit response.
|
||||||
-- @params TextDocumentEdit [table] see https://microsoft.github.io/language-server-protocol/specification
|
-- @params TextDocumentEdit [table] see https://microsoft.github.io/language-server-protocol/specification
|
||||||
function M.apply_text_document_edit(text_document_edit)
|
function M.apply_text_document_edit(text_document_edit)
|
||||||
@@ -151,12 +164,14 @@ end
|
|||||||
--- Getting vim complete-items with incomplete flag.
|
--- Getting vim complete-items with incomplete flag.
|
||||||
-- @params CompletionItem[], CompletionList or nil (https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
|
-- @params CompletionItem[], CompletionList or nil (https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
|
||||||
-- @return { matches = complete-items table, incomplete = boolean }
|
-- @return { matches = complete-items table, incomplete = boolean }
|
||||||
function M.text_document_completion_list_to_complete_items(result)
|
function M.text_document_completion_list_to_complete_items(result, prefix)
|
||||||
local items = M.extract_completion_items(result)
|
local items = M.extract_completion_items(result)
|
||||||
if vim.tbl_isempty(items) then
|
if vim.tbl_isempty(items) then
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
items = M.remove_unmatch_completion_items(items, prefix)
|
||||||
|
|
||||||
local matches = {}
|
local matches = {}
|
||||||
|
|
||||||
for _, completion_item in ipairs(items) do
|
for _, completion_item in ipairs(items) do
|
||||||
|
|||||||
Reference in New Issue
Block a user