diff options
author | Maria José Solano <majosolano99@gmail.com> | 2024-02-26 11:42:51 -0800 |
---|---|---|
committer | Christian Clason <c.clason@uni-graz.at> | 2024-02-27 16:50:51 +0100 |
commit | 63f9c2da9aab52fa698fcbfdbc58ffd41794d28a (patch) | |
tree | 37742567d493c54245e6e0b1004f5d18b4319945 | |
parent | 3d96e3f9f25389e979bb7f2417ec2135f79fbfbb (diff) | |
download | rneovim-63f9c2da9aab52fa698fcbfdbc58ffd41794d28a.tar.gz rneovim-63f9c2da9aab52fa698fcbfdbc58ffd41794d28a.tar.bz2 rneovim-63f9c2da9aab52fa698fcbfdbc58ffd41794d28a.zip |
feat(lsp): support completion itemDefaults
-rw-r--r-- | runtime/doc/news.txt | 14 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/_completion.lua | 40 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/protocol.lua | 8 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 4 | ||||
-rw-r--r-- | test/functional/plugin/lsp/completion_spec.lua | 28 |
5 files changed, 93 insertions, 1 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 9ce96b7a67..6895254a42 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -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()| (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* @@ -213,6 +222,11 @@ The following new APIs and features were added. the original LSP `Location` or `LocationLink`. • Added support for connecting to servers using named pipes (Windows) or 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 • Bundled parsers and queries (highlight, folds) for Markdown, Python, and diff --git a/runtime/lua/vim/lsp/_completion.lua b/runtime/lua/vim/lsp/_completion.lua index 3a38c1b5e1..a169f96565 100644 --- a/runtime/lua/vim/lsp/_completion.lua +++ b/runtime/lua/vim/lsp/_completion.lua @@ -6,6 +6,14 @@ local ms = protocol.Methods --- @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 ---@return string parsed snippet local function parse_snippet(input) @@ -39,13 +47,43 @@ local function get_completion_word(item) return item.label 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 ---@return lsp.CompletionItem[] local function get_items(result) 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 + else + return result end - return result end --- Turns the result of a `textDocument/completion` request into vim-compatible diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 82e8c4a7de..fb41311961 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -764,6 +764,14 @@ function protocol.make_client_capabilities() return res end)(), }, + completionList = { + itemDefaults = { + 'editRange', + 'insertTextFormat', + 'insertTextMode', + 'data', + }, + }, -- TODO(tjdevries): Implement this contextSupport = false, diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index e371cb0e15..3973e606f8 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -551,6 +551,10 @@ end --- Can be used to extract the completion items from a --- `textDocument/completion` request, which may return one of --- `CompletionItem[]`, `CompletionList` or null. +--- +--- Note that this method doesn't apply `itemDefaults` to `CompletionList`s, and hence the returned +--- results might be incorrect. +--- ---@deprecated ---@param result table The result of a `textDocument/completion` request ---@return lsp.CompletionItem[] List of completion items diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index b49f970385..655eb76be6 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -248,4 +248,32 @@ describe('vim.lsp._completion', function() item.user_data = nil eq(expected, item) 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) |