fix(lsp): handle absence of a trailing newline #25194

Fixes #24339

rust-analyzer sends "Invalid offset" error in such cases. Some other
servers handle it specially.

LSP spec mentions that "A range is comparable to a selection in an
editor". Most editors don't handle trailing newlines the same way
Neovim/Vim does, it's clearly visible if it's present or not. With that
in mind it's understandable why sending end position as simply the start
of the line after the last one is considered invalid in such cases.
This commit is contained in:
Sergey Slipchenko
2023-09-21 14:06:40 +04:00
committed by GitHub
parent 8bd6f7c20b
commit 345bd91db2
3 changed files with 127 additions and 16 deletions

View File

@@ -1244,6 +1244,67 @@ describe('LSP', function()
}
end)
it('should send correct range for inlay hints with noeol', function()
local expected_handlers = {
{NIL, {}, {method="shutdown", client_id=1}};
{NIL, {}, {method="finish", client_id=1}};
{NIL, {}, {
method="textDocument/inlayHint",
params = {
textDocument = {
uri = 'file://',
},
range = {
start = { line = 0, character = 0 },
['end'] = { line = 1, character = 3 },
}
},
bufnr=2,
client_id=1,
}};
{NIL, {}, {method="start", client_id=1}};
}
local client
test_rpc_server {
test_name = "inlay_hint";
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_lines(BUFFER, 0, -1, false, {
"testing";
"123";
})
vim.bo[BUFFER].eol = false
]]
end;
on_init = function(_client)
client = _client
eq(true, client.supports_method('textDocument/inlayHint'))
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
end;
on_exit = function(code, signal)
eq(0, code, "exit code")
eq(0, signal, "exit signal")
end;
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
vim.lsp.inlay_hint(BUFFER, true)
]]
end
if ctx.method == 'textDocument/inlayHint' then
client.notify('finish')
end
eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
if ctx.method == 'finish' then
client.stop()
end
end;
}
end)
it('should check the body and didChange incremental', function()
local expected_handlers = {
{NIL, {}, {method="shutdown", client_id=1}};