From 729111d3a3cd4939b3c24925cf1e0d7befec483e Mon Sep 17 00:00:00 2001 From: Robert Muir Date: Wed, 27 Aug 2025 21:51:30 -0400 Subject: [PATCH] fix(lsp): don't treat MarkedString[] with language id as empty #35518 Problem: Hover response of MarkedString[] where the first element contains a language identifier treated as empty. Solution: Fix empty check to handle case of MarkedString[] where the first element is a pair of a language and value. --- runtime/lua/vim/lsp/buf.lua | 19 +++++++++++++++++-- test/functional/plugin/lsp_spec.lua | 28 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index c61ce958fb..bd44511bc0 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -69,11 +69,26 @@ function M.hover(config) lsp.log.error(err.code, err.message) elseif result and result.contents then -- Make sure the response is not empty + -- Five response shapes: + -- - MarkupContent: { kind="markdown", value="doc" } + -- - MarkedString-string: "doc" + -- - MarkedString-pair: { language="c", value="doc" } + -- - MarkedString[]-string: { "doc1", ... } + -- - MarkedString[]-pair: { { language="c", value="doc1" }, ... } if ( type(result.contents) == 'table' - and #(vim.tbl_get(result.contents, 'value') or result.contents[1] or '') > 0 - ) or (type(result.contents) == 'string' and #result.contents > 0) + and #( + vim.tbl_get(result.contents, 'value') -- MarkupContent or MarkedString-pair + or vim.tbl_get(result.contents, 1, 'value') -- MarkedString[]-pair + or result.contents[1] -- MarkedString[]-string + or '' + ) + > 0 + ) + or ( + type(result.contents) == 'string' and #result.contents > 0 -- MarkedString-string + ) then results1[client_id] = result else diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index b8b62cb24c..cccbbbbda5 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -7139,5 +7139,33 @@ describe('LSP', function() eq('Empty hover response', n.exec_capture('lua vim.lsp.buf.hover()')) end) + + it('treats markedstring array as not empty', function() + exec_lua(create_server_definition) + exec_lua(function() + local server = _G._create_server({ + capabilities = { + hoverProvider = true, + }, + handlers = { + ['textDocument/hover'] = function(_, _, callback) + local res = { + contents = { + { + language = 'java', + value = 'Example', + }, + 'doc comment', + }, + } + callback(nil, res) + end, + }, + }) + vim.lsp.start({ name = 'dummy', cmd = server.cmd }) + end) + + eq('', n.exec_capture('lua vim.lsp.buf.hover()')) + end) end) end)