aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp.lua
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/lsp.lua')
-rw-r--r--runtime/lua/vim/lsp.lua88
1 files changed, 52 insertions, 36 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index d45827b0d7..93ec9ed624 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -483,6 +483,13 @@ end
--- result. You can use this with `client.cancel_request(request_id)`
--- to cancel the request.
---
+--- - request_sync(method, params, timeout_ms, bufnr)
+--- Sends a request to the server and synchronously waits for the response.
+--- This is a wrapper around {client.request}
+--- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from
+--- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a
+--- string describing the failure reason. If the request was unsuccessful returns `nil`.
+---
--- - notify(method, params)
--- Sends a notification to an LSP server.
--- Returns: a boolean to indicate if the notification was successful. If
@@ -891,6 +898,42 @@ function lsp.start_client(config)
end
--@private
+ --- Sends a request to the server and synchronously waits for the response.
+ ---
+ --- This is a wrapper around {client.request}
+ ---
+ --@param method (string) LSP method name.
+ --@param params (table) LSP request params.
+ --@param timeout_ms (number, optional, default=1000) Maximum time in
+ ---milliseconds to wait for a result.
+ --@param bufnr (number) Buffer handle (0 for current).
+ --@returns { err=err, result=result }, a dictionary, where `err` and `result` come from the |lsp-handler|.
+ ---On timeout, cancel or error, returns `(nil, err)` where `err` is a
+ ---string describing the failure reason. If the request was unsuccessful
+ ---returns `nil`.
+ --@see |vim.lsp.buf_request_sync()|
+ function client.request_sync(method, params, timeout_ms, bufnr)
+ local request_result = nil
+ local function _sync_handler(err, _, result)
+ request_result = { err = err, result = result }
+ end
+
+ local success, request_id = client.request(method, params, _sync_handler,
+ bufnr)
+ if not success then return nil end
+
+ local wait_result, reason = vim.wait(timeout_ms or 1000, function()
+ return request_result ~= nil
+ end, 10)
+
+ if not wait_result then
+ client.cancel_request(request_id)
+ return nil, wait_result_reason[reason]
+ end
+ return request_result
+ end
+
+ --@private
--- Sends a notification to an LSP server.
---
--@param method (string) LSP method name.
@@ -916,7 +959,7 @@ function lsp.start_client(config)
-- Track this so that we can escalate automatically if we've alredy tried a
-- graceful shutdown
- local tried_graceful_shutdown = false
+ local graceful_shutdown_failed = false
--@private
--- Stops a client, optionally with force.
---
@@ -938,11 +981,10 @@ function lsp.start_client(config)
if handle:is_closing() then
return
end
- if force or (not client.initialized) or tried_graceful_shutdown then
+ if force or (not client.initialized) or graceful_shutdown_failed then
handle:kill(15)
return
end
- tried_graceful_shutdown = true
-- Sending a signal after a process has exited is acceptable.
rpc.request('shutdown', nil, function(err, _)
if err == nil then
@@ -950,6 +992,7 @@ function lsp.start_client(config)
else
-- If there was an error in the shutdown request, then term to be safe.
handle:kill(15)
+ graceful_shutdown_failed = true
end
end)
end
@@ -1179,38 +1222,11 @@ function lsp._vim_exit_handler()
client.stop()
end
- local function wait_async(timeout, ms, predicate, cb)
- local timer = uv.new_timer()
- local time = 0
-
- local function done(in_time)
- timer:stop()
- timer:close()
- cb(in_time)
+ if not vim.wait(500, function() return tbl_isempty(active_clients) end, 50) then
+ for _, client in pairs(active_clients) do
+ client.stop(true)
end
-
- timer:start(0, ms, function()
- if predicate() == true then
- done(true)
- return
- end
-
- if time == timeout then
- done(false)
- return
- end
-
- time = time + ms
- end)
end
-
- wait_async(500, 50, function() return tbl_isempty(active_clients) end, function(in_time)
- if not in_time then
- for _, client in pairs(active_clients) do
- client.stop(true)
- end
- end
- end)
end
nvim_command("autocmd VimLeavePre * lua vim.lsp._vim_exit_handler()")
@@ -1316,12 +1332,12 @@ end
---
--- Calls |vim.lsp.buf_request_all()| but blocks Nvim while awaiting the result.
--- Parameters are the same as |vim.lsp.buf_request()| but the return result is
---- different. Wait maximum of {timeout_ms} (default 100) ms.
+--- different. Wait maximum of {timeout_ms} (default 1000) ms.
---
--@param bufnr (number) Buffer handle, or 0 for current.
--@param method (string) LSP method name
--@param params (optional, table) Parameters to send to the server
---@param timeout_ms (optional, number, default=100) Maximum time in
+--@param timeout_ms (optional, number, default=1000) Maximum time in
--- milliseconds to wait for a result.
---
--@returns Map of client_id:request_result. On timeout, cancel or error,
@@ -1334,7 +1350,7 @@ function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
request_results = it
end)
- local wait_result, reason = vim.wait(timeout_ms or 100, function()
+ local wait_result, reason = vim.wait(timeout_ms or 1000, function()
return request_results ~= nil
end, 10)