aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/lsp.txt6
-rw-r--r--runtime/lua/vim/lsp/rpc.lua8
-rw-r--r--test/functional/plugin/lsp/testutil.lua27
-rw-r--r--test/functional/plugin/lsp_spec.lua40
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()