From 145548a24ae694ff048b080aa7e8b0329b9c9491 Mon Sep 17 00:00:00 2001 From: glepnir Date: Wed, 11 Mar 2026 02:34:58 +0800 Subject: [PATCH] feat(lsp): show snippet preview if completeopt=popup #32553 Problem: LSP completion does not show snippet preview. Solution: Show snippet preview if 'completeopt' includes popup. --- runtime/lua/vim/lsp/completion.lua | 12 ++++++++++ .../functional/plugin/lsp/completion_spec.lua | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index adf198b164..fd12809b7a 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -243,6 +243,18 @@ end ---@param item lsp.CompletionItem ---@return string local function get_doc(item) + if + vim.o.completeopt:find('popup') + and item.insertTextFormat == protocol.InsertTextFormat.Snippet + and #(item.documentation or '') == 0 + and vim.bo.filetype ~= '' + and (item.textEdit or (item.insertText and item.insertText ~= '')) + then + -- Shows snippet preview in doc popup if completeopt=popup. + local text = parse_snippet(item.insertText or item.textEdit.newText) + return ('```%s\n%s\n```'):format(vim.bo.filetype, text) + end + local doc = item.documentation if not doc then return '' diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 3f48ec4d91..b50b7191cc 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -750,6 +750,28 @@ describe('vim.lsp.completion: item conversion', function() eq(1, #result.items) eq('foobar', result.items[1].user_data.nvim.lsp.completion_item.textEdit.newText) end) + + it('shows snippet source in doc popup if completeopt include popup', function() + exec_lua([[ + vim.opt.completeopt:append('popup') + vim.bo.filetype = 'lua' + ]]) + local completion_list = { + isIncomplete = false, + items = { + { + insertText = 'for ${1:index}, ${2:value} in ipairs(${3:t}) do\n\t$0\nend', + insertTextFormat = 2, + kind = 15, + label = 'for .. ipairs', + sortText = '0001', + }, + }, + } + local result = complete('|', completion_list) + eq('for .. ipairs', result.items[1].word) + eq('```lua\nfor index, value in ipairs(t) do\n\t\nend\n```', result.items[1].info) + end) end) --- @param name string