diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 5c4c8a4dd5..959422eecb 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -301,7 +301,7 @@ function M._lsp_to_complete_items(result, prefix, client_id) return match_item_by_value(item.filterText, prefix) end - if item.textEdit then + if item.textEdit and not item.textEdit.newText then -- server took care of filtering return true end @@ -370,11 +370,18 @@ end local function adjust_start_col(lnum, line, items, encoding) local min_start_char = nil for _, item in pairs(items) do - if item.textEdit and item.textEdit.range and item.textEdit.range.start.line == lnum then - if min_start_char and min_start_char ~= item.textEdit.range.start.character then - return nil + if item.textEdit then + if item.textEdit.range and item.textEdit.range.start.line == lnum then + if min_start_char and min_start_char ~= item.textEdit.range.start.character then + return nil + end + min_start_char = item.textEdit.range.start.character + elseif item.textEdit.insert and item.textEdit.insert.start.line == lnum then + if min_start_char and min_start_char ~= item.textEdit.insert.start.character then + return nil + end + min_start_char = item.textEdit.insert.start.character end - min_start_char = item.textEdit.range.start.character end end if min_start_char then diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 509c203ef7..f367c0a7c3 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -478,6 +478,7 @@ function protocol.make_client_capabilities() preselectSupport = false, deprecatedSupport = true, documentationFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText }, + insertReplaceSupport = true, resolveSupport = { properties = { 'additionalTextEdits', diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 22536b2606..b4decc90bc 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -149,10 +149,6 @@ describe('vim.lsp.completion: item conversion', function() abbr = 'foo', word = 'foo', }, - { - abbr = 'bar', - word = 'bar', - }, } result = vim.tbl_map(function(x) return { @@ -618,21 +614,6 @@ describe('vim.lsp.completion: item conversion', function() }, }, }, - { - label = 'insert_replace_edit', - kind = 9, - textEdit = { - newText = 'foobar', - insert = { - start = { line = 0, character = 7 }, - ['end'] = { line = 0, character = 11 }, - }, - replace = { - start = { line = 0, character = 0 }, - ['end'] = { line = 0, character = 0 }, - }, - }, - }, }, } local expected = { @@ -647,17 +628,6 @@ describe('vim.lsp.completion: item conversion', function() abbr_hlgroup = '', word = 'this_thread', }, - { - abbr = 'insert_replace_edit', - dup = 1, - empty = 1, - icase = 1, - info = '', - kind = 'Module', - menu = '', - abbr_hlgroup = '', - word = 'foobar', - }, } local result = complete(' std::this|', completion_list) eq(7, result.server_start_boundary) @@ -806,6 +776,53 @@ describe('vim.lsp.completion: item conversion', function() eq('hello', text) end ) + + it('uses the start boundary from an insertReplace response', function() + local completion_list = { + isIncomplete = false, + items = { + { + data = { cacheId = 1 }, + kind = 2, + label = 'foobar', + sortText = '11', + textEdit = { + insert = { + start = { character = 4, line = 4 }, + ['end'] = { character = 8, line = 4 }, + }, + newText = 'foobar', + replace = { + start = { character = 4, line = 4 }, + ['end'] = { character = 8, line = 4 }, + }, + }, + }, + { + data = { cacheId = 2 }, + kind = 2, + label = 'bazqux', + sortText = '11', + textEdit = { + insert = { + start = { character = 4, line = 4 }, + ['end'] = { character = 5, line = 4 }, + }, + newText = 'bazqux', + replace = { + start = { character = 4, line = 4 }, + ['end'] = { character = 5, line = 4 }, + }, + }, + }, + }, + } + + local result = complete('foo.f|', completion_list) + eq(1, #result.items) + local text = result.items[1].user_data.nvim.lsp.completion_item.textEdit.newText + eq('foobar', text) + end) end) --- @param name string