diff options
Diffstat (limited to 'runtime/lua/vim/lsp/codelens.lua')
-rw-r--r-- | runtime/lua/vim/lsp/codelens.lua | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index fbd37e3830..20b203fe99 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -22,19 +22,33 @@ local namespaces = setmetatable({}, { end; }) ---@private +---@private M.__namespaces = namespaces ---@private +---@private local function execute_lens(lens, bufnr, client_id) local line = lens.range.start.line api.nvim_buf_clear_namespace(bufnr, namespaces[client_id], line, line + 1) + local command = lens.command + local fn = vim.lsp.commands[command.command] + if fn then + fn(command, { bufnr = bufnr, client_id = client_id }) + return + end -- Need to use the client that returned the lens → must not use buf_request local client = vim.lsp.get_client_by_id(client_id) assert(client, 'Client is required to execute lens, client_id=' .. client_id) - client.request('workspace/executeCommand', lens.command, function(...) + local command_provider = client.server_capabilities.executeCommandProvider + local commands = type(command_provider) == 'table' and command_provider.commands or {} + if not vim.tbl_contains(commands, command.command) then + vim.notify(string.format( + "Language server does not support command `%s`. This command may require a client extension.", command.command), + vim.log.levels.WARN) + return + end + client.request('workspace/executeCommand', command, function(...) local result = vim.lsp.handlers['workspace/executeCommand'](...) M.refresh() return result @@ -44,9 +58,10 @@ end --- Return all lenses for the given buffer --- +---@param bufnr number Buffer number. 0 can be used for the current buffer. ---@return table (`CodeLens[]`) function M.get(bufnr) - local lenses_by_client = lens_cache_by_buf[bufnr] + local lenses_by_client = lens_cache_by_buf[bufnr or 0] if not lenses_by_client then return {} end local lenses = {} for _, client_lenses in pairs(lenses_by_client) do @@ -111,15 +126,19 @@ function M.display(lenses, bufnr, client_id) local ns = namespaces[client_id] local num_lines = api.nvim_buf_line_count(bufnr) for i = 0, num_lines do - local line_lenses = lenses_by_lnum[i] + local line_lenses = lenses_by_lnum[i] or {} api.nvim_buf_clear_namespace(bufnr, ns, i, i + 1) local chunks = {} - for _, lens in pairs(line_lenses or {}) do + local num_line_lenses = #line_lenses + for j, lens in ipairs(line_lenses) do local text = lens.command and lens.command.title or 'Unresolved lens ...' table.insert(chunks, {text, 'LspCodeLens' }) + if j < num_line_lenses then + table.insert(chunks, {' | ', 'LspCodeLensSeparator' }) + end end if #chunks > 0 then - api.nvim_buf_set_virtual_text(bufnr, ns, i, chunks, {}) + api.nvim_buf_set_extmark(bufnr, ns, i, 0, { virt_text = chunks }) end end end @@ -147,7 +166,7 @@ function M.save(lenses, bufnr, client_id) end ---@private +---@private local function resolve_lenses(lenses, bufnr, client_id, callback) lenses = lenses or {} local num_lens = vim.tbl_count(lenses) @@ -156,7 +175,7 @@ local function resolve_lenses(lenses, bufnr, client_id, callback) return end - --@private + ---@private local function countdown() num_lens = num_lens - 1 if num_lens == 0 then @@ -169,18 +188,18 @@ local function resolve_lenses(lenses, bufnr, client_id, callback) if lens.command then countdown() else - client.request('codeLens/resolve', lens, function(_, _, result) + client.request('codeLens/resolve', lens, function(_, result) if result and result.command then lens.command = result.command -- Eager display to have some sort of incremental feedback -- Once all lenses got resolved there will be a full redraw for all lenses -- So that multiple lens per line are properly displayed - api.nvim_buf_set_virtual_text( + api.nvim_buf_set_extmark( bufnr, ns, lens.range.start.line, - {{ lens.command.title, 'LspCodeLens' },}, - {} + 0, + { virt_text = {{ lens.command.title, 'LspCodeLens' }} } ) end countdown() @@ -192,17 +211,17 @@ end --- |lsp-handler| for the method `textDocument/codeLens` --- -function M.on_codelens(err, _, result, client_id, bufnr) +function M.on_codelens(err, result, ctx, _) assert(not err, vim.inspect(err)) - M.save(result, bufnr, client_id) + M.save(result, ctx.bufnr, ctx.client_id) -- Eager display for any resolved (and unresolved) lenses and refresh them -- once resolved. - M.display(result, bufnr, client_id) - resolve_lenses(result, bufnr, client_id, function() - M.display(result, bufnr, client_id) - active_refreshes[bufnr] = nil + M.display(result, ctx.bufnr, ctx.client_id) + resolve_lenses(result, ctx.bufnr, ctx.client_id, function() + M.display(result, ctx.bufnr, ctx.client_id) + active_refreshes[ctx.bufnr] = nil end) end |