aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/lsp')
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua55
-rw-r--r--runtime/lua/vim/lsp/handlers.lua9
-rw-r--r--runtime/lua/vim/lsp/protocol.lua7
-rw-r--r--runtime/lua/vim/lsp/util.lua14
4 files changed, 77 insertions, 8 deletions
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 64dde78f17..c83e29aa64 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -203,8 +203,10 @@ local bufnr_and_client_cacher_mt = {
-- Diagnostic Saving & Caching {{{
local _diagnostic_cleanup = setmetatable({}, bufnr_and_client_cacher_mt)
local diagnostic_cache = setmetatable({}, bufnr_and_client_cacher_mt)
+local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_client_cacher_mt)
local diagnostic_cache_lines = setmetatable({}, bufnr_and_client_cacher_mt)
local diagnostic_cache_counts = setmetatable({}, bufnr_and_client_cacher_mt)
+local diagnostic_attached_buffers = {}
local _bufs_waiting_to_update = setmetatable({}, bufnr_and_client_cacher_mt)
@@ -826,6 +828,7 @@ function M.clear(bufnr, client_id, diagnostic_ns, sign_ns)
diagnostic_ns = diagnostic_ns or M._get_diagnostic_namespace(client_id)
sign_ns = sign_ns or M._get_sign_namespace(client_id)
+ diagnostic_cache_extmarks[bufnr][client_id] = {}
assert(bufnr, "bufnr is required")
assert(diagnostic_ns, "Need diagnostic_ns, got nil")
@@ -1038,6 +1041,54 @@ function M.on_publish_diagnostics(_, _, params, client_id, _, config)
M.display(diagnostics, bufnr, client_id, config)
end
+-- restores the extmarks set by M.display
+--- @param last number last line that was changed
+-- @private
+local function restore_extmarks(bufnr, last)
+ for client_id, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do
+ local ns = M._get_diagnostic_namespace(client_id)
+ local extmarks_current = api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {details = true})
+ local found = {}
+ for _, extmark in ipairs(extmarks_current) do
+ -- nvim_buf_set_lines will move any extmark to the line after the last
+ -- nvim_buf_set_text will move any extmark to the last line
+ if extmark[2] ~= last + 1 then
+ found[extmark[1]] = true
+ end
+ end
+ for _, extmark in ipairs(extmarks) do
+ if not found[extmark[1]] then
+ local opts = extmark[4]
+ opts.id = extmark[1]
+ -- HACK: end_row should be end_line
+ if opts.end_row then
+ opts.end_line = opts.end_row
+ opts.end_row = nil
+ end
+ pcall(api.nvim_buf_set_extmark, bufnr, ns, extmark[2], extmark[3], opts)
+ end
+ end
+ end
+end
+
+-- caches the extmarks set by M.display
+-- @private
+local function save_extmarks(bufnr, client_id)
+ bufnr = bufnr == 0 and api.nvim_get_current_buf() or bufnr
+ if not diagnostic_attached_buffers[bufnr] then
+ api.nvim_buf_attach(bufnr, false, {
+ on_lines = function(_, _, _, _, _, last)
+ restore_extmarks(bufnr, last - 1)
+ end,
+ on_detach = function()
+ diagnostic_cache_extmarks[bufnr] = nil
+ end})
+ diagnostic_attached_buffers[bufnr] = true
+ end
+ local ns = M._get_diagnostic_namespace(client_id)
+ diagnostic_cache_extmarks[bufnr][client_id] = api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {details = true})
+end
+
--@private
--- Display diagnostics for the buffer, given a configuration.
function M.display(diagnostics, bufnr, client_id, config)
@@ -1108,7 +1159,11 @@ function M.display(diagnostics, bufnr, client_id, config)
if signs_opts then
M.set_signs(diagnostics, bufnr, client_id, nil, signs_opts)
end
+
+ -- cache extmarks
+ save_extmarks(bufnr, client_id)
end
+
-- }}}
-- Diagnostic User Functions {{{
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 41852b9d88..7da24d8c43 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -316,6 +316,7 @@ M['textDocument/typeDefinition'] = location_handler
M['textDocument/implementation'] = location_handler
--- |lsp-handler| for the method "textDocument/signatureHelp"
+--- The active parameter is highlighted with |hl-LspSignatureActiveParameter|
--- <pre>
--- vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(
--- vim.lsp.handlers.signature_help, {
@@ -338,13 +339,17 @@ function M.signature_help(_, method, result, _, bufnr, config)
return
end
local ft = api.nvim_buf_get_option(bufnr, 'filetype')
- local lines = util.convert_signature_help_to_markdown_lines(result, ft)
+ local lines, hl = util.convert_signature_help_to_markdown_lines(result, ft)
lines = util.trim_empty_lines(lines)
if vim.tbl_isempty(lines) then
print('No signature help available')
return
end
- return util.open_floating_preview(lines, "markdown", config)
+ local fbuf, fwin = util.open_floating_preview(lines, "markdown", config)
+ if hl then
+ api.nvim_buf_add_highlight(fbuf, -1, "LspSignatureActiveParameter", 0, unpack(hl))
+ end
+ return fbuf, fwin
end
--@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index 7e43eb84de..6d02b9ba74 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -691,10 +691,11 @@ function protocol.make_client_capabilities()
signatureHelp = {
dynamicRegistration = false;
signatureInformation = {
+ activeParameterSupport = true;
documentationFormat = { protocol.MarkupKind.Markdown; protocol.MarkupKind.PlainText };
- -- parameterInformation = {
- -- labelOffsetSupport = false;
- -- };
+ parameterInformation = {
+ labelOffsetSupport = true;
+ };
};
};
references = {
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 06afc2c5e2..17440ca1b5 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -856,6 +856,7 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft)
--=== 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_signature = signature_help.activeSignature or 0
-- If the activeSignature is not inside the valid range, then clip it.
if active_signature >= #signature_help.signatures then
@@ -875,7 +876,7 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft)
M.convert_input_to_markdown_lines(signature.documentation, contents)
end
if signature.parameters and #signature.parameters > 0 then
- local active_parameter = signature_help.activeParameter or 0
+ local active_parameter = (signature.activeParameter or signature_help.activeParameter or 0)
-- If the activeParameter is not inside the valid range, then clip it.
if active_parameter >= #signature.parameters then
active_parameter = 0
@@ -900,13 +901,20 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft)
documentation?: string | MarkupContent;
}
--]=]
- -- TODO highlight parameter
+ if parameter.label then
+ if type(parameter.label) == "table" then
+ active_hl = parameter.label
+ else
+ local i = signature.label:find(parameter.label)
+ if i then active_hl = {i - 1, i + #parameter.label - 1} end
+ end
+ end
if parameter.documentation then
M.convert_input_to_markdown_lines(parameter.documentation, contents)
end
end
end
- return contents
+ return contents, active_hl
end
--- Creates a table with sensible default options for a floating window. The