aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/lsp')
-rw-r--r--runtime/lua/vim/lsp/client.lua14
-rw-r--r--runtime/lua/vim/lsp/inlay_hint.lua32
-rw-r--r--runtime/lua/vim/lsp/rpc.lua25
3 files changed, 40 insertions, 31 deletions
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
index 98b3cfc762..448f986cd3 100644
--- a/runtime/lua/vim/lsp/client.lua
+++ b/runtime/lua/vim/lsp/client.lua
@@ -37,7 +37,7 @@ local validate = vim.validate
--- `is_closing` and `terminate`.
--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|.
--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()|
---- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?
+--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
---
--- Directory to launch the `cmd` process. Not related to `root_dir`.
--- (default: cwd)
@@ -506,25 +506,17 @@ function Client.create(config)
}
-- Start the RPC client.
- local rpc --- @type vim.lsp.rpc.PublicClient?
local config_cmd = config.cmd
if type(config_cmd) == 'function' then
- rpc = config_cmd(dispatchers)
+ self.rpc = config_cmd(dispatchers)
else
- rpc = lsp.rpc.start(config_cmd, dispatchers, {
+ self.rpc = lsp.rpc.start(config_cmd, dispatchers, {
cwd = config.cmd_cwd,
env = config.cmd_env,
detached = config.detached,
})
end
- -- Return nil if the rpc client fails to start
- if not rpc then
- return
- end
-
- self.rpc = rpc
-
setmetatable(self, Client)
return self
diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua
index 37b330f5f6..3d8b54ee3d 100644
--- a/runtime/lua/vim/lsp/inlay_hint.lua
+++ b/runtime/lua/vim/lsp/inlay_hint.lua
@@ -41,13 +41,13 @@ function M.on_inlayhint(err, result, ctx, _)
bufstate.client_hints = vim.defaulttable()
bufstate.version = ctx.version
end
- local hints_by_client = bufstate.client_hints
+ local client_hints = bufstate.client_hints
local client = assert(vim.lsp.get_client_by_id(client_id))
- local new_hints_by_lnum = vim.defaulttable()
+ local new_lnum_hints = vim.defaulttable()
local num_unprocessed = #result
if num_unprocessed == 0 then
- hints_by_client[client_id] = {}
+ client_hints[client_id] = {}
bufstate.version = ctx.version
api.nvim__buf_redraw_range(bufnr, 0, -1)
return
@@ -73,10 +73,10 @@ function M.on_inlayhint(err, result, ctx, _)
for _, hint in ipairs(result) do
local lnum = hint.position.line
hint.position.character = pos_to_byte(hint.position)
- table.insert(new_hints_by_lnum[lnum], hint)
+ table.insert(new_lnum_hints[lnum], hint)
end
- hints_by_client[client_id] = new_hints_by_lnum
+ client_hints[client_id] = new_lnum_hints
bufstate.version = ctx.version
api.nvim__buf_redraw_range(bufnr, 0, -1)
end
@@ -175,19 +175,19 @@ function M.get(filter)
end
--- @type vim.lsp.inlay_hint.get.ret[]
- local hints = {}
+ local result = {}
for _, client in pairs(clients) do
- local hints_by_lnum = bufstate.client_hints[client.id]
- if hints_by_lnum then
+ local lnum_hints = bufstate.client_hints[client.id]
+ if lnum_hints then
for lnum = range.start.line, range['end'].line do
- local line_hints = hints_by_lnum[lnum] or {}
- for _, hint in pairs(line_hints) do
+ local hints = lnum_hints[lnum] or {}
+ for _, hint in pairs(hints) do
local line, char = hint.position.line, hint.position.character
if
(line > range.start.line or char >= range.start.character)
and (line < range['end'].line or char <= range['end'].character)
then
- table.insert(hints, {
+ table.insert(result, {
bufnr = bufnr,
client_id = client.id,
inlay_hint = hint,
@@ -197,7 +197,7 @@ function M.get(filter)
end
end
end
- return hints
+ return result
end
--- Clear inlay hints
@@ -315,14 +315,14 @@ api.nvim_set_decoration_provider(namespace, {
if not bufstate.client_hints then
return
end
- local hints_by_client = assert(bufstate.client_hints)
+ local client_hints = assert(bufstate.client_hints)
for lnum = topline, botline do
if bufstate.applied[lnum] ~= bufstate.version then
api.nvim_buf_clear_namespace(bufnr, namespace, lnum, lnum + 1)
- for _, hints_by_lnum in pairs(hints_by_client) do
- local line_hints = hints_by_lnum[lnum] or {}
- for _, hint in pairs(line_hints) do
+ for _, lnum_hints in pairs(client_hints) do
+ local hints = lnum_hints[lnum] or {}
+ for _, hint in pairs(hints) do
local text = ''
local label = hint.label
if type(label) == 'string' then
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 6748b32ec0..3c63a12da2 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -645,9 +645,23 @@ function M.connect(host_or_path, port)
or assert(uv.new_tcp(), 'Could not create new TCP socket')
)
local closing = false
+ -- Connect returns a PublicClient synchronously so the caller
+ -- can immediately send messages before the connection is established
+ -- -> Need to buffer them until that happens
+ local connected = false
+ -- size should be enough because the client can't really do anything until initialization is done
+ -- which required a response from the server - implying the connection got established
+ local msgbuf = vim.ringbuf(10)
local transport = {
write = function(msg)
- handle:write(msg)
+ if connected then
+ local _, err = handle:write(msg)
+ if err and not closing then
+ log.error('Error on handle:write: %q', err)
+ end
+ else
+ msgbuf:push(msg)
+ end
end,
is_closing = function()
return closing
@@ -679,6 +693,10 @@ function M.connect(host_or_path, port)
handle:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err)
client:on_error(M.client_errors.READ_ERROR, read_err)
end))
+ connected = true
+ for msg in msgbuf do
+ handle:write(msg)
+ end
end
if port == nil then
handle:connect(host_or_path, on_connect)
@@ -704,7 +722,7 @@ end
--- @param cmd string[] Command to start the LSP server.
--- @param dispatchers? vim.lsp.rpc.Dispatchers
--- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams
---- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods:
+--- @return vim.lsp.rpc.PublicClient : Client RPC object, with these methods:
--- - `notify()` |vim.lsp.rpc.notify()|
--- - `request()` |vim.lsp.rpc.request()|
--- - `is_closing()` returns a boolean indicating if the RPC is closing.
@@ -779,8 +797,7 @@ function M.start(cmd, dispatchers, extra_spawn_params)
end
local msg =
string.format('Spawning language server with cmd: `%s` failed%s', vim.inspect(cmd), sfx)
- vim.notify(msg, vim.log.levels.WARN)
- return nil
+ error(msg)
end
sysobj = sysobj_or_err --[[@as vim.SystemObj]]