From 1799aaebda4afc0f7c74ff1821374c7bdf4f2c05 Mon Sep 17 00:00:00 2001 From: Olivia Kinnear Date: Tue, 28 Apr 2026 18:17:44 -0500 Subject: [PATCH] fix(lsp): util.lua attempt to concatenate userdata #39225 Problem: Error when querying document symbols using python-lsp-server: lsp/util.lua:1955: attempt to concatenate field 'containerName' (a userdata value) Solution: Check for `vim.NIL`. --- runtime/lua/vim/_core/util.lua | 7 +++++++ runtime/lua/vim/lsp/completion.lua | 3 ++- runtime/lua/vim/lsp/util.lua | 7 ++++--- test/functional/plugin/lsp/util_spec.lua | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/runtime/lua/vim/_core/util.lua b/runtime/lua/vim/_core/util.lua index e5dd5c2068..bceded9043 100644 --- a/runtime/lua/vim/_core/util.lua +++ b/runtime/lua/vim/_core/util.lua @@ -166,4 +166,11 @@ function M.get_forge_url(repo, target, target_type) return ('%s/%s/%s'):format(repo, middle, target) end +--- Check if value is `nil` or `vim.NIL` +--- +--- @return boolean +function M.isnil(value) + return value == nil or value == vim.NIL +end + return M diff --git a/runtime/lua/vim/lsp/completion.lua b/runtime/lua/vim/lsp/completion.lua index 4f3852adb8..7011f137e6 100644 --- a/runtime/lua/vim/lsp/completion.lua +++ b/runtime/lua/vim/lsp/completion.lua @@ -36,6 +36,7 @@ local M = {} local api = vim.api local lsp = vim.lsp local protocol = lsp.protocol +local isnil = require('vim._core.util').isnil local rtt_ms = 50.0 local ns_to_ms = 0.000001 @@ -1010,7 +1011,7 @@ local function trigger(bufnr, clients, ctx) client and client.name or 'UNKNOWN' ) ) - elseif result and result ~= vim.NIL and #(result.items or result) > 0 then + elseif not isnil(result) and #(result.items or result) > 0 then Context.isIncomplete = Context.isIncomplete or result.isIncomplete local encoding = client and client.offset_encoding or 'utf-16' local client_matches, tmp_server_start_boundary diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 9e8f661ac7..30f89ac129 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -3,6 +3,7 @@ local validate = vim.validate local api = vim.api local list_extend = vim.list_extend local uv = vim.uv +local isnil = require('vim._core.util').isnil local M = {} @@ -1986,13 +1987,13 @@ function M.symbols_to_items(symbols, bufnr, position_encoding) local end_lnum = range['end'].line + 1 local end_col = get_line_byte_from_position(bufnr, range['end'], position_encoding) + 1 - local is_deprecated = symbol.deprecated - or (symbol.tags and vim.tbl_contains(symbol.tags, protocol.SymbolTag.Deprecated)) + local is_deprecated = not isnil(symbol.deprecated or nil) + or (not isnil(symbol.tags) and vim.tbl_contains(symbol.tags, protocol.SymbolTag.Deprecated)) local text = string.format( '[%s] %s%s%s', kind, symbol.name, - symbol.containerName and ' in ' .. symbol.containerName or '', + not isnil(symbol.containerName) and ' in ' .. symbol.containerName or '', is_deprecated and ' (deprecated)' or '' ) diff --git a/test/functional/plugin/lsp/util_spec.lua b/test/functional/plugin/lsp/util_spec.lua index db7c56495f..56c273e277 100644 --- a/test/functional/plugin/lsp/util_spec.lua +++ b/test/functional/plugin/lsp/util_spec.lua @@ -629,7 +629,7 @@ describe('vim.lsp.util', function() filename = '/test_b', kind = 'Module', lnum = 4, - text = '[Module] TestB in TestBContainer (deprecated)', + text = '[Module] TestB (deprecated)', }, } eq( @@ -672,7 +672,7 @@ describe('vim.lsp.util', function() }, uri = 'file:///test_b', }, - containerName = 'TestBContainer', + containerName = vim.NIL, }, } return vim.lsp.util.symbols_to_items(sym_info, nil, 'utf-16')