From 5653b25e9b8fa311db16dd306a9b849e5456c603 Mon Sep 17 00:00:00 2001 From: glepnir Date: Sat, 14 Mar 2026 17:20:34 +0800 Subject: [PATCH] fix(lsp): handle non-string documentation in completion items #38291 Problem: `get_doc` throws error with "attempt to get length of a userdata value" when `item.documentation` is truthy but not a string (e.g. vim.NIL from a JSON null). Solution: Check `type(item.documentation)` before taking its length. --- runtime/lua/vim/lsp/completion.lua | 2 +- test/functional/plugin/lsp/completion_spec.lua | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index a1925907e6..7109f01468 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -261,7 +261,7 @@ local function get_doc(item) if has_completeopt('popup') and item.insertTextFormat == protocol.InsertTextFormat.Snippet - and #(item.documentation or '') == 0 + and (type(item.documentation) ~= 'string' or #item.documentation == 0) and vim.bo.filetype ~= '' and (item.textEdit or (item.insertText and item.insertText ~= '')) then diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua index 3c94098f03..3b05248c35 100644 --- a/test/functional/plugin/lsp/completion_spec.lua +++ b/test/functional/plugin/lsp/completion_spec.lua @@ -767,11 +767,21 @@ describe('vim.lsp.completion: item conversion', function() label = 'for .. ipairs', sortText = '0001', }, + { + insertText = 'for ${1:i}, ${2:v} in ipairs(${3:t}) do\n\t$0\nend', + insertTextFormat = 2, + kind = 15, + label = 'for .. ipairs 2', + sortText = '0002', + documentation = vim.NIL, + }, }, } 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) + eq('for .. ipairs 2', result.items[2].word) + eq('```lua\nfor i, v in ipairs(t) do\n\t\nend\n```', result.items[2].info) end) end)