aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua
diff options
context:
space:
mode:
authorjdrouhard <john@drouhard.dev>2026-07-04 10:22:34 -0500
committerGitHub <noreply@github.com>2026-07-04 11:22:34 -0400
commitf0559997dd33e87bf7bb10ecc5dffb91d29177f6 (patch)
treea47dd20c997327fc1e684edc305285a9592effb2 /runtime/lua
parent29db6ce84c446fd23fb8e5462b5781bceba5f7aa (diff)
downloadrneovim-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')
-rw-r--r--runtime/lua/vim/lsp/semantic_tokens.lua20
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