mirror of
https://github.com/neovim/neovim.git
synced 2025-10-09 11:26:37 +00:00
lua LSP client: initial implementation (#11336)
Mainly configuration and RPC infrastructure can be considered "done". Specific requests and their callbacks will be improved later (and also served by plugins). There are also some TODO:s for the client itself, like incremental updates. Co-authored by at-tjdevries and at-h-michael, with many review/suggestion contributions.
This commit is contained in:

committed by
Björn Linse

parent
db436d5277
commit
00dc12c5d8
634
test/functional/plugin/lsp/lsp_spec.lua
Normal file
634
test/functional/plugin/lsp/lsp_spec.lua
Normal file
@@ -0,0 +1,634 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
|
||||
local clear = helpers.clear
|
||||
local exec_lua = helpers.exec_lua
|
||||
local eq = helpers.eq
|
||||
local NIL = helpers.NIL
|
||||
|
||||
-- Use these to get access to a coroutine so that I can run async tests and use
|
||||
-- yield.
|
||||
local run, stop = helpers.run, helpers.stop
|
||||
|
||||
if helpers.pending_win32(pending) then return end
|
||||
|
||||
local is_windows = require'luv'.os_uname().sysname == "Windows"
|
||||
local lsp_test_rpc_server_file = "test/functional/fixtures/lsp-test-rpc-server.lua"
|
||||
if is_windows then
|
||||
lsp_test_rpc_server_file = lsp_test_rpc_server_file:gsub("/", "\\")
|
||||
end
|
||||
|
||||
local function test_rpc_server_setup(test_name, timeout_ms)
|
||||
exec_lua([=[
|
||||
lsp = require('vim.lsp')
|
||||
local test_name, fixture_filename, timeout = ...
|
||||
TEST_RPC_CLIENT_ID = lsp.start_client {
|
||||
cmd = {
|
||||
vim.api.nvim_get_vvar("progpath"), '-Es', '-u', 'NONE', '--headless',
|
||||
"-c", string.format("lua TEST_NAME = %q", test_name),
|
||||
"-c", string.format("lua TIMEOUT = %d", timeout),
|
||||
"-c", "luafile "..fixture_filename,
|
||||
};
|
||||
callbacks = setmetatable({}, {
|
||||
__index = function(t, method)
|
||||
return function(...)
|
||||
return vim.rpcrequest(1, 'callback', ...)
|
||||
end
|
||||
end;
|
||||
});
|
||||
root_dir = vim.loop.cwd();
|
||||
on_init = function(client, result)
|
||||
TEST_RPC_CLIENT = client
|
||||
vim.rpcrequest(1, "init", result)
|
||||
end;
|
||||
on_exit = function(...)
|
||||
vim.rpcnotify(1, "exit", ...)
|
||||
end;
|
||||
}
|
||||
]=], test_name, lsp_test_rpc_server_file, timeout_ms or 1e3)
|
||||
end
|
||||
|
||||
local function test_rpc_server(config)
|
||||
if config.test_name then
|
||||
clear()
|
||||
test_rpc_server_setup(config.test_name, config.timeout_ms or 1e3)
|
||||
end
|
||||
local client = setmetatable({}, {
|
||||
__index = function(_, name)
|
||||
-- Workaround for not being able to yield() inside __index for Lua 5.1 :(
|
||||
-- Otherwise I would just return the value here.
|
||||
return function(...)
|
||||
return exec_lua([=[
|
||||
local name = ...
|
||||
if type(TEST_RPC_CLIENT[name]) == 'function' then
|
||||
return TEST_RPC_CLIENT[name](select(2, ...))
|
||||
else
|
||||
return TEST_RPC_CLIENT[name]
|
||||
end
|
||||
]=], name, ...)
|
||||
end
|
||||
end;
|
||||
})
|
||||
local code, signal
|
||||
local function on_request(method, args)
|
||||
if method == "init" then
|
||||
if config.on_init then
|
||||
config.on_init(client, unpack(args))
|
||||
end
|
||||
return NIL
|
||||
end
|
||||
if method == 'callback' then
|
||||
if config.on_callback then
|
||||
config.on_callback(unpack(args))
|
||||
end
|
||||
end
|
||||
return NIL
|
||||
end
|
||||
local function on_notify(method, args)
|
||||
if method == 'exit' then
|
||||
code, signal = unpack(args)
|
||||
return stop()
|
||||
end
|
||||
end
|
||||
-- TODO specify timeout?
|
||||
-- run(on_request, on_notify, config.on_setup, 1000)
|
||||
run(on_request, on_notify, config.on_setup)
|
||||
if config.on_exit then
|
||||
config.on_exit(code, signal)
|
||||
end
|
||||
stop()
|
||||
if config.test_name then
|
||||
exec_lua("lsp._vim_exit_handler()")
|
||||
end
|
||||
end
|
||||
|
||||
describe('Language Client API', function()
|
||||
describe('server_name is specified', function()
|
||||
before_each(function()
|
||||
clear()
|
||||
-- Run an instance of nvim on the file which contains our "scripts".
|
||||
-- Pass TEST_NAME to pick the script.
|
||||
local test_name = "basic_init"
|
||||
exec_lua([=[
|
||||
lsp = require('vim.lsp')
|
||||
local test_name, fixture_filename = ...
|
||||
TEST_RPC_CLIENT_ID = lsp.start_client {
|
||||
cmd = {
|
||||
vim.api.nvim_get_vvar("progpath"), '-Es', '-u', 'NONE', '--headless',
|
||||
"-c", string.format("lua TEST_NAME = %q", test_name),
|
||||
"-c", "luafile "..fixture_filename;
|
||||
};
|
||||
root_dir = vim.loop.cwd();
|
||||
}
|
||||
]=], test_name, lsp_test_rpc_server_file)
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
exec_lua("lsp._vim_exit_handler()")
|
||||
-- exec_lua("lsp.stop_all_clients(true)")
|
||||
end)
|
||||
|
||||
describe('start_client and stop_client', function()
|
||||
it('should return true', function()
|
||||
for _ = 1, 20 do
|
||||
helpers.sleep(10)
|
||||
if exec_lua("return #lsp.get_active_clients()") > 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
eq(1, exec_lua("return #lsp.get_active_clients()"))
|
||||
eq(false, exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID) == nil"))
|
||||
eq(false, exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID).is_stopped()"))
|
||||
exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID).stop()")
|
||||
eq(false, exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID).is_stopped()"))
|
||||
for _ = 1, 20 do
|
||||
helpers.sleep(10)
|
||||
if exec_lua("return #lsp.get_active_clients()") == 0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
eq(true, exec_lua("return lsp.get_client_by_id(TEST_RPC_CLIENT_ID) == nil"))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('basic_init test', function()
|
||||
it('should run correctly', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "test", {}, 1};
|
||||
}
|
||||
test_rpc_server {
|
||||
test_name = "basic_init";
|
||||
on_init = function(client, _init_result)
|
||||
-- client is a dummy object which will queue up commands to be run
|
||||
-- once the server initializes. It can't accept lua callbacks or
|
||||
-- other types that may be unserializable for now.
|
||||
client.stop()
|
||||
end;
|
||||
-- If the program timed out, then code will be nil.
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code") eq(0, signal, "exit signal")
|
||||
end;
|
||||
-- Note that NIL must be used here.
|
||||
-- on_callback(err, method, result, client_id)
|
||||
on_callback = function(...)
|
||||
eq(table.remove(expected_callbacks), {...})
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should fail', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "test", {}, 1};
|
||||
}
|
||||
test_rpc_server {
|
||||
test_name = "basic_init";
|
||||
on_init = function(client)
|
||||
client.notify('test')
|
||||
client.stop()
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(1, code, "exit code") eq(0, signal, "exit signal")
|
||||
end;
|
||||
on_callback = function(...)
|
||||
eq(table.remove(expected_callbacks), {...}, "expected callback")
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should succeed with manual shutdown', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "test", {}, 1};
|
||||
}
|
||||
test_rpc_server {
|
||||
test_name = "basic_init";
|
||||
on_init = function(client)
|
||||
eq(0, client.resolved_capabilities().text_document_did_change)
|
||||
client.request('shutdown')
|
||||
client.notify('exit')
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code") eq(0, signal, "exit signal")
|
||||
end;
|
||||
on_callback = function(...)
|
||||
eq(table.remove(expected_callbacks), {...}, "expected callback")
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should verify capabilities sent', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
}
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_capabilities";
|
||||
on_init = function(client)
|
||||
client.stop()
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code") eq(0, signal, "exit signal")
|
||||
end;
|
||||
on_callback = function(...)
|
||||
eq(table.remove(expected_callbacks), {...}, "expected callback")
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should not send didOpen if the buffer closes before init', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_finish";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
eq(1, exec_lua("return TEST_RPC_CLIENT_ID"))
|
||||
eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
|
||||
exec_lua [[
|
||||
vim.api.nvim_command(BUFFER.."bwipeout")
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
|
||||
eq(full_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
client.notify('finish')
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code") eq(0, signal, "exit signal")
|
||||
end;
|
||||
on_callback = function(err, method, params, client_id)
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should check the body sent attaching before init', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_buffer_open";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
exec_lua [[
|
||||
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
|
||||
eq(full_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
exec_lua [[
|
||||
assert(not lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID), "Shouldn't attach twice")
|
||||
]]
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code") eq(0, signal, "exit signal")
|
||||
end;
|
||||
on_callback = function(err, method, params, client_id)
|
||||
if method == 'start' then
|
||||
client.notify('finish')
|
||||
end
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should check the body sent attaching after init', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_buffer_open";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
|
||||
eq(full_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
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_callback = function(err, method, params, client_id)
|
||||
if method == 'start' then
|
||||
client.notify('finish')
|
||||
end
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should check the body and didChange full', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_buffer_open_and_change";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
|
||||
eq(full_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
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_callback = function(err, method, params, client_id)
|
||||
if method == 'start' then
|
||||
exec_lua [[
|
||||
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
|
||||
"boop";
|
||||
})
|
||||
]]
|
||||
client.notify('finish')
|
||||
end
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
-- TODO(askhan) we don't support full for now, so we can disable these tests.
|
||||
pending('should check the body and didChange incremental', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_buffer_open_and_change_incremental";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
|
||||
eq(sync_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
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_callback = function(err, method, params, client_id)
|
||||
if method == 'start' then
|
||||
exec_lua [[
|
||||
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
|
||||
"boop";
|
||||
})
|
||||
]]
|
||||
client.notify('finish')
|
||||
end
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
-- TODO(askhan) we don't support full for now, so we can disable these tests.
|
||||
pending('should check the body and didChange incremental normal mode editting', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_buffer_open_and_change_incremental_editting";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
|
||||
eq(sync_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
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_callback = function(err, method, params, client_id)
|
||||
if method == 'start' then
|
||||
helpers.command("normal! 1Go")
|
||||
client.notify('finish')
|
||||
end
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should check the body and didChange full with 2 changes', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_buffer_open_and_change_multi";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
|
||||
eq(sync_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
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_callback = function(err, method, params, client_id)
|
||||
if method == 'start' then
|
||||
exec_lua [[
|
||||
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
|
||||
"321";
|
||||
})
|
||||
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
|
||||
"boop";
|
||||
})
|
||||
]]
|
||||
client.notify('finish')
|
||||
end
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
it('should check the body and didChange full lifecycle', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "basic_check_buffer_open_and_change_multi_and_close";
|
||||
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";
|
||||
})
|
||||
]]
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
|
||||
eq(sync_kind, client.resolved_capabilities().text_document_did_change)
|
||||
eq(true, client.resolved_capabilities().text_document_open_close)
|
||||
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_callback = function(err, method, params, client_id)
|
||||
if method == 'start' then
|
||||
exec_lua [[
|
||||
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
|
||||
"321";
|
||||
})
|
||||
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
|
||||
"boop";
|
||||
})
|
||||
vim.api.nvim_command(BUFFER.."bwipeout")
|
||||
]]
|
||||
client.notify('finish')
|
||||
end
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
if method == 'finish' then
|
||||
client.stop()
|
||||
end
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
end)
|
||||
|
||||
describe("parsing tests", function()
|
||||
it('should handle invalid content-length correctly', function()
|
||||
local expected_callbacks = {
|
||||
{NIL, "shutdown", {}, 1};
|
||||
{NIL, "finish", {}, 1};
|
||||
{NIL, "start", {}, 1};
|
||||
}
|
||||
local client
|
||||
test_rpc_server {
|
||||
test_name = "invalid_header";
|
||||
on_setup = function()
|
||||
end;
|
||||
on_init = function(_client)
|
||||
client = _client
|
||||
client.stop(true)
|
||||
end;
|
||||
on_exit = function(code, signal)
|
||||
eq(0, code, "exit code") eq(0, signal, "exit signal")
|
||||
end;
|
||||
on_callback = function(err, method, params, client_id)
|
||||
eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback")
|
||||
end;
|
||||
}
|
||||
end)
|
||||
|
||||
end)
|
||||
end)
|
Reference in New Issue
Block a user