mirror of
https://github.com/neovim/neovim
synced 2025-07-16 09:11:51 +00:00
fix(lsp): on detach, cancel pending foldingRange requests #31509
Problem: 1. Open a relatively large file (so the server needs some time to process the request). 2. Then immediately execute `:bdelete`. 3. Once the request is completed, the handler will obtain the bufstate of a buffer already unloaded. Error executing vim.schedule lua callback: ...7841_1/share/nvim/runtime/lua/vim/lsp/_folding_range.lua:119: assertion failed! stack traceback: [C]: in function 'assert' ...7841_1/share/nvim/runtime/lua/vim/lsp/_folding_range.lua:119: in function 'multi_handler' ...7841_1/share/nvim/runtime/lua/vim/lsp/_folding_range.lua:140: in function 'handler' ...HEAD-c137841_1/share/nvim/runtime/lua/vim/lsp/client.lua:669: in function '' vim/_editor.lua: in function <vim/_editor.lua:0> Solution: On detach, cancel all pending textDocument_foldingRange requests.
This commit is contained in:
@ -2153,6 +2153,41 @@ local function make_line_range_params(bufnr, start_line, end_line, position_enco
|
||||
}
|
||||
end
|
||||
|
||||
---@class (private) vim.lsp.util._cancel_requests.Filter
|
||||
---@field bufnr? integer
|
||||
---@field clients? vim.lsp.Client[]
|
||||
---@field method? string
|
||||
---@field type? string
|
||||
|
||||
---@private
|
||||
--- Cancel all {filter}ed requests.
|
||||
---
|
||||
---@param filter? vim.lsp.util._cancel_requests.Filter
|
||||
function M._cancel_requests(filter)
|
||||
filter = filter or {}
|
||||
local bufnr = filter.bufnr and vim._resolve_bufnr(filter.bufnr) or nil
|
||||
local clients = filter.clients
|
||||
local method = filter.method
|
||||
local type = filter.type
|
||||
|
||||
for _, client in
|
||||
ipairs(clients or vim.lsp.get_clients({
|
||||
bufnr = bufnr,
|
||||
method = method,
|
||||
}))
|
||||
do
|
||||
for id, request in pairs(client.requests) do
|
||||
if
|
||||
(bufnr == nil or bufnr == request.bufnr)
|
||||
and (method == nil or method == request.method)
|
||||
and (type == nil or type == request.type)
|
||||
then
|
||||
client:cancel_request(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@class (private) vim.lsp.util._refresh.Opts
|
||||
---@field bufnr integer? Buffer to refresh (default: 0)
|
||||
---@field only_visible? boolean Whether to only refresh for the visible regions of the buffer (default: false)
|
||||
@ -2180,12 +2215,12 @@ function M._refresh(method, opts)
|
||||
if api.nvim_win_get_buf(window) == bufnr then
|
||||
local first = vim.fn.line('w0', window)
|
||||
local last = vim.fn.line('w$', window)
|
||||
M._cancel_requests({
|
||||
bufnr = bufnr,
|
||||
clients = clients,
|
||||
type = 'pending',
|
||||
})
|
||||
for _, client in ipairs(clients) do
|
||||
for rid, req in pairs(client.requests) do
|
||||
if req.method == method and req.type == 'pending' and req.bufnr == bufnr then
|
||||
client:cancel_request(rid)
|
||||
end
|
||||
end
|
||||
client:request(method, {
|
||||
textDocument = textDocument,
|
||||
range = make_line_range_params(bufnr, first - 1, last - 1, client.offset_encoding),
|
||||
|
Reference in New Issue
Block a user