diff options
Diffstat (limited to 'runtime/lua/vim/lsp.lua')
-rw-r--r-- | runtime/lua/vim/lsp.lua | 88 |
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) |