diff options
author | Tristan Knight <admin@snappeh.com> | 2024-09-03 16:10:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-03 08:10:39 -0700 |
commit | 45e76acaa053a077cab49b6606536d3f2646f033 (patch) | |
tree | 41f6c72705df360f795777bb68b6a36e75643ab0 | |
parent | fdd3a9cdf7167ca8fc84ec9a7e583f6410a27188 (diff) | |
download | rneovim-45e76acaa053a077cab49b6606536d3f2646f033.tar.gz rneovim-45e76acaa053a077cab49b6606536d3f2646f033.tar.bz2 rneovim-45e76acaa053a077cab49b6606536d3f2646f033.zip |
feat(lsp): support hostname in rpc.connect #30238
Updated the `rpc.connect` function to support connecting to LSP servers
using hostnames, not just IP addresses. This change includes updates to
the documentation and additional test cases to verify the new
functionality.
- Modified `connect` function to resolve hostnames.
- Updated documentation to reflect the change.
- Added test case for connecting using hostname.
Added a TCP echo server utility function to the LSP test suite. This
server echoes the first message it receives and is used in tests to
verify LSP server connections via both IP address and hostname.
Refactored existing tests to use the new utility function.
-rw-r--r-- | runtime/doc/lsp.txt | 6 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 8 | ||||
-rw-r--r-- | test/functional/plugin/lsp/testutil.lua | 27 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 40 |
4 files changed, 59 insertions, 22 deletions
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index a8b5825e63..e820d54a9e 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -2311,14 +2311,14 @@ connect({host_or_path}, {port}) *vim.lsp.rpc.connect()* Create a LSP RPC client factory that connects to either: • a named pipe (windows) • a domain socket (unix) - • a host and port via TCP (host must be IP address) + • a host and port via TCP Return a function that can be passed to the `cmd` field for |vim.lsp.start_client()| or |vim.lsp.start()|. Parameters: ~ - • {host_or_path} (`string`) host (IP address) to connect to or path to - a pipe/domain socket + • {host_or_path} (`string`) host to connect to or path to a pipe/domain + socket • {port} (`integer?`) TCP port to connect to. If absent the first argument must be a pipe diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index a9c6723094..d81eae20d1 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -627,12 +627,12 @@ end --- --- - a named pipe (windows) --- - a domain socket (unix) ---- - a host and port via TCP (host must be IP address) +--- - a host and port via TCP --- --- Return a function that can be passed to the `cmd` field for --- |vim.lsp.start_client()| or |vim.lsp.start()|. --- ----@param host_or_path string host (IP address) to connect to or path to a pipe/domain socket +---@param host_or_path string host to connect to or path to a pipe/domain socket ---@param port integer? TCP port to connect to. If absent the first argument must be a pipe ---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient function M.connect(host_or_path, port) @@ -703,7 +703,9 @@ function M.connect(host_or_path, port) if port == nil then handle:connect(host_or_path, on_connect) else - handle:connect(host_or_path, port, on_connect) + local info = uv.getaddrinfo(host_or_path, nil) + local resolved_host = info and info[1] and info[1].addr or host_or_path + handle:connect(resolved_host, port, on_connect) end return public_client(client) diff --git a/test/functional/plugin/lsp/testutil.lua b/test/functional/plugin/lsp/testutil.lua index 2595f6ad09..f60d111f87 100644 --- a/test/functional/plugin/lsp/testutil.lua +++ b/test/functional/plugin/lsp/testutil.lua @@ -21,6 +21,33 @@ function M.clear_notrace() } end +M.create_tcp_echo_server = function() + --- Create a TCP server that echos the first message it receives. + --- @param host string + ---@return uv.uv_tcp_t + ---@return integer + ---@return fun():string|nil + function _G._create_tcp_server(host) + local uv = vim.uv + local server = assert(uv.new_tcp()) + local init = nil + server:bind(host, 0) + server:listen(127, function(err) + assert(not err, err) + local socket = assert(uv.new_tcp()) + server:accept(socket) + socket:read_start(require('vim.lsp.rpc').create_read_loop(function(body) + init = body + socket:close() + end)) + end) + local port = server:getsockname().port + return server, port, function() + return init + end + end +end + M.create_server_definition = function() function _G._create_server(opts) opts = opts or {} diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index ff042424f9..1347ea9745 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -33,6 +33,7 @@ local create_server_definition = t_lsp.create_server_definition local fake_lsp_code = t_lsp.fake_lsp_code local fake_lsp_logfile = t_lsp.fake_lsp_logfile local test_rpc_server = t_lsp.test_rpc_server +local create_tcp_echo_server = t_lsp.create_tcp_echo_server local function get_buf_option(name, bufnr) bufnr = bufnr or 'BUFFER' @@ -4981,26 +4982,33 @@ describe('LSP', function() end) describe('cmd', function() - it('can connect to lsp server via rpc.connect', function() + it('connects to lsp server via rpc.connect using ip address', function() + exec_lua(create_tcp_echo_server) local result = exec_lua(function() - local uv = vim.uv - local server = assert(uv.new_tcp()) - local init = nil - server:bind('127.0.0.1', 0) - server:listen(127, function(err) - assert(not err, err) - local socket = assert(uv.new_tcp()) - server:accept(socket) - socket:read_start(require('vim.lsp.rpc').create_read_loop(function(body) - init = body - socket:close() - end)) - end) - local port = server:getsockname().port + local server, port, last_message = _G._create_tcp_server('127.0.0.1') vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect('127.0.0.1', port) }) vim.wait(1000, function() - return init ~= nil + return last_message() ~= nil + end) + local init = last_message() + assert(init, 'server must receive `initialize` request') + server:close() + server:shutdown() + return vim.json.decode(init) + end) + eq('initialize', result.method) + end) + + it('connects to lsp server via rpc.connect using hostname', function() + skip(is_os('bsd'), 'issue with host resolution in ci') + exec_lua(create_tcp_echo_server) + local result = exec_lua(function() + local server, port, last_message = _G._create_tcp_server('::1') + vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect('localhost', port) }) + vim.wait(1000, function() + return last_message() ~= nil end) + local init = last_message() assert(init, 'server must receive `initialize` request') server:close() server:shutdown() |