mirror of
https://github.com/neovim/neovim.git
synced 2026-07-10 03:19:44 +00:00
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.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user