diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 2ad13a2f0c..eb4be0fa4d 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -174,6 +174,14 @@ function Provider:automatic_request() end, 200) end +---@package +---@param client_id integer +---@param on_response function +function Provider:refresh(client_id, on_response) + self:reset_timer() + self:request(client_id, on_response) +end + ---@private ---@param client vim.lsp.Client ---@param unresolved_lens lsp.CodeLens @@ -484,15 +492,12 @@ function M.on_refresh(err, _, ctx) for bufnr, provider in pairs(Provider.active) do for client_id in pairs(provider.client_state) do if client_id == ctx.client_id then - -- Do nothing if a request is already scheduled. - if not provider.timer then - provider:request(client_id, function() - if api.nvim_buf_is_valid(bufnr) then - provider.row_version = {} - vim.api.nvim__redraw({ buf = bufnr, valid = true, flush = false }) - end - end) - end + provider:refresh(client_id, function() + if api.nvim_buf_is_valid(bufnr) then + provider.row_version = {} + vim.api.nvim__redraw({ buf = bufnr, valid = true, flush = false }) + end + end) end end end diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua index 96efc49635..e3731c1e16 100644 --- a/test/functional/plugin/lsp/codelens_spec.lua +++ b/test/functional/plugin/lsp/codelens_spec.lua @@ -306,6 +306,58 @@ describe('vim.lsp.codelens', function() ]]) end) + it('refreshes immediately and cancels a pending automatic refresh', function() + exec_lua(function() + local deferred + local request_count = 0 + local defer_fn = vim.defer_fn + local client = assert(vim.lsp.get_client_by_id(client_id)) + local request = client.request + + --- @diagnostic disable-next-line: duplicate-set-field + vim.defer_fn = function(callback) + deferred = { + callback = callback, + closed = false, + stopped = false, + is_closing = function(self) + return self.closed + end, + stop = function(self) + self.stopped = true + end, + close = function(self) + self.closed = true + end, + } + return deferred + end + + client.request = function(self, method, ...) + if method == 'textDocument/codeLens' then + request_count = request_count + 1 + end + return request(self, method, ...) + end + + vim.api.nvim_buf_set_lines(0, 0, 0, false, { '// changed' }) + assert(deferred, 'expected pending automatic codelens refresh') + + vim.lsp.codelens.on_refresh( + nil, + nil, + { method = 'workspace/codeLens/refresh', client_id = client_id } + ) + + vim.defer_fn = defer_fn + client.request = request + + assert(deferred.stopped, 'expected pending codelens refresh to stop') + assert(deferred.closed, 'expected pending codelens refresh to close') + assert(request_count == 1, 'expected exactly one immediate codelens refresh request') + end) + end) + it('ignores stale codeLens/resolve responses', function() clear_notrace() exec_lua(create_server_definition)