aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/util.lua
diff options
context:
space:
mode:
authorYi Ming <ofseed@foxmail.com>2025-02-12 22:22:59 +0800
committerGitHub <noreply@github.com>2025-02-12 06:22:59 -0800
commitbe8d87014c0c120ece50aabff307c1f5d9167ec0 (patch)
tree2a3bf35919203553c0e3449b3a4a18261d80e954 /runtime/lua/vim/lsp/util.lua
parent2c629ad13f19ac262c0ae85628ceec6d4e0243fb (diff)
downloadrneovim-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.lua45
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),