diff options
author | Mathias Fußenegger <mfussenegger@users.noreply.github.com> | 2023-06-09 11:32:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-09 11:32:43 +0200 |
commit | e5e0bda41b640d324350c5147b956e37e9f8b32c (patch) | |
tree | d546e647fcde46494740852171593e78101d9997 /runtime/lua/vim/lsp.lua | |
parent | f31dba93f921891159eb707b185517648df00d6b (diff) | |
download | rneovim-e5e0bda41b640d324350c5147b956e37e9f8b32c.tar.gz rneovim-e5e0bda41b640d324350c5147b956e37e9f8b32c.tar.bz2 rneovim-e5e0bda41b640d324350c5147b956e37e9f8b32c.zip |
feat(lsp)!: add vim.lsp.status, client.progress and promote LspProgressUpdate (#23958)
`client.messages` could grow unbounded because the default handler only
added new messages, never removing them.
A user either had to consume the messages by calling
`vim.lsp.util.get_progress_messages` or by manually removing them from
`client.messages.progress`. If they didn't do that, using LSP
effectively leaked memory.
To fix this, this deprecates the `messages` property and instead adds a
`progress` ring buffer that only keeps at most 50 messages. In addition
it deprecates `vim.lsp.util.get_progress_messages` in favour of a new
`vim.lsp.status()` and also promotes the `LspProgressUpdate` user
autocmd to a regular autocmd to allow users to pattern match on the
progress kind.
Also closes https://github.com/neovim/neovim/pull/20327
Diffstat (limited to 'runtime/lua/vim/lsp.lua')
-rw-r--r-- | runtime/lua/vim/lsp.lua | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 532504a7db..6ddbfc6df7 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -807,6 +807,9 @@ end --- --- - {server_capabilities} (table): Response from the server sent on --- `initialize` describing the server's capabilities. +--- +--- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages +--- sent by the server. function lsp.client() error() end @@ -891,6 +894,50 @@ function lsp.start(config, opts) return client_id end +--- Consumes the latest progress messages from all clients and formats them as a string. +--- Empty if there are no clients or if no new messages +--- +---@return string +function lsp.status() + local percentage = nil + local groups = {} + for _, client in ipairs(vim.lsp.get_active_clients()) do + for progress in client.progress do + local value = progress.value + if type(value) == 'table' and value.kind then + local group = groups[progress.token] + if not group then + group = {} + groups[progress.token] = group + end + group.title = value.title or group.title + group.message = value.message or group.message + if value.percentage then + percentage = math.max(percentage or 0, value.percentage) + end + end + -- else: Doesn't look like work done progress and can be in any format + -- Just ignore it as there is no sensible way to display it + end + end + local messages = {} + for _, group in pairs(groups) do + if group.title then + table.insert( + messages, + group.message and (group.title .. ': ' .. group.message) or group.title + ) + elseif group.message then + table.insert(messages, group.message) + end + end + local message = table.concat(messages, ', ') + if percentage then + return string.format('%03d: %s', percentage, message) + end + return message +end + ---@private -- Determines whether the given option can be set by `set_defaults`. local function is_empty_or_default(bufnr, option) @@ -1266,10 +1313,23 @@ function lsp.start_client(config) --- @type table<integer,{ type: string, bufnr: integer, method: string}> requests = {}, - -- for $/progress report + + --- Contains $/progress report messages. + --- They have the format {token: integer|string, value: any} + --- For "work done progress", value will be one of: + --- - lsp.WorkDoneProgressBegin, + --- - lsp.WorkDoneProgressReport (extended with title from Begin) + --- - lsp.WorkDoneProgressEnd (extended with title from Begin) + progress = vim.ringbuf(50), + + ---@deprecated use client.progress instead messages = { name = name, messages = {}, progress = {}, status = {} }, dynamic_capabilities = require('vim.lsp._dynamic').new(client_id), } + + ---@type table<string|integer, string> title of unfinished progress sequences by token + client.progress.pending = {} + --- @type lsp.ClientCapabilities client.config.capabilities = config.capabilities or protocol.make_client_capabilities() |