aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/util.lua
diff options
context:
space:
mode:
authorMaria José Solano <majosolano99@gmail.com>2024-10-15 02:36:04 -0700
committerGitHub <noreply@github.com>2024-10-15 02:36:04 -0700
commite0a5c3bb581752569df4490b48cb54e7c1ab0613 (patch)
tree97e6936d443d2cb7f4da14a04a285ac16034f1dd /runtime/lua/vim/lsp/util.lua
parent74a161477266b3c131076ac572c5d4b577593ec4 (diff)
downloadrneovim-e0a5c3bb581752569df4490b48cb54e7c1ab0613.tar.gz
rneovim-e0a5c3bb581752569df4490b48cb54e7c1ab0613.tar.bz2
rneovim-e0a5c3bb581752569df4490b48cb54e7c1ab0613.zip
fix(lsp): handle multiline signature help labels #30460
Diffstat (limited to 'runtime/lua/vim/lsp/util.lua')
-rw-r--r--runtime/lua/vim/lsp/util.lua93
1 files changed, 58 insertions, 35 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index ebc3f7c55e..fc822f1403 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -781,24 +781,37 @@ function M.convert_input_to_markdown_lines(input, contents)
return contents
end
+--- Returns the line/column-based position in `contents` at the given offset.
+---
+---@param offset integer
+---@param contents string[]
+---@return { [1]: integer, [2]: integer }
+local function get_pos_from_offset(offset, contents)
+ local i = 0
+ for l, line in ipairs(contents) do
+ if offset >= i and offset < i + #line then
+ return { l - 1, offset - i + 1 }
+ else
+ i = i + #line + 1
+ end
+ end
+end
+
--- Converts `textDocument/signatureHelp` response to markdown lines.
---
---@param signature_help lsp.SignatureHelp Response of `textDocument/SignatureHelp`
---@param ft string|nil filetype that will be use as the `lang` for the label markdown code block
---@param triggers table|nil list of trigger characters from the lsp server. used to better determine parameter offsets
---@return string[]|nil table list of lines of converted markdown.
----@return number[]|nil table of active hl
+---@return Range4|nil table of active hl
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers)
- if not signature_help.signatures then
- return
- end
--The active signature. If omitted or the value lies outside the range of
--`signatures` the value defaults to zero or is ignored if `signatures.length == 0`.
--Whenever possible implementors should make an active decision about
--the active signature and shouldn't rely on a default value.
local contents = {}
- local active_hl
+ local active_offset ---@type [integer, integer]|nil
local active_signature = signature_help.activeSignature or 0
-- If the activeSignature is not inside the valid range, then clip it.
-- In 3.15 of the protocol, activeSignature was allowed to be negative
@@ -806,9 +819,6 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
active_signature = 0
end
local signature = signature_help.signatures[active_signature + 1]
- if not signature then
- return
- end
local label = signature.label
if ft then
-- wrap inside a code block for proper rendering
@@ -825,6 +835,8 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
M.convert_input_to_markdown_lines(signature.documentation, contents)
end
if signature.parameters and #signature.parameters > 0 then
+ -- First check if the signature has an activeParameter. If it doesn't check if the response
+ -- had that property instead. Else just default to 0.
local active_parameter = (signature.activeParameter or signature_help.activeParameter or 0)
if active_parameter < 0 then
active_parameter = 0
@@ -837,8 +849,8 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
end
local parameter = signature.parameters[active_parameter + 1]
- if parameter then
- --[=[
+ local parameter_label = parameter.label
+ --[=[
--Represents a parameter of a callable-signature. A parameter can
--have a label and a doc-comment.
interface ParameterInformation {
@@ -856,36 +868,47 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
documentation?: string | MarkupContent;
}
--]=]
- if parameter.label then
- if type(parameter.label) == 'table' then
- active_hl = parameter.label
- else
- local offset = 1
- -- try to set the initial offset to the first found trigger character
- for _, t in ipairs(triggers or {}) do
- local trigger_offset = signature.label:find(t, 1, true)
- if trigger_offset and (offset == 1 or trigger_offset < offset) then
- offset = trigger_offset
- end
- end
- for p, param in pairs(signature.parameters) do
- offset = signature.label:find(param.label, offset, true)
- if not offset then
- break
- end
- if p == active_parameter + 1 then
- active_hl = { offset - 1, offset + #parameter.label - 1 }
- break
- end
- offset = offset + #param.label + 1
- end
+ if type(parameter_label) == 'table' then
+ active_offset = parameter_label
+ else
+ local offset = 1 ---@type integer|nil
+ -- try to set the initial offset to the first found trigger character
+ for _, t in ipairs(triggers or {}) do
+ local trigger_offset = signature.label:find(t, 1, true)
+ if trigger_offset and (offset == 1 or trigger_offset < offset) then
+ offset = trigger_offset
end
end
- if parameter.documentation then
- M.convert_input_to_markdown_lines(parameter.documentation, contents)
+ for p, param in pairs(signature.parameters) do
+ offset = signature.label:find(param.label, offset, true)
+ if not offset then
+ break
+ end
+ if p == active_parameter + 1 then
+ active_offset = { offset - 1, offset + #parameter_label - 1 }
+ break
+ end
+ offset = offset + #param.label + 1
end
end
+ if parameter.documentation then
+ M.convert_input_to_markdown_lines(parameter.documentation, contents)
+ end
+ end
+
+ local active_hl = nil
+ if active_offset then
+ active_hl = {}
+ -- Account for the start of the markdown block.
+ if ft then
+ active_offset[1], active_offset[2] =
+ active_offset[1] + #contents[1], active_offset[2] + #contents[1]
+ end
+
+ list_extend(active_hl, get_pos_from_offset(active_offset[1], contents))
+ list_extend(active_hl, get_pos_from_offset(active_offset[2], contents))
end
+
return contents, active_hl
end