diff options
author | Yi Ming <ofseed@foxmail.com> | 2025-02-12 22:22:59 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-12 06:22:59 -0800 |
commit | be8d87014c0c120ece50aabff307c1f5d9167ec0 (patch) | |
tree | 2a3bf35919203553c0e3449b3a4a18261d80e954 /runtime/lua/vim/lsp/util.lua | |
parent | 2c629ad13f19ac262c0ae85628ceec6d4e0243fb (diff) | |
download | rneovim-be8d87014c0c120ece50aabff307c1f5d9167ec0.tar.gz rneovim-be8d87014c0c120ece50aabff307c1f5d9167ec0.tar.bz2 rneovim-be8d87014c0c120ece50aabff307c1f5d9167ec0.zip |
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.
Diffstat (limited to 'runtime/lua/vim/lsp/util.lua')
-rw-r--r-- | runtime/lua/vim/lsp/util.lua | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 86c0a2b3db..ba519614c0 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -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), |