From 2eb14c54bcdb5c1fd0ac5aab454336b5b0dc3eb2 Mon Sep 17 00:00:00 2001 From: Marcus Caisey Date: Sun, 29 Mar 2026 22:48:11 +0100 Subject: [PATCH] fix(lsp): highlight snippet preview when server can't completionItem/resolve (#38534) Problem: The snippet preview is not being highlighted by treesitter for completion items from servers which don't support `completionItem/resolve` (like gopls). This was broken by #38428. Solution: Call `update_popup_window` after updating the completion item with the snippet preview. I've added assertions to the `selecting an item triggers completionItem/resolve + (snippet) preview` test case which covers the snippet preview being shown since no tests failed when I removed the `nvim__complete_set` call which actually populates the preview on this codepath. --- runtime/lua/vim/lsp/completion.lua | 3 +- .../functional/plugin/lsp/completion_spec.lua | 37 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 7795f42645..74873d96f2 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -803,10 +803,11 @@ local function on_completechanged(group, bufnr) then -- Shows snippet preview in doc popup if completeopt=popup. local text = parse_snippet(lsp_item.insertText or lsp_item.textEdit.newText) - api.nvim__complete_set( + local windata = api.nvim__complete_set( data.selected, { info = ('```%s\n%s\n```'):format(vim.bo.filetype, text) } ) + update_popup_window(windata.winid, windata.bufnr, protocol.MarkupKind.Markdown) end return end diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 81380e31a0..9315f723fb 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -1398,7 +1398,7 @@ describe('vim.lsp.completion: integration', function() exec_lua(function() vim.o.completeopt = 'menuone,popup' end) - create_server('dummy', completion_list, { + local dummy_client_id = create_server('dummy', completion_list, { resolve_result = { { detail = 'function', @@ -1474,6 +1474,41 @@ describe('vim.lsp.completion: integration', function() {1:~ }|*15 {5:-- INSERT --} | ]]) + + n.command('lua vim.lsp.buf_detach_client(0, ' .. dummy_client_id .. ')') + -- Server which doesn't support completionItem/resolve + create_server('dummy2', { + isIncomplete = false, + items = { + { + insertText = 'package main', + insertTextFormat = 1, + kind = 9, + label = 'package main', + sortText = '0001', + }, + { + insertText = 'package ${1:name}', + insertTextFormat = 2, + kind = 9, + label = 'package', + sortText = '0002', + }, + }, + }) + feed('S') + -- No popup shown for item without snippet + wait_for_pum() + eq(true, n.fn.complete_info({ 'selected' }).preview_bufnr == nil) + feed('') + -- Popup shown for item with snippet + screen:expect([[ + package^ | + {4:package main Module }{100:package name}{1: }| + {12:package Module }{1: }| + {1:~ }|*16 + {5:-- INSERT --} | + ]]) end) it('omnifunc works without enable() #38252', function()