aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim
diff options
context:
space:
mode:
authorBartłomiej Maryńczak <marynczakbartlomiej@gmail.com>2025-04-26 16:08:03 +0200
committerGitHub <noreply@github.com>2025-04-26 07:08:03 -0700
commit83156974497df69a5f449c15d1fb472afdf7b6ff (patch)
tree1f8b606311a7ea9e3620e08173e27f6bc3a9cf00 /runtime/lua/vim
parente45ec5a8527e155c2df68edd69c149f1342486a2 (diff)
downloadrneovim-83156974497df69a5f449c15d1fb472afdf7b6ff.tar.gz
rneovim-83156974497df69a5f449c15d1fb472afdf7b6ff.tar.bz2
rneovim-83156974497df69a5f449c15d1fb472afdf7b6ff.zip
fix(lsp): detect if Client:request resolved synchronously #33624
Problem: In cases when the (in-process) LSP server responds to the request immediately and calls `notify_reply_callback` the request will still be marked as pending, because the code assumes that the response will occur asynchronously. Then the request will be pending forever, because it was already set as "completed" before we even set it as "pending". A workaround is to wrap `notify_replay_callback` in `vim.shedule` ([like so](https://github.com/neovim/neovim/pull/24338#issuecomment-2809568617)] but that seems counterintuitive. Solution: Handle this case in Client:request().
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r--runtime/lua/vim/lsp/client.lua14
1 files changed, 12 insertions, 2 deletions
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
index d8d46e425c..d2f9395b85 100644
--- a/runtime/lua/vim/lsp/client.lua
+++ b/runtime/lua/vim/lsp/client.lua
@@ -678,6 +678,12 @@ function Client:request(method, params, handler, bufnr)
bufnr = vim._resolve_bufnr(bufnr)
local version = lsp.util.buf_versions[bufnr]
log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr)
+
+ -- Detect if request resolved synchronously (only possible with in-process servers).
+ local already_responded = false
+ local request_registered = false
+
+ -- NOTE: rpc.request might call an in-process (Lua) server, thus may be synchronous.
local success, request_id = self.rpc.request(method, params, function(err, result)
handler(err, result, {
method = method,
@@ -688,11 +694,15 @@ function Client:request(method, params, handler, bufnr)
})
end, function(request_id)
-- Called when the server sends a response to the request (including cancelled acknowledgment).
- self:_process_request(request_id, 'complete')
+ if request_registered then
+ self:_process_request(request_id, 'complete')
+ end
+ already_responded = true
end)
- if success and request_id then
+ if success and request_id and not already_responded then
self:_process_request(request_id, 'pending', bufnr, method)
+ request_registered = true
end
return success, request_id