diff options
author | Mathias Fußenegger <mfussenegger@users.noreply.github.com> | 2022-11-19 10:48:49 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-19 10:48:49 +0100 |
commit | af204dd0f193c3cd3154156c9f9fd40199b840c6 (patch) | |
tree | 9edb14530ecad40c0d60b114ceeb0424af902ba8 /runtime/lua/vim/lsp/rpc.lua | |
parent | 0958dccc6ddeca2e4ab36c1a0f444d2d5995ae99 (diff) | |
download | rneovim-af204dd0f193c3cd3154156c9f9fd40199b840c6.tar.gz rneovim-af204dd0f193c3cd3154156c9f9fd40199b840c6.tar.bz2 rneovim-af204dd0f193c3cd3154156c9f9fd40199b840c6.zip |
feat(lsp): run handler in coroutine to support async response (#21026)
To illustrate a use-case this also changes `window/showMessageRequest`
to use `vim.ui.select`
Diffstat (limited to 'runtime/lua/vim/lsp/rpc.lua')
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index ff62623544..b93b227150 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -391,44 +391,46 @@ function Client:handle_body(body) -- Schedule here so that the users functions don't trigger an error and -- we can still use the result. schedule(function() - local status, result - status, result, err = self:try_call( - client_errors.SERVER_REQUEST_HANDLER_ERROR, - self.dispatchers.server_request, - decoded.method, - decoded.params - ) - local _ = log.debug() - and log.debug( - 'server_request: callback result', - { status = status, result = result, err = err } + coroutine.wrap(function() + local status, result + status, result, err = self:try_call( + client_errors.SERVER_REQUEST_HANDLER_ERROR, + self.dispatchers.server_request, + decoded.method, + decoded.params ) - if status then - if result == nil and err == nil then - error( - string.format( - 'method %q: either a result or an error must be sent to the server in response', - decoded.method - ) - ) - end - if err then - assert( - type(err) == 'table', - 'err must be a table. Use rpc_response_error to help format errors.' - ) - local code_name = assert( - protocol.ErrorCodes[err.code], - 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.' + local _ = log.debug() + and log.debug( + 'server_request: callback result', + { status = status, result = result, err = err } ) - err.message = err.message or code_name + if status then + if result == nil and err == nil then + error( + string.format( + 'method %q: either a result or an error must be sent to the server in response', + decoded.method + ) + ) + end + if err then + assert( + type(err) == 'table', + 'err must be a table. Use rpc_response_error to help format errors.' + ) + local code_name = assert( + protocol.ErrorCodes[err.code], + 'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.' + ) + err.message = err.message or code_name + end + else + -- On an exception, result will contain the error message. + err = rpc_response_error(protocol.ErrorCodes.InternalError, result) + result = nil end - else - -- On an exception, result will contain the error message. - err = rpc_response_error(protocol.ErrorCodes.InternalError, result) - result = nil - end - self:send_response(decoded.id, err, result) + self:send_response(decoded.id, err, result) + end)() end) -- This works because we are expecting vim.NIL here elseif decoded.id and (decoded.result ~= vim.NIL or decoded.error ~= vim.NIL) then |