diff options
author | Mathias Fussenegger <f.mathias@zignar.net> | 2022-08-24 20:25:34 +0200 |
---|---|---|
committer | Mathias Fussenegger <f.mathias@zignar.net> | 2022-08-28 14:07:53 +0200 |
commit | 60ec6e34d585a7f633d49aab790066c1740885e1 (patch) | |
tree | 94527df960d8c891c767a5141477f32107a98db6 /runtime/lua/vim/lsp/rpc.lua | |
parent | 46bb34e26b3bee89fd1d5d9d1bebced00000732d (diff) | |
download | rneovim-60ec6e34d585a7f633d49aab790066c1740885e1.tar.gz rneovim-60ec6e34d585a7f633d49aab790066c1740885e1.tar.bz2 rneovim-60ec6e34d585a7f633d49aab790066c1740885e1.zip |
feat(lsp): add tcp support
Diffstat (limited to 'runtime/lua/vim/lsp/rpc.lua')
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 104 |
1 files changed, 81 insertions, 23 deletions
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 5ac1b91e70..238c6c0570 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -556,6 +556,84 @@ local function public_client(client) return result end +---@private +local function merge_dispatchers(dispatchers) + if dispatchers then + local user_dispatchers = dispatchers + dispatchers = {} + for dispatch_name, default_dispatch in pairs(default_dispatchers) do + local user_dispatcher = user_dispatchers[dispatch_name] + if user_dispatcher then + if type(user_dispatcher) ~= 'function' then + error(string.format('dispatcher.%s must be a function', dispatch_name)) + end + -- server_request is wrapped elsewhere. + if + not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason. + then + user_dispatcher = schedule_wrap(user_dispatcher) + end + dispatchers[dispatch_name] = user_dispatcher + else + dispatchers[dispatch_name] = default_dispatch + end + end + else + dispatchers = default_dispatchers + end + return dispatchers +end + +--- Create a LSP RPC client factory that connects via TCP to the given host +--- and port +--- +---@param host string +---@param port number +---@return function +local function connect(host, port) + return function(dispatchers) + dispatchers = merge_dispatchers(dispatchers) + local tcp = uv.new_tcp() + local closing = false + local transport = { + write = function(msg) + tcp:write(msg) + end, + is_closing = function() + return closing + end, + terminate = function() + if not closing then + closing = true + tcp:shutdown() + tcp:close() + dispatchers.on_exit(0, 0) + end + end, + } + local client = new_client(dispatchers, transport) + tcp:connect(host, port, function(err) + if err then + vim.schedule(function() + vim.notify( + string.format('Could not connect to %s:%s, reason: %s', host, port, vim.inspect(err)), + vim.log.levels.WARN + ) + end) + return + end + local handle_body = function(body) + client:handle_body(body) + end + tcp:read_start(create_read_loop(handle_body, transport.terminate, function(read_err) + client:on_error(client_errors.READ_ERROR, read_err) + end)) + end) + + return public_client(client) + end +end + --- Starts an LSP server process and create an LSP RPC client object to --- interact with it. Communication with the server is currently limited to stdio. --- @@ -593,30 +671,8 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) if extra_spawn_params and extra_spawn_params.cwd then assert(is_dir(extra_spawn_params.cwd), 'cwd must be a directory') end - if dispatchers then - local user_dispatchers = dispatchers - dispatchers = {} - for dispatch_name, default_dispatch in pairs(default_dispatchers) do - local user_dispatcher = user_dispatchers[dispatch_name] - if user_dispatcher then - if type(user_dispatcher) ~= 'function' then - error(string.format('dispatcher.%s must be a function', dispatch_name)) - end - -- server_request is wrapped elsewhere. - if - not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason. - then - user_dispatcher = schedule_wrap(user_dispatcher) - end - dispatchers[dispatch_name] = user_dispatcher - else - dispatchers[dispatch_name] = default_dispatch - end - end - else - dispatchers = default_dispatchers - end + dispatchers = merge_dispatchers(dispatchers) local stdin = uv.new_pipe(false) local stdout = uv.new_pipe(false) local stderr = uv.new_pipe(false) @@ -693,8 +749,10 @@ end return { start = start, + connect = connect, rpc_response_error = rpc_response_error, format_rpc_error = format_rpc_error, client_errors = client_errors, + create_read_loop = create_read_loop, } -- vim:sw=2 ts=2 et |