diff options
| author | jdrouhard <john@drouhard.dev> | 2026-07-04 10:22:34 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-04 11:22:34 -0400 |
| commit | f0559997dd33e87bf7bb10ecc5dffb91d29177f6 (patch) | |
| tree | a47dd20c997327fc1e684edc305285a9592effb2 /runtime/lua/vim | |
| parent | 29db6ce84c446fd23fb8e5462b5781bceba5f7aa (diff) | |
| download | rneovim-f0559997dd33e87bf7bb10ecc5dffb91d29177f6.tar.gz rneovim-f0559997dd33e87bf7bb10ecc5dffb91d29177f6.tar.bz2 rneovim-f0559997dd33e87bf7bb10ecc5dffb91d29177f6.zip | |
fix(lsp): semantic tokens reset_timer() usage #40554
Problem: reset_timer() was being called without checking for whether the
client state for the client_id still existed. debounce_request() starts
a timer that defers a call to send_request() which then calls
reset_timer(). If the timer fires after the client_state is erased, then
the deferred function attempts to dereference the timer on a nil client
state.
Solution: Change reset_timer to take a state directly so it can't be nil
and move the reset_timer() call inside a guard that ensures state
exists. Additionally, reset a client's timer when the client detaches so
it doesn't become dangling.
Diffstat (limited to 'runtime/lua/vim')
| -rw-r--r-- | runtime/lua/vim/lsp/semantic_tokens.lua | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua index d3a1c6c505..db4c437d2d 100644 --- a/runtime/lua/vim/lsp/semantic_tokens.lua +++ b/runtime/lua/vim/lsp/semantic_tokens.lua @@ -276,6 +276,7 @@ function STHighlighter:on_detach(client_id) if state then --TODO: delete namespace if/when that becomes possible api.nvim_buf_clear_namespace(self.bufnr, state.namespace, 0, -1) + self:reset_timer(state) self.client_state[client_id] = nil end end @@ -299,14 +300,14 @@ end ---@package ---@param client_id integer function STHighlighter:send_request(client_id) - local version = util.buf_versions[self.bufnr] - - self:reset_timer(client_id) - local client = vim.lsp.get_client_by_id(client_id) local state = self.client_state[client_id] if client and state then + self:reset_timer(state) + + local version = util.buf_versions[self.bufnr] + -- If the server supports range and there's no full result yet, then start with a range -- request if state.supports_range and not state.has_full_result then @@ -320,7 +321,6 @@ function STHighlighter:send_request(client_id) self:send_full_delta_request(client, state, version) end end - -- end end --- Send a range request for the visible area @@ -445,7 +445,7 @@ end ---@private function STHighlighter:cancel_active_request(client_id) - local state = self.client_state[client_id] + local state = assert(self.client_state[client_id]) local client = vim.lsp.get_client_by_id(client_id) ---@param request STActiveRequest @@ -772,8 +772,7 @@ end ---@param client_id integer function STHighlighter:debounce_request(client_id) local state = assert(self.client_state[client_id]) - - self:reset_timer(client_id) + self:reset_timer(state) if self.debounce > 0 then state.timer = vim.defer_fn(function() self:send_request(client_id) @@ -784,9 +783,8 @@ function STHighlighter:debounce_request(client_id) end ---@private ----@param client_id integer -function STHighlighter:reset_timer(client_id) - local state = self.client_state[client_id] +---@param state STClientState +function STHighlighter:reset_timer(state) local timer = state.timer if timer then state.timer = nil |