mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 12:28:18 +00:00
refactor(lsp): merge rpc.domain_socket_connect into rpc.connect (#28398)
See discussion in https://github.com/neovim/neovim/pull/26850
This commit is contained in:

committed by
GitHub

parent
206475d791
commit
97323d821b
@@ -2229,32 +2229,20 @@ Lua module: vim.lsp.rpc *lsp-rpc*
|
|||||||
• {terminate} (`fun()`)
|
• {terminate} (`fun()`)
|
||||||
|
|
||||||
|
|
||||||
connect({host}, {port}) *vim.lsp.rpc.connect()*
|
connect({host_or_path}, {port}) *vim.lsp.rpc.connect()*
|
||||||
Create a LSP RPC client factory that connects via TCP to the given host
|
Create a LSP RPC client factory that connects to either:
|
||||||
and port.
|
• a named pipe (windows)
|
||||||
|
• a domain socket (unix)
|
||||||
|
• a host and port via TCP
|
||||||
|
|
||||||
Return a function that can be passed to the `cmd` field for
|
Return a function that can be passed to the `cmd` field for
|
||||||
|vim.lsp.start_client()| or |vim.lsp.start()|.
|
|vim.lsp.start_client()| or |vim.lsp.start()|.
|
||||||
|
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {host} (`string`) host to connect to
|
• {host_or_path} (`string`) host to connect to or path to a pipe/domain
|
||||||
• {port} (`integer`) port to connect to
|
socket
|
||||||
|
• {port} (`integer?`) TCP port to connect to. If absent the
|
||||||
Return: ~
|
first argument must be a pipe
|
||||||
(`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
|
|
||||||
|
|
||||||
*vim.lsp.rpc.domain_socket_connect()*
|
|
||||||
domain_socket_connect({pipe_path})
|
|
||||||
Create a LSP RPC client factory that connects via named pipes (Windows) or
|
|
||||||
unix domain sockets (Unix) to the given pipe_path (file path on Unix and
|
|
||||||
name on Windows).
|
|
||||||
|
|
||||||
Return a function that can be passed to the `cmd` field for
|
|
||||||
|vim.lsp.start_client()| or |vim.lsp.start()|.
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {pipe_path} (`string`) file path of the domain socket (Unix) or name
|
|
||||||
of the named pipe (Windows) to connect to
|
|
||||||
|
|
||||||
Return: ~
|
Return: ~
|
||||||
(`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
|
(`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
|
||||||
|
@@ -225,7 +225,7 @@ The following new APIs and features were added.
|
|||||||
• |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to
|
• |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to
|
||||||
the original LSP `Location` or `LocationLink`.
|
the original LSP `Location` or `LocationLink`.
|
||||||
• Added support for connecting to servers using named pipes (Windows) or
|
• Added support for connecting to servers using named pipes (Windows) or
|
||||||
unix domain sockets (Unix) via |vim.lsp.rpc.domain_socket_connect()|.
|
unix domain sockets (Unix) via |vim.lsp.rpc.connect()|.
|
||||||
• Added support for `completionList.itemDefaults`, reducing overhead when
|
• Added support for `completionList.itemDefaults`, reducing overhead when
|
||||||
computing completion items where properties often share the same value
|
computing completion items where properties often share the same value
|
||||||
(e.g. `commitCharacters`). Note that this might affect plugins and
|
(e.g. `commitCharacters`). Note that this might affect plugins and
|
||||||
|
@@ -621,22 +621,33 @@ local function merge_dispatchers(dispatchers)
|
|||||||
return merged
|
return merged
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create a LSP RPC client factory that connects via TCP to the given host and port.
|
--- Create a LSP RPC client factory that connects to either:
|
||||||
|
---
|
||||||
|
--- - a named pipe (windows)
|
||||||
|
--- - a domain socket (unix)
|
||||||
|
--- - a host and port via TCP
|
||||||
---
|
---
|
||||||
--- Return a function that can be passed to the `cmd` field for
|
--- Return a function that can be passed to the `cmd` field for
|
||||||
--- |vim.lsp.start_client()| or |vim.lsp.start()|.
|
--- |vim.lsp.start_client()| or |vim.lsp.start()|.
|
||||||
---
|
---
|
||||||
---@param host string host to connect to
|
---@param host_or_path string host to connect to or path to a pipe/domain socket
|
||||||
---@param port integer port to connect to
|
---@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
|
---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
|
||||||
function M.connect(host, port)
|
function M.connect(host_or_path, port)
|
||||||
return function(dispatchers)
|
return function(dispatchers)
|
||||||
dispatchers = merge_dispatchers(dispatchers)
|
dispatchers = merge_dispatchers(dispatchers)
|
||||||
local tcp = assert(uv.new_tcp())
|
local handle = (
|
||||||
|
port == nil
|
||||||
|
and assert(
|
||||||
|
uv.new_pipe(false),
|
||||||
|
string.format('Pipe with name %s could not be opened.', host_or_path)
|
||||||
|
)
|
||||||
|
or assert(uv.new_tcp(), 'Could not create new TCP socket')
|
||||||
|
)
|
||||||
local closing = false
|
local closing = false
|
||||||
local transport = {
|
local transport = {
|
||||||
write = function(msg)
|
write = function(msg)
|
||||||
tcp:write(msg)
|
handle:write(msg)
|
||||||
end,
|
end,
|
||||||
is_closing = function()
|
is_closing = function()
|
||||||
return closing
|
return closing
|
||||||
@@ -644,18 +655,19 @@ function M.connect(host, port)
|
|||||||
terminate = function()
|
terminate = function()
|
||||||
if not closing then
|
if not closing then
|
||||||
closing = true
|
closing = true
|
||||||
tcp:shutdown()
|
handle:shutdown()
|
||||||
tcp:close()
|
handle:close()
|
||||||
dispatchers.on_exit(0, 0)
|
dispatchers.on_exit(0, 0)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
local client = new_client(dispatchers, transport)
|
local client = new_client(dispatchers, transport)
|
||||||
tcp:connect(host, port, function(err)
|
local function on_connect(err)
|
||||||
if err then
|
if err then
|
||||||
|
local address = port == nil and host_or_path or (host_or_path .. ':' .. port)
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
vim.notify(
|
vim.notify(
|
||||||
string.format('Could not connect to %s:%s, reason: %s', host, port, vim.inspect(err)),
|
string.format('Could not connect to %s, reason: %s', address, vim.inspect(err)),
|
||||||
vim.log.levels.WARN
|
vim.log.levels.WARN
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
@@ -664,64 +676,15 @@ function M.connect(host, port)
|
|||||||
local handle_body = function(body)
|
local handle_body = function(body)
|
||||||
client:handle_body(body)
|
client:handle_body(body)
|
||||||
end
|
end
|
||||||
tcp:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err)
|
handle:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err)
|
||||||
client:on_error(M.client_errors.READ_ERROR, read_err)
|
client:on_error(M.client_errors.READ_ERROR, read_err)
|
||||||
end))
|
end))
|
||||||
end)
|
|
||||||
|
|
||||||
return public_client(client)
|
|
||||||
end
|
end
|
||||||
end
|
if port == nil then
|
||||||
|
handle:connect(host_or_path, on_connect)
|
||||||
--- Create a LSP RPC client factory that connects via named pipes (Windows)
|
else
|
||||||
--- or unix domain sockets (Unix) to the given pipe_path (file path on
|
handle:connect(host_or_path, port, on_connect)
|
||||||
--- Unix and name on Windows).
|
|
||||||
---
|
|
||||||
--- Return a function that can be passed to the `cmd` field for
|
|
||||||
--- |vim.lsp.start_client()| or |vim.lsp.start()|.
|
|
||||||
---
|
|
||||||
---@param pipe_path string file path of the domain socket (Unix) or name of the named pipe (Windows) to connect to
|
|
||||||
---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
|
|
||||||
function M.domain_socket_connect(pipe_path)
|
|
||||||
return function(dispatchers)
|
|
||||||
dispatchers = merge_dispatchers(dispatchers)
|
|
||||||
local pipe =
|
|
||||||
assert(uv.new_pipe(false), string.format('pipe with name %s could not be opened.', pipe_path))
|
|
||||||
local closing = false
|
|
||||||
local transport = {
|
|
||||||
write = vim.schedule_wrap(function(msg)
|
|
||||||
pipe:write(msg)
|
|
||||||
end),
|
|
||||||
is_closing = function()
|
|
||||||
return closing
|
|
||||||
end,
|
|
||||||
terminate = function()
|
|
||||||
if not closing then
|
|
||||||
closing = true
|
|
||||||
pipe:shutdown()
|
|
||||||
pipe:close()
|
|
||||||
dispatchers.on_exit(0, 0)
|
|
||||||
end
|
end
|
||||||
end,
|
|
||||||
}
|
|
||||||
local client = new_client(dispatchers, transport)
|
|
||||||
pipe:connect(pipe_path, function(err)
|
|
||||||
if err then
|
|
||||||
vim.schedule(function()
|
|
||||||
vim.notify(
|
|
||||||
string.format('Could not connect to :%s, reason: %s', pipe_path, vim.inspect(err)),
|
|
||||||
vim.log.levels.WARN
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local handle_body = function(body)
|
|
||||||
client:handle_body(body)
|
|
||||||
end
|
|
||||||
pipe:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err)
|
|
||||||
client:on_error(M.client_errors.READ_ERROR, read_err)
|
|
||||||
end))
|
|
||||||
end)
|
|
||||||
|
|
||||||
return public_client(client)
|
return public_client(client)
|
||||||
end
|
end
|
||||||
|
@@ -4311,7 +4311,7 @@ describe('LSP', function()
|
|||||||
]]
|
]]
|
||||||
eq('initialize', result.method)
|
eq('initialize', result.method)
|
||||||
end)
|
end)
|
||||||
it('can connect to lsp server via rpc.domain_socket_connect', function()
|
it('can connect to lsp server via pipe or domain_socket', function()
|
||||||
local tmpfile --- @type string
|
local tmpfile --- @type string
|
||||||
if is_os('win') then
|
if is_os('win') then
|
||||||
tmpfile = '\\\\.\\\\pipe\\pipe.test'
|
tmpfile = '\\\\.\\\\pipe\\pipe.test'
|
||||||
@@ -4336,7 +4336,7 @@ describe('LSP', function()
|
|||||||
client:close()
|
client:close()
|
||||||
end))
|
end))
|
||||||
end)
|
end)
|
||||||
vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.domain_socket_connect(SOCK) })
|
vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.connect(SOCK) })
|
||||||
vim.wait(1000, function() return init ~= nil end)
|
vim.wait(1000, function() return init ~= nil end)
|
||||||
assert(init, "server must receive `initialize` request")
|
assert(init, "server must receive `initialize` request")
|
||||||
server:close()
|
server:close()
|
||||||
|
Reference in New Issue
Block a user