diff options
Diffstat (limited to 'runtime/lua/vim/lsp')
-rw-r--r-- | runtime/lua/vim/lsp/diagnostic.lua | 55 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/handlers.lua | 9 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/protocol.lua | 7 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 14 |
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 |