fix(lsp): schedule removal of client object (#20148)

The execution of the LspDetach autocommands in the LSP client's on_exit
function are scheduled on the event loop to avoid making API calls in a
fast context; however, this means that by the time the LspDetach
autocommands finally run the client object has already been deleted.

To address this, we also schedule the deletion of the client on the
event loop so that it is guaranteed to occur after all of the LspDetach
autocommands have fired.
This commit is contained in:
Gregory Anders
2022-09-10 18:56:29 -06:00
committed by GitHub
parent 91a2e7a571
commit 9b4cab0126

View File

@@ -1147,33 +1147,34 @@ function lsp.start_client(config)
local namespace = vim.lsp.diagnostic.get_namespace(client_id)
vim.diagnostic.reset(namespace, bufnr)
end)
client_ids[client_id] = nil
end
if vim.tbl_isempty(client_ids) then
vim.schedule(function()
unset_defaults(bufnr)
client_ids[client_id] = nil
if vim.tbl_isempty(client_ids) then
unset_defaults(bufnr)
end
end)
end
end
local client = active_clients[client_id] and active_clients[client_id]
or uninitialized_clients[client_id]
active_clients[client_id] = nil
uninitialized_clients[client_id] = nil
-- Client can be absent if executable starts, but initialize fails
-- init/attach won't have happened
if client then
changetracking.reset(client)
end
if code ~= 0 or (signal ~= 0 and signal ~= 15) then
local msg =
string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal)
vim.schedule(function()
-- Schedule the deletion of the client object so that it exists in the execution of LspDetach
-- autocommands
vim.schedule(function()
local client = active_clients[client_id] and active_clients[client_id]
or uninitialized_clients[client_id]
active_clients[client_id] = nil
uninitialized_clients[client_id] = nil
-- Client can be absent if executable starts, but initialize fails
-- init/attach won't have happened
if client then
changetracking.reset(client)
end
if code ~= 0 or (signal ~= 0 and signal ~= 15) then
local msg =
string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal)
vim.notify(msg, vim.log.levels.WARN)
end)
end
end
end)
end
-- Start the RPC client.