mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
feat(lsp): support completion itemDefaults
This commit is contained in:
parent
3d96e3f9f2
commit
63f9c2da9a
@ -125,6 +125,15 @@ The following changes may require adaptations in user config or plugins.
|
|||||||
• Returning any truthy value from a callback passed to |nvim_create_autocmd()|
|
• Returning any truthy value from a callback passed to |nvim_create_autocmd()|
|
||||||
(rather than just `true`) will delete the autocommand.
|
(rather than just `true`) will delete the autocommand.
|
||||||
|
|
||||||
|
• |vim.lsp.util.extract_completion_items()| will no longer return reliable
|
||||||
|
results, since it does not apply `itemDefaults` when its input is a
|
||||||
|
`CompletionList`.
|
||||||
|
Moreover, since support for LSP `completionList.itemDefaults` was added,
|
||||||
|
some third party plugins might be negatively impacted in case the language
|
||||||
|
servers support the feature but the plugin does not.
|
||||||
|
If necessary, the respective capability can be
|
||||||
|
removed when calling |vim.lsp.protocol.make_client_capabilities()|.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
BREAKING CHANGES IN HEAD *news-breaking-dev*
|
BREAKING CHANGES IN HEAD *news-breaking-dev*
|
||||||
|
|
||||||
@ -213,6 +222,11 @@ The following new APIs and features were added.
|
|||||||
the original LSP `Location` or `LocationLink`.
|
the original LSP `Location` or `LocationLink`.
|
||||||
• Added support for connecting to servers using named pipes (Windows) or
|
• Added support for connecting to servers using named pipes (Windows) or
|
||||||
unix domain sockets (Unix) via |vim.lsp.rpc.domain_socket_connect()|.
|
unix domain sockets (Unix) via |vim.lsp.rpc.domain_socket_connect()|.
|
||||||
|
• Added support for `completionList.itemDefaults`, reducing overhead when
|
||||||
|
computing completion items where properties often share the same value
|
||||||
|
(e.g. `commitCharacters`). Note that this might affect plugins and
|
||||||
|
language servers that don't support the feature, and in such cases the
|
||||||
|
respective capability can be unset.
|
||||||
|
|
||||||
• Treesitter
|
• Treesitter
|
||||||
• Bundled parsers and queries (highlight, folds) for Markdown, Python, and
|
• Bundled parsers and queries (highlight, folds) for Markdown, Python, and
|
||||||
|
@ -6,6 +6,14 @@ local ms = protocol.Methods
|
|||||||
|
|
||||||
--- @alias vim.lsp.CompletionResult lsp.CompletionList | lsp.CompletionItem[]
|
--- @alias vim.lsp.CompletionResult lsp.CompletionList | lsp.CompletionItem[]
|
||||||
|
|
||||||
|
-- TODO(mariasolos): Remove this declaration once we figure out a better way to handle
|
||||||
|
-- literal/anonymous types (see https://github.com/neovim/neovim/pull/27542/files#r1495259331).
|
||||||
|
--- @class lsp.ItemDefaults
|
||||||
|
--- @field editRange lsp.Range | { insert: lsp.Range, replace: lsp.Range } | nil
|
||||||
|
--- @field insertTextFormat lsp.InsertTextFormat?
|
||||||
|
--- @field insertTextMode lsp.InsertTextMode?
|
||||||
|
--- @field data any
|
||||||
|
|
||||||
---@param input string unparsed snippet
|
---@param input string unparsed snippet
|
||||||
---@return string parsed snippet
|
---@return string parsed snippet
|
||||||
local function parse_snippet(input)
|
local function parse_snippet(input)
|
||||||
@ -39,13 +47,43 @@ local function get_completion_word(item)
|
|||||||
return item.label
|
return item.label
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Applies the given defaults to the completion item, modifying it in place.
|
||||||
|
---
|
||||||
|
--- @param item lsp.CompletionItem
|
||||||
|
--- @param defaults lsp.ItemDefaults?
|
||||||
|
local function apply_defaults(item, defaults)
|
||||||
|
if not defaults then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
item.insertTextFormat = item.insertTextFormat or defaults.insertTextFormat
|
||||||
|
item.insertTextMode = item.insertTextMode or defaults.insertTextMode
|
||||||
|
item.data = item.data or defaults.data
|
||||||
|
if defaults.editRange then
|
||||||
|
local textEdit = item.textEdit or {}
|
||||||
|
item.textEdit = textEdit
|
||||||
|
textEdit.newText = textEdit.newText or item.textEditText or item.insertText
|
||||||
|
if defaults.editRange.start then
|
||||||
|
textEdit.range = textEdit.range or defaults.editRange
|
||||||
|
elseif defaults.editRange.insert then
|
||||||
|
textEdit.insert = defaults.editRange.insert
|
||||||
|
textEdit.replace = defaults.editRange.replace
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---@param result vim.lsp.CompletionResult
|
---@param result vim.lsp.CompletionResult
|
||||||
---@return lsp.CompletionItem[]
|
---@return lsp.CompletionItem[]
|
||||||
local function get_items(result)
|
local function get_items(result)
|
||||||
if result.items then
|
if result.items then
|
||||||
|
for _, item in ipairs(result.items) do
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
|
apply_defaults(item, result.itemDefaults)
|
||||||
|
end
|
||||||
return result.items
|
return result.items
|
||||||
|
else
|
||||||
|
return result
|
||||||
end
|
end
|
||||||
return result
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Turns the result of a `textDocument/completion` request into vim-compatible
|
--- Turns the result of a `textDocument/completion` request into vim-compatible
|
||||||
|
@ -764,6 +764,14 @@ function protocol.make_client_capabilities()
|
|||||||
return res
|
return res
|
||||||
end)(),
|
end)(),
|
||||||
},
|
},
|
||||||
|
completionList = {
|
||||||
|
itemDefaults = {
|
||||||
|
'editRange',
|
||||||
|
'insertTextFormat',
|
||||||
|
'insertTextMode',
|
||||||
|
'data',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
-- TODO(tjdevries): Implement this
|
-- TODO(tjdevries): Implement this
|
||||||
contextSupport = false,
|
contextSupport = false,
|
||||||
|
@ -551,6 +551,10 @@ end
|
|||||||
--- Can be used to extract the completion items from a
|
--- Can be used to extract the completion items from a
|
||||||
--- `textDocument/completion` request, which may return one of
|
--- `textDocument/completion` request, which may return one of
|
||||||
--- `CompletionItem[]`, `CompletionList` or null.
|
--- `CompletionItem[]`, `CompletionList` or null.
|
||||||
|
---
|
||||||
|
--- Note that this method doesn't apply `itemDefaults` to `CompletionList`s, and hence the returned
|
||||||
|
--- results might be incorrect.
|
||||||
|
---
|
||||||
---@deprecated
|
---@deprecated
|
||||||
---@param result table The result of a `textDocument/completion` request
|
---@param result table The result of a `textDocument/completion` request
|
||||||
---@return lsp.CompletionItem[] List of completion items
|
---@return lsp.CompletionItem[] List of completion items
|
||||||
|
@ -248,4 +248,32 @@ describe('vim.lsp._completion', function()
|
|||||||
item.user_data = nil
|
item.user_data = nil
|
||||||
eq(expected, item)
|
eq(expected, item)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('uses defaults from itemDefaults', function()
|
||||||
|
--- @type lsp.CompletionList
|
||||||
|
local completion_list = {
|
||||||
|
isIncomplete = false,
|
||||||
|
itemDefaults = {
|
||||||
|
editRange = {
|
||||||
|
start = { line = 1, character = 1 },
|
||||||
|
['end'] = { line = 1, character = 4 },
|
||||||
|
},
|
||||||
|
insertTextFormat = 2,
|
||||||
|
data = 'foobar',
|
||||||
|
},
|
||||||
|
items = {
|
||||||
|
{
|
||||||
|
label = 'hello',
|
||||||
|
data = 'item-property-has-priority',
|
||||||
|
textEditText = 'hello',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
local result = complete('|', completion_list)
|
||||||
|
eq(1, #result.items)
|
||||||
|
local item = result.items[1].user_data.nvim.lsp.completion_item --- @type lsp.CompletionItem
|
||||||
|
eq(2, item.insertTextFormat)
|
||||||
|
eq('item-property-has-priority', item.data)
|
||||||
|
eq({ line = 1, character = 1 }, item.textEdit.range.start)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user