From 767fbd88ff3c10326a523b9ffc6c0fe9ed37037e Mon Sep 17 00:00:00 2001 From: glepnir Date: Sun, 17 May 2026 23:58:49 +0800 Subject: [PATCH] fix(lsp): fallback to filterText for non-matching PlainText items #39695 Problem: PlainText completion items used `textEdit.newText` or `insertText` as the completion word even when they did not match the typed prefix. This could break popup completion behavior like 'completeopt+=longest'. Solution: Fall back to `filterText` when `newText` or `insertText` does not match the typed prefix. --- runtime/lua/vim/lsp/completion.lua | 9 ++- .../functional/plugin/lsp/completion_spec.lua | 78 +++++++++++++------ 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 3a6f17aa78..4f6c9022ea 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -211,8 +211,15 @@ local function get_completion_word(item, prefix, match) elseif item.textEdit then local word = item.textEdit.newText word = string.gsub(word, '\r\n?', '\n') - return word:match('([^\n]*)') or word + word = word:match('([^\n]*)') or word + if item.filterText and not match(word, prefix) then + return item.filterText + end + return word elseif item.insertText and item.insertText ~= '' then + if item.filterText and not match(item.insertText, prefix) then + return item.filterText + end return item.insertText end return item.label diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index c8310e94c9..00ef82327c 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -222,6 +222,59 @@ describe('vim.lsp.completion: item conversion', function() eq(expected, got) end + it('uses filterText as word if label/newText would not match', function() + local items = { + { + filterText = '