fix(lsp): :lsp restart restarts on client exit #37125

Problem:
`:lsp restart` detects when a client has exited by using the `LspDetach`
autocommand. This works correctly in common cases, but breaks when
restarting a client which is not attached to any buffer. It also breaks
if a client is detached in between `:lsp restart` and the actual
stopping of the client.

Solution:
Move restart logic into `vim/lsp/client.lua`, so it can hook in to
`_on_exit()`. The public `on_exit` callback cannot be used for this, as
`:lsp restart` needs to ensure the restart only happens once, even if
the command is run multiple times on the same client.
This commit is contained in:
Olivia Kinnear
2026-01-02 01:58:10 -05:00
committed by GitHub
parent 3ac76977bc
commit a03ab03a10
4 changed files with 42 additions and 30 deletions

View File

@@ -908,6 +908,31 @@ function Client:stop(force)
end)
end
--- Stops a client, then starts a new client with the same config and attached
--- buffers.
---
--- @param force? integer|boolean See [Client:stop()] for details.
--- (default: `self.exit_timeout`)
function Client:_restart(force)
validate('force', force, { 'number', 'boolean' }, true)
self._handle_restart = function()
--- @type integer[]
local attached_buffers = vim.tbl_keys(self.attached_buffers)
vim.schedule(function()
local new_client_id = lsp.start(self.config, { attach = false })
if new_client_id then
for _, buffer in ipairs(attached_buffers) do
lsp.buf_attach_client(buffer, new_client_id)
end
end
end)
end
self:stop(force)
end
--- Get options for a method that is registered dynamically.
--- @param method vim.lsp.protocol.Method | vim.lsp.protocol.Method.Registration
function Client:_supports_registration(method)
@@ -1334,6 +1359,11 @@ function Client:_on_exit(code, signal)
end
end)
if self._handle_restart ~= nil then
self._handle_restart()
self._handle_restart = nil
end
-- Schedule the deletion of the client object so that it exists in the execution of LspDetach
-- autocommands
vim.schedule(function()