Skip to content

Commit b92e92b

Browse files
authored
feat(lsp): support auto-force escalation in client stop #36430
(cherry picked from commit 02cd564)
1 parent e0fdfd3 commit b92e92b

File tree

3 files changed

+24
-40
lines changed

3 files changed

+24
-40
lines changed

runtime/doc/lsp.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,7 @@ Lua module: vim.lsp.client *lsp-client*
12781278
See |Client:notify()|.
12791279
• {cancel_request} (`fun(self: vim.lsp.Client, id: integer): boolean`)
12801280
See |Client:cancel_request()|.
1281-
{stop} (`fun(self: vim.lsp.Client, force: boolean?)`)
1281+
{stop} (`fun(self: vim.lsp.Client, force: boolean|integer?)`)
12821282
See |Client:stop()|.
12831283
• {is_stopped} (`fun(self: vim.lsp.Client): boolean`) See
12841284
|Client:is_stopped()|.
@@ -1531,8 +1531,14 @@ Client:stop({force}) *Client:stop()*
15311531
you request to stop a client which has previously been requested to
15321532
shutdown, it will automatically escalate and force shutdown.
15331533

1534+
If `force` is a number, it will be treated as the time in milliseconds to
1535+
wait before forcing the shutdown.
1536+
1537+
Note: Forcing shutdown while a server is busy writing out project or index
1538+
files can lead to file corruption.
1539+
15341540
Parameters: ~
1535-
{force} (`boolean?`)
1541+
{force} (`boolean|integer?`)
15361542

15371543
Client:supports_method({method}, {bufnr}) *Client:supports_method()*
15381544
Checks if a client supports a given method. Always returns true for

runtime/lua/vim/lsp.lua

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,42 +1208,8 @@ api.nvim_create_autocmd('VimLeavePre', {
12081208
client:stop()
12091209
end
12101210

1211-
local timeouts = {} --- @type table<integer,integer>
1212-
local max_timeout = 0
1213-
local send_kill = false
1214-
1215-
for client_id, client in pairs(active_clients) do
1216-
local timeout = client.flags.exit_timeout
1217-
if timeout then
1218-
send_kill = true
1219-
timeouts[client_id] = timeout
1220-
max_timeout = math.max(timeout, max_timeout)
1221-
end
1222-
end
1223-
1224-
local poll_time = 50
1225-
1226-
local function check_clients_closed()
1227-
for client_id, timeout in pairs(timeouts) do
1228-
timeouts[client_id] = timeout - poll_time
1229-
end
1230-
1231-
for client_id, _ in pairs(active_clients) do
1232-
if timeouts[client_id] ~= nil and timeouts[client_id] > 0 then
1233-
return false
1234-
end
1235-
end
1236-
return true
1237-
end
1238-
1239-
if send_kill then
1240-
if not vim.wait(max_timeout, check_clients_closed, poll_time) then
1241-
for client_id, client in pairs(active_clients) do
1242-
if timeouts[client_id] ~= nil then
1243-
client:stop(true)
1244-
end
1245-
end
1246-
end
1211+
for _, client in pairs(active_clients) do
1212+
client:stop(client.flags.exit_timeout)
12471213
end
12481214
end,
12491215
})

runtime/lua/vim/lsp/client.lua

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,8 +804,20 @@ end
804804
--- you request to stop a client which has previously been requested to
805805
--- shutdown, it will automatically escalate and force shutdown.
806806
---
807-
--- @param force? boolean
807+
--- If `force` is a number, it will be treated as the time in milliseconds to
808+
--- wait before forcing the shutdown.
809+
---
810+
--- Note: Forcing shutdown while a server is busy writing out project or index
811+
--- files can lead to file corruption.
812+
---
813+
--- @param force? boolean|integer
808814
function Client:stop(force)
815+
if type(force) == 'number' then
816+
vim.defer_fn(function()
817+
self:stop(true)
818+
end, force)
819+
end
820+
809821
local rpc = self.rpc
810822
if rpc.is_closing() then
811823
return
@@ -825,7 +837,7 @@ function Client:stop(force)
825837
if err == nil then
826838
rpc.notify(ms.exit)
827839
else
828-
-- If there was an error in the shutdown request, then term to be safe.
840+
-- If there was an error in the shutdown request, then terminate to be safe.
829841
rpc.terminate()
830842
self._graceful_shutdown_failed = true
831843
end

0 commit comments

Comments
 (0)