2024-04-20 08:44:13 -07:00
|
|
|
|
local t = require('test.testutil')
|
|
|
|
|
local n = require('test.functional.testnvim')()
|
|
|
|
|
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local t_lsp = require('test.functional.plugin.lsp.testutil')
|
|
|
|
|
|
|
|
|
|
local assert_log = t.assert_log
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local buf_lines = n.buf_lines
|
|
|
|
|
local clear = n.clear
|
|
|
|
|
local command = n.command
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local dedent = t.dedent
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local exec_lua = n.exec_lua
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local eq = t.eq
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local eval = n.eval
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local matches = t.matches
|
|
|
|
|
local pcall_err = t.pcall_err
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local pesc = vim.pesc
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local insert = n.insert
|
|
|
|
|
local fn = n.fn
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local retry = t.retry
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local stop = n.stop
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local NIL = vim.NIL
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local read_file = t.read_file
|
|
|
|
|
local write_file = t.write_file
|
|
|
|
|
local is_ci = t.is_ci
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local api = n.api
|
2024-04-08 02:03:20 -07:00
|
|
|
|
local is_os = t.is_os
|
|
|
|
|
local skip = t.skip
|
|
|
|
|
local mkdir = t.mkdir
|
|
|
|
|
local tmpname = t.tmpname
|
|
|
|
|
|
|
|
|
|
local clear_notrace = t_lsp.clear_notrace
|
|
|
|
|
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
|
2024-09-03 08:10:39 -07:00
|
|
|
|
local create_tcp_echo_server = t_lsp.create_tcp_echo_server
|
2019-11-13 13:55:26 -07:00
|
|
|
|
|
2023-03-09 07:12:56 -07:00
|
|
|
|
local function get_buf_option(name, bufnr)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
return exec_lua(function()
|
|
|
|
|
bufnr = bufnr or _G.BUFFER
|
|
|
|
|
return vim.api.nvim_get_option_value(name, { buf = bufnr })
|
|
|
|
|
end)
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end
|
|
|
|
|
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local function make_edit(y_0, x_0, y_1, x_1, text)
|
|
|
|
|
return {
|
|
|
|
|
range = {
|
|
|
|
|
start = { line = y_0, character = x_0 },
|
|
|
|
|
['end'] = { line = y_1, character = x_1 },
|
|
|
|
|
},
|
|
|
|
|
newText = type(text) == 'table' and table.concat(text, '\n') or (text or ''),
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--- @param edits [integer, integer, integer, integer, string|string[]][]
|
|
|
|
|
--- @param encoding? string
|
|
|
|
|
local function apply_text_edits(edits, encoding)
|
|
|
|
|
local edits1 = vim.tbl_map(
|
|
|
|
|
--- @param edit [integer, integer, integer, integer, string|string[]]
|
|
|
|
|
function(edit)
|
|
|
|
|
return make_edit(unpack(edit))
|
|
|
|
|
end,
|
|
|
|
|
edits
|
|
|
|
|
)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.util.apply_text_edits(edits1, 1, encoding or 'utf-16')
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
end
|
|
|
|
|
|
2020-02-08 19:08:02 -07:00
|
|
|
|
-- TODO(justinmk): hangs on Windows https://github.com/neovim/neovim/pull/11837
|
2022-11-21 17:13:30 -07:00
|
|
|
|
if skip(is_os('win')) then
|
|
|
|
|
return
|
|
|
|
|
end
|
2019-11-13 13:55:26 -07:00
|
|
|
|
|
2019-12-31 08:51:54 -07:00
|
|
|
|
describe('LSP', function()
|
2021-09-26 14:21:40 -07:00
|
|
|
|
before_each(function()
|
|
|
|
|
clear_notrace()
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
|
2021-09-26 14:21:40 -07:00
|
|
|
|
after_each(function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
stop()
|
|
|
|
|
exec_lua('lsp.stop_client(lsp.get_clients(), true)')
|
2024-04-02 06:45:19 -07:00
|
|
|
|
api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
teardown(function()
|
|
|
|
|
os.remove(fake_lsp_logfile)
|
2021-09-26 14:21:40 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
describe('server_name specified', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
before_each(function()
|
|
|
|
|
-- Run an instance of nvim on the file which contains our "scripts".
|
|
|
|
|
-- Pass TEST_NAME to pick the script.
|
|
|
|
|
local test_name = 'basic_init'
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
_G.lsp = require('vim.lsp')
|
|
|
|
|
function _G.test__start_client()
|
2024-12-04 06:14:47 -07:00
|
|
|
|
return vim.lsp.start({
|
2024-08-11 03:58:15 -07:00
|
|
|
|
cmd_env = {
|
2024-08-11 01:27:48 -07:00
|
|
|
|
NVIM_LOG_FILE = fake_lsp_logfile,
|
2024-08-11 03:58:15 -07:00
|
|
|
|
NVIM_APPNAME = 'nvim_lsp_test',
|
|
|
|
|
},
|
|
|
|
|
cmd = {
|
|
|
|
|
vim.v.progpath,
|
|
|
|
|
'-l',
|
2024-08-11 01:27:48 -07:00
|
|
|
|
fake_lsp_code,
|
|
|
|
|
test_name,
|
2024-08-11 03:58:15 -07:00
|
|
|
|
},
|
|
|
|
|
workspace_folders = {
|
|
|
|
|
{
|
|
|
|
|
uri = 'file://' .. vim.uv.cwd(),
|
|
|
|
|
name = 'test_folder',
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-12-04 06:14:47 -07:00
|
|
|
|
}, { attach = false })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
end
|
|
|
|
|
_G.TEST_CLIENT1 = _G.test__start_client()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2019-12-31 08:51:54 -07:00
|
|
|
|
it('start_client(), stop_client()', function()
|
|
|
|
|
retry(nil, 4000, function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
1,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return #vim.lsp.get_clients()
|
|
|
|
|
end)
|
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
end)
|
|
|
|
|
eq(
|
|
|
|
|
2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.TEST_CLIENT2 = _G.test__start_client()
|
|
|
|
|
return _G.TEST_CLIENT2
|
|
|
|
|
end)
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
eq(
|
|
|
|
|
3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.TEST_CLIENT3 = _G.test__start_client()
|
|
|
|
|
return _G.TEST_CLIENT3
|
|
|
|
|
end)
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
retry(nil, 4000, function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
3,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return #vim.lsp.get_clients()
|
|
|
|
|
end)
|
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
false,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.get_client_by_id(_G.TEST_CLIENT1) == nil
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
eq(
|
|
|
|
|
false,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.get_client_by_id(_G.TEST_CLIENT1).is_stopped()
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.get_client_by_id(_G.TEST_CLIENT1).stop()
|
|
|
|
|
end)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
retry(nil, 4000, function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
2,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return #vim.lsp.get_clients()
|
|
|
|
|
end)
|
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
true,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.get_client_by_id(_G.TEST_CLIENT1) == nil
|
|
|
|
|
end)
|
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.stop_client({ _G.TEST_CLIENT2, _G.TEST_CLIENT3 })
|
|
|
|
|
end)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
retry(nil, 4000, function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
0,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return #vim.lsp.get_clients()
|
|
|
|
|
end)
|
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('stop_client() also works on client objects', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.TEST_CLIENT2 = _G.test__start_client()
|
|
|
|
|
_G.TEST_CLIENT3 = _G.test__start_client()
|
|
|
|
|
end)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
retry(nil, 4000, function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
3,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return #vim.lsp.get_clients()
|
|
|
|
|
end)
|
|
|
|
|
)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
end)
|
|
|
|
|
-- Stop all clients.
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.stop_client(vim.lsp.get_clients())
|
|
|
|
|
end)
|
2019-12-31 08:51:54 -07:00
|
|
|
|
retry(nil, 4000, function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
0,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return #vim.lsp.get_clients()
|
|
|
|
|
end)
|
|
|
|
|
)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2022-05-22 05:06:21 -07:00
|
|
|
|
|
2019-11-13 13:55:26 -07:00
|
|
|
|
describe('basic_init test', function()
|
|
|
|
|
it('should run correctly', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'test', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_init',
|
2021-02-22 16:02:51 -07:00
|
|
|
|
on_init = function(client, _)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
-- 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.
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
-- If the program timed out, then code will be nil.
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
-- Note that NIL must be used here.
|
2021-06-22 01:35:36 -07:00
|
|
|
|
-- on_handler(err, method, result, client_id)
|
|
|
|
|
on_handler = function(...)
|
|
|
|
|
eq(table.remove(expected_handlers), { ... })
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should fail', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'test', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_init',
|
|
|
|
|
on_init = function(client)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('test')
|
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(101, code, 'exit code') -- See fake-lsp-server.lua
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2020-02-16 20:02:09 -07:00
|
|
|
|
assert_log(
|
|
|
|
|
pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]),
|
|
|
|
|
fake_lsp_logfile
|
|
|
|
|
)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
2021-06-22 01:35:36 -07:00
|
|
|
|
on_handler = function(...)
|
2021-06-28 14:02:17 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { ... }, 'expected handler')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2022-06-03 09:16:11 -07:00
|
|
|
|
it('should send didChangeConfiguration after initialize if there are settings', function()
|
|
|
|
|
test_rpc_server({
|
|
|
|
|
test_name = 'basic_init_did_change_configuration',
|
|
|
|
|
on_init = function(client, _)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-06-03 09:16:11 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2024-02-07 04:24:44 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2022-06-03 09:16:11 -07:00
|
|
|
|
end,
|
|
|
|
|
settings = {
|
|
|
|
|
dummy = 1,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
2023-06-01 09:15:33 -07:00
|
|
|
|
it(
|
|
|
|
|
"should set the client's offset_encoding when positionEncoding capability is supported",
|
|
|
|
|
function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
capabilities = {
|
|
|
|
|
positionEncoding = 'utf-8',
|
|
|
|
|
},
|
|
|
|
|
})
|
2023-06-01 09:15:33 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local client_id = vim.lsp.start({
|
|
|
|
|
name = 'dummy',
|
|
|
|
|
cmd = server.cmd,
|
|
|
|
|
})
|
2023-06-01 09:15:33 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
if not client_id then
|
|
|
|
|
return 'vim.lsp.start did not return client_id'
|
|
|
|
|
end
|
2023-06-01 09:15:33 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local client = vim.lsp.get_client_by_id(client_id)
|
|
|
|
|
if not client then
|
|
|
|
|
return 'No client found with id ' .. client_id
|
|
|
|
|
end
|
|
|
|
|
return client.offset_encoding
|
|
|
|
|
end)
|
2023-06-01 09:15:33 -07:00
|
|
|
|
eq('utf-8', result)
|
|
|
|
|
end
|
|
|
|
|
)
|
|
|
|
|
|
2019-11-13 13:55:26 -07:00
|
|
|
|
it('should succeed with manual shutdown', function()
|
2022-11-21 17:13:30 -07:00
|
|
|
|
if is_ci() then
|
2021-07-23 09:33:07 -07:00
|
|
|
|
pending('hangs the build on CI #14028, re-enable with freeze timeout #14204')
|
2021-04-03 01:04:14 -07:00
|
|
|
|
return
|
2024-04-08 02:03:20 -07:00
|
|
|
|
elseif t.skip_fragile(pending) then
|
2021-08-13 20:53:55 -07:00
|
|
|
|
return
|
2021-04-03 01:04:14 -07:00
|
|
|
|
end
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
2024-06-14 02:03:58 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1, version = 0 } },
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'test', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_init',
|
|
|
|
|
on_init = function(client)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(0, client.server_capabilities().textDocumentSync.change)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:request('shutdown')
|
|
|
|
|
client:notify('exit')
|
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
2021-06-22 01:35:36 -07:00
|
|
|
|
on_handler = function(...)
|
2021-06-28 14:02:17 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { ... }, 'expected handler')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2021-12-21 11:53:34 -07:00
|
|
|
|
it('should detach buffer in response to nvim_buf_detach', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-12-21 11:53:34 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_finish',
|
2024-03-21 08:15:20 -07:00
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
true,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
eq(
|
|
|
|
|
true,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.buf_is_attached(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
|
|
|
|
)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.cmd(_G.BUFFER .. 'bwipeout')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-03-21 08:15:20 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2021-12-21 11:53:34 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-12-21 11:53:34 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.buf_detach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
|
|
|
|
eq(
|
|
|
|
|
false,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.buf_is_attached(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
|
|
|
|
)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-12-21 11:53:34 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2022-05-09 11:00:27 -07:00
|
|
|
|
it('should fire autocommands on attach and detach', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-05-09 11:00:27 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_init',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
2022-05-09 11:00:27 -07:00
|
|
|
|
vim.api.nvim_create_autocmd('LspAttach', {
|
|
|
|
|
callback = function(args)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client0 = assert(vim.lsp.get_client_by_id(args.data.client_id))
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.g.lsp_attached = client0.name
|
2022-05-09 11:00:27 -07:00
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
vim.api.nvim_create_autocmd('LspDetach', {
|
|
|
|
|
callback = function(args)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client0 = assert(vim.lsp.get_client_by_id(args.data.client_id))
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.g.lsp_detached = client0.name
|
2022-05-09 11:00:27 -07:00
|
|
|
|
end,
|
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-05-09 11:00:27 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
true,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
|
|
|
|
)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2022-05-09 11:00:27 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq('basic_init', api.nvim_get_var('lsp_attached'))
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.buf_detach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
2024-01-12 10:59:57 -07:00
|
|
|
|
eq('basic_init', api.nvim_get_var('lsp_detached'))
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-05-09 11:00:27 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2023-03-09 07:12:56 -07:00
|
|
|
|
it('should set default options on attach', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2023-03-09 07:12:56 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'set_defaults_all_capabilities',
|
2023-04-11 09:37:27 -07:00
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
if ctx.method == 'test' then
|
|
|
|
|
eq('v:lua.vim.lsp.tagfunc', get_buf_option('tagfunc'))
|
|
|
|
|
eq('v:lua.vim.lsp.omnifunc', get_buf_option('omnifunc'))
|
|
|
|
|
eq('v:lua.vim.lsp.formatexpr()', get_buf_option('formatexpr'))
|
2023-07-14 09:47:18 -07:00
|
|
|
|
eq('', get_buf_option('keywordprg'))
|
|
|
|
|
eq(
|
|
|
|
|
true,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local keymap --- @type table<string,any>
|
2024-11-22 05:51:30 -07:00
|
|
|
|
local called = false
|
|
|
|
|
local origin = vim.lsp.buf.hover
|
|
|
|
|
vim.lsp.buf.hover = function()
|
|
|
|
|
called = true
|
|
|
|
|
end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim._with({ buf = _G.BUFFER }, function()
|
|
|
|
|
keymap = vim.fn.maparg('K', 'n', false, true)
|
|
|
|
|
end)
|
2024-11-22 05:51:30 -07:00
|
|
|
|
keymap.callback()
|
|
|
|
|
vim.lsp.buf.hover = origin
|
|
|
|
|
return called
|
2023-07-14 09:47:18 -07:00
|
|
|
|
end)
|
|
|
|
|
)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(_, _)
|
|
|
|
|
eq('', get_buf_option('tagfunc'))
|
|
|
|
|
eq('', get_buf_option('omnifunc'))
|
|
|
|
|
eq('', get_buf_option('formatexpr'))
|
2023-07-14 09:47:18 -07:00
|
|
|
|
eq(
|
2024-11-22 05:51:30 -07:00
|
|
|
|
true,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local keymap --- @type string
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim._with({ buf = _G.BUFFER }, function()
|
|
|
|
|
keymap = vim.fn.maparg('K', 'n', false, false)
|
|
|
|
|
end)
|
2024-11-22 05:51:30 -07:00
|
|
|
|
return keymap:match('<Lua %d+: .+/runtime/lua/vim/lsp%.lua:%d+>') ~= nil
|
2023-07-14 09:47:18 -07:00
|
|
|
|
end)
|
|
|
|
|
)
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should overwrite options set by ftplugins', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local BUFFER_1 --- @type integer
|
|
|
|
|
local BUFFER_2 --- @type integer
|
2023-03-09 07:12:56 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'set_defaults_all_capabilities',
|
2023-04-11 09:37:27 -07:00
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2023-03-09 07:12:56 -07:00
|
|
|
|
vim.api.nvim_command('filetype plugin on')
|
2024-08-11 01:27:48 -07:00
|
|
|
|
BUFFER_1 = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
BUFFER_2 = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_set_option_value('filetype', 'man', { buf = BUFFER_1 })
|
|
|
|
|
vim.api.nvim_set_option_value('filetype', 'xml', { buf = BUFFER_2 })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2023-04-11 09:37:27 -07:00
|
|
|
|
|
|
|
|
|
-- Sanity check to ensure that some values are set after setting filetype.
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq("v:lua.require'man'.goto_tag", get_buf_option('tagfunc', BUFFER_1))
|
|
|
|
|
eq('xmlcomplete#CompleteTags', get_buf_option('omnifunc', BUFFER_2))
|
|
|
|
|
eq('xmlformat#Format()', get_buf_option('formatexpr', BUFFER_2))
|
2023-04-11 09:37:27 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.buf_attach_client(BUFFER_1, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
vim.lsp.buf_attach_client(BUFFER_2, _G.TEST_RPC_CLIENT_ID)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
if ctx.method == 'test' then
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq('v:lua.vim.lsp.tagfunc', get_buf_option('tagfunc', BUFFER_1))
|
|
|
|
|
eq('v:lua.vim.lsp.omnifunc', get_buf_option('omnifunc', BUFFER_2))
|
|
|
|
|
eq('v:lua.vim.lsp.formatexpr()', get_buf_option('formatexpr', BUFFER_2))
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(_, _)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq('', get_buf_option('tagfunc', BUFFER_1))
|
|
|
|
|
eq('', get_buf_option('omnifunc', BUFFER_2))
|
|
|
|
|
eq('', get_buf_option('formatexpr', BUFFER_2))
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should not overwrite user-defined options', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2023-03-09 07:12:56 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'set_defaults_all_capabilities',
|
2023-04-11 09:37:27 -07:00
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_set_option_value('tagfunc', 'tfu', { buf = _G.BUFFER })
|
|
|
|
|
vim.api.nvim_set_option_value('omnifunc', 'ofu', { buf = _G.BUFFER })
|
|
|
|
|
vim.api.nvim_set_option_value('formatexpr', 'fex', { buf = _G.BUFFER })
|
|
|
|
|
vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
end)
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
if ctx.method == 'test' then
|
|
|
|
|
eq('tfu', get_buf_option('tagfunc'))
|
|
|
|
|
eq('ofu', get_buf_option('omnifunc'))
|
|
|
|
|
eq('fex', get_buf_option('formatexpr'))
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2023-03-09 07:12:56 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(_, _)
|
|
|
|
|
eq('tfu', get_buf_option('tagfunc'))
|
|
|
|
|
eq('ofu', get_buf_option('omnifunc'))
|
|
|
|
|
eq('fex', get_buf_option('formatexpr'))
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2022-09-08 08:09:32 -07:00
|
|
|
|
it('should detach buffer on bufwipe', function()
|
2022-09-12 15:01:35 -07:00
|
|
|
|
clear()
|
2022-12-04 07:39:22 -07:00
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local server = _G._create_server()
|
2022-09-08 08:09:32 -07:00
|
|
|
|
local bufnr = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_set_current_buf(bufnr)
|
2024-05-23 03:03:47 -07:00
|
|
|
|
local detach_called = false
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_create_autocmd('LspDetach', {
|
2024-05-23 03:03:47 -07:00
|
|
|
|
callback = function()
|
|
|
|
|
detach_called = true
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end,
|
2024-05-23 03:03:47 -07:00
|
|
|
|
})
|
2022-12-04 07:39:22 -07:00
|
|
|
|
local client_id = vim.lsp.start({ name = 'detach-dummy', cmd = server.cmd })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
assert(client_id, 'lsp.start must return client_id')
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client = assert(vim.lsp.get_client_by_id(client_id))
|
2022-09-08 08:09:32 -07:00
|
|
|
|
local num_attached_before = vim.tbl_count(client.attached_buffers)
|
|
|
|
|
vim.api.nvim_buf_delete(bufnr, { force = true })
|
|
|
|
|
local num_attached_after = vim.tbl_count(client.attached_buffers)
|
|
|
|
|
return {
|
|
|
|
|
bufnr = bufnr,
|
|
|
|
|
client_id = client_id,
|
|
|
|
|
num_attached_before = num_attached_before,
|
|
|
|
|
num_attached_after = num_attached_after,
|
2024-05-23 03:03:47 -07:00
|
|
|
|
detach_called = detach_called,
|
2022-09-08 08:09:32 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-09-08 08:09:32 -07:00
|
|
|
|
eq(true, result ~= nil, 'exec_lua must return result')
|
|
|
|
|
eq(1, result.num_attached_before)
|
|
|
|
|
eq(0, result.num_attached_after)
|
2024-05-23 03:03:47 -07:00
|
|
|
|
eq(true, result.detach_called)
|
2022-09-08 08:09:32 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2024-05-23 06:17:53 -07:00
|
|
|
|
it('should not re-attach buffer if it was deleted in on_init #28575', function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
2024-05-23 06:17:53 -07:00
|
|
|
|
handlers = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
initialize = function(_, _, callback)
|
2024-05-23 06:17:53 -07:00
|
|
|
|
vim.schedule(function()
|
|
|
|
|
callback(nil, { capabilities = {} })
|
|
|
|
|
end)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end,
|
|
|
|
|
},
|
2024-05-23 06:17:53 -07:00
|
|
|
|
})
|
|
|
|
|
local bufnr = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
local on_init_called = false
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2024-05-23 06:17:53 -07:00
|
|
|
|
name = 'detach-dummy',
|
|
|
|
|
cmd = server.cmd,
|
|
|
|
|
on_init = function()
|
|
|
|
|
vim.api.nvim_buf_delete(bufnr, {})
|
|
|
|
|
on_init_called = true
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end,
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2024-05-23 06:17:53 -07:00
|
|
|
|
vim.lsp.buf_attach_client(bufnr, client_id)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local ok = vim.wait(1000, function()
|
|
|
|
|
return on_init_called
|
|
|
|
|
end)
|
|
|
|
|
assert(ok, 'on_init was not called')
|
|
|
|
|
end)
|
2024-05-23 06:17:53 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2024-05-27 08:06:03 -07:00
|
|
|
|
it('should allow on_lines + nvim_buf_delete during LSP initialization #28575', function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2024-05-27 08:06:03 -07:00
|
|
|
|
local initialized = false
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server({
|
2024-05-27 08:06:03 -07:00
|
|
|
|
handlers = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
initialize = function(_, _, callback)
|
2024-05-27 08:06:03 -07:00
|
|
|
|
vim.schedule(function()
|
|
|
|
|
callback(nil, { capabilities = {} })
|
|
|
|
|
initialized = true
|
|
|
|
|
end)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end,
|
|
|
|
|
},
|
2024-05-27 08:06:03 -07:00
|
|
|
|
})
|
|
|
|
|
local bufnr = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_set_current_buf(bufnr)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.start({
|
2024-05-27 08:06:03 -07:00
|
|
|
|
name = 'detach-dummy',
|
|
|
|
|
cmd = server.cmd,
|
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { 'hello' })
|
2024-05-27 08:06:03 -07:00
|
|
|
|
vim.api.nvim_buf_delete(bufnr, {})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local ok = vim.wait(1000, function()
|
|
|
|
|
return initialized
|
|
|
|
|
end)
|
|
|
|
|
assert(ok, 'lsp did not initialize')
|
|
|
|
|
end)
|
2024-05-27 08:06:03 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-12-31 06:41:43 -07:00
|
|
|
|
it('client should return settings via workspace/configuration handler', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{
|
|
|
|
|
NIL,
|
|
|
|
|
{
|
|
|
|
|
items = {
|
2020-12-31 06:41:43 -07:00
|
|
|
|
{ section = 'testSetting1' },
|
|
|
|
|
{ section = 'testSetting2' },
|
2022-04-15 02:12:41 -07:00
|
|
|
|
{ section = 'test.Setting3' },
|
|
|
|
|
{ section = 'test.Setting4' },
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ method = 'workspace/configuration', client_id = 1 },
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2020-12-31 06:41:43 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2020-12-31 06:41:43 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_workspace_configuration',
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2020-12-31 06:41:43 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local client0 = vim.lsp.get_client_by_id(_G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
client0.settings = {
|
|
|
|
|
testSetting1 = true,
|
|
|
|
|
testSetting2 = false,
|
|
|
|
|
test = { Setting3 = 'nested' },
|
|
|
|
|
}
|
|
|
|
|
end)
|
2020-12-31 06:41:43 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
if ctx.method == 'workspace/configuration' then
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local server_result = exec_lua(
|
|
|
|
|
[[
|
|
|
|
|
local method, params = ...
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return require 'vim.lsp.handlers'['workspace/configuration'](
|
|
|
|
|
err,
|
|
|
|
|
params,
|
|
|
|
|
{ method = method, client_id = _G.TEST_RPC_CLIENT_ID }
|
|
|
|
|
)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
]],
|
|
|
|
|
ctx.method,
|
|
|
|
|
result
|
|
|
|
|
)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('workspace/configuration', server_result)
|
2020-12-31 06:41:43 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
if ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2020-12-31 06:41:43 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-01-18 11:33:10 -07:00
|
|
|
|
it(
|
|
|
|
|
'workspace/configuration returns NIL per section if client was started without config.settings',
|
|
|
|
|
function()
|
2022-05-22 05:06:21 -07:00
|
|
|
|
local result = nil
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_init',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
c.stop()
|
|
|
|
|
end,
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
result = exec_lua(function()
|
|
|
|
|
local result0 = {
|
|
|
|
|
items = {
|
|
|
|
|
{ section = 'foo' },
|
|
|
|
|
{ section = 'bar' },
|
|
|
|
|
},
|
2022-05-22 05:06:21 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return vim.lsp.handlers['workspace/configuration'](
|
|
|
|
|
nil,
|
|
|
|
|
result0,
|
|
|
|
|
{ client_id = _G.TEST_RPC_CLIENT_ID }
|
|
|
|
|
)
|
|
|
|
|
end)
|
2022-05-22 05:06:21 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
eq({ NIL, NIL }, result)
|
2021-01-18 11:33:10 -07:00
|
|
|
|
end
|
|
|
|
|
)
|
2020-12-31 06:41:43 -07:00
|
|
|
|
|
2019-11-13 13:55:26 -07:00
|
|
|
|
it('should verify capabilities sent', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_capabilities',
|
|
|
|
|
on_init = function(client)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local full_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(full_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq({ includeText = false }, client.server_capabilities().textDocumentSync.save)
|
|
|
|
|
eq(false, client.server_capabilities().codeLensProvider)
|
2020-10-24 21:28:15 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2020-10-24 21:28:15 -07:00
|
|
|
|
end,
|
2021-06-22 01:35:36 -07:00
|
|
|
|
on_handler = function(...)
|
2021-06-28 14:02:17 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { ... }, 'expected handler')
|
2020-10-24 21:28:15 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2022-07-17 10:13:33 -07:00
|
|
|
|
it('BufWritePost sends didSave with bool textDocumentSync.save', function()
|
2022-04-30 13:13:26 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-04-30 13:13:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'text_document_sync_save_bool',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2022-04-30 13:13:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
vim.api.nvim_exec_autocmds('BufWritePost', { buffer = _G.BUFFER, modeline = false })
|
|
|
|
|
end)
|
2022-04-30 13:13:26 -07:00
|
|
|
|
else
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-04-30 13:13:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2022-12-08 02:55:01 -07:00
|
|
|
|
it('BufWritePre does not send notifications if server lacks willSave capabilities', function()
|
2022-12-08 04:22:40 -07:00
|
|
|
|
clear()
|
2022-12-08 02:55:01 -07:00
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local messages = exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
2022-12-08 02:55:01 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
textDocumentSync = {
|
|
|
|
|
willSave = false,
|
|
|
|
|
willSaveWaitUntil = false,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2022-12-08 02:55:01 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd }))
|
2022-12-08 02:55:01 -07:00
|
|
|
|
local buf = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.api.nvim_exec_autocmds('BufWritePre', { buffer = buf, modeline = false })
|
|
|
|
|
vim.lsp.stop_client(client_id)
|
|
|
|
|
return server.messages
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-03-11 07:23:14 -07:00
|
|
|
|
eq(4, #messages)
|
|
|
|
|
eq('initialize', messages[1].method)
|
|
|
|
|
eq('initialized', messages[2].method)
|
|
|
|
|
eq('shutdown', messages[3].method)
|
|
|
|
|
eq('exit', messages[4].method)
|
2022-12-08 02:55:01 -07:00
|
|
|
|
end)
|
2022-12-08 04:22:40 -07:00
|
|
|
|
|
2022-12-08 02:55:01 -07:00
|
|
|
|
it('BufWritePre sends willSave / willSaveWaitUntil, applies textEdits', function()
|
2022-12-08 04:22:40 -07:00
|
|
|
|
clear()
|
2022-12-08 02:55:01 -07:00
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
2022-12-08 02:55:01 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
textDocumentSync = {
|
|
|
|
|
willSave = true,
|
|
|
|
|
willSaveWaitUntil = true,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2022-12-08 02:55:01 -07:00
|
|
|
|
},
|
|
|
|
|
handlers = {
|
2024-05-23 06:17:53 -07:00
|
|
|
|
['textDocument/willSaveWaitUntil'] = function(_, _, callback)
|
2022-12-08 02:55:01 -07:00
|
|
|
|
local text_edit = {
|
|
|
|
|
range = {
|
|
|
|
|
start = { line = 0, character = 0 },
|
|
|
|
|
['end'] = { line = 0, character = 0 },
|
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
newText = 'Hello',
|
2022-12-08 02:55:01 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
callback(nil, { text_edit })
|
|
|
|
|
end,
|
2022-12-08 02:55:01 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
local buf = vim.api.nvim_get_current_buf()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd }))
|
2022-12-08 02:55:01 -07:00
|
|
|
|
vim.api.nvim_exec_autocmds('BufWritePre', { buffer = buf, modeline = false })
|
|
|
|
|
vim.lsp.stop_client(client_id)
|
|
|
|
|
return {
|
|
|
|
|
messages = server.messages,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
lines = vim.api.nvim_buf_get_lines(buf, 0, -1, true),
|
2022-12-08 02:55:01 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-12-08 02:55:01 -07:00
|
|
|
|
local messages = result.messages
|
|
|
|
|
eq('textDocument/willSave', messages[3].method)
|
|
|
|
|
eq('textDocument/willSaveWaitUntil', messages[4].method)
|
|
|
|
|
eq({ 'Hello' }, result.lines)
|
|
|
|
|
end)
|
|
|
|
|
|
2022-08-01 13:32:53 -07:00
|
|
|
|
it('saveas sends didOpen if filename changed', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-08-01 13:32:53 -07:00
|
|
|
|
test_rpc_server({
|
|
|
|
|
test_name = 'text_document_save_did_open',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'start' then
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local tmpfile_old = tmpname()
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local tmpfile_new = tmpname(false)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.BUFFER = vim.api.nvim_get_current_buf()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.api.nvim_buf_set_name(_G.BUFFER, tmpfile_old)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, true, { 'help me' })
|
|
|
|
|
vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
vim._with({ buf = _G.BUFFER }, function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.cmd('saveas ' .. tmpfile_new)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2022-08-01 13:32:53 -07:00
|
|
|
|
else
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-08-01 13:32:53 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
|
2022-07-17 10:13:33 -07:00
|
|
|
|
it('BufWritePost sends didSave including text if server capability is set', function()
|
2022-04-30 13:13:26 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-04-30 13:13:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'text_document_sync_save_includeText',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2022-04-30 13:13:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, true, { 'help me' })
|
|
|
|
|
vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
vim.api.nvim_exec_autocmds('BufWritePost', { buffer = _G.BUFFER, modeline = false })
|
|
|
|
|
end)
|
2022-04-30 13:13:26 -07:00
|
|
|
|
else
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-04-30 13:13:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2024-11-14 04:53:20 -07:00
|
|
|
|
it('client:supports_methods() should validate capabilities', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
2020-10-24 21:28:15 -07:00
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'capabilities_for_client_supports_method',
|
|
|
|
|
on_init = function(client)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-04-30 02:22:30 -07:00
|
|
|
|
local expected_sync_capabilities = {
|
|
|
|
|
change = 1,
|
|
|
|
|
openClose = true,
|
|
|
|
|
save = { includeText = false },
|
|
|
|
|
willSave = false,
|
|
|
|
|
willSaveWaitUntil = false,
|
|
|
|
|
}
|
|
|
|
|
eq(expected_sync_capabilities, client.server_capabilities().textDocumentSync)
|
|
|
|
|
eq(true, client.server_capabilities().completionProvider)
|
|
|
|
|
eq(true, client.server_capabilities().hoverProvider)
|
|
|
|
|
eq(false, client.server_capabilities().definitionProvider)
|
|
|
|
|
eq(false, client.server_capabilities().renameProvider)
|
|
|
|
|
eq(true, client.server_capabilities().codeLensProvider.resolveProvider)
|
2020-10-24 21:28:15 -07:00
|
|
|
|
|
|
|
|
|
-- known methods for resolved capabilities
|
2024-11-14 04:53:20 -07:00
|
|
|
|
eq(true, client:supports_method('textDocument/hover'))
|
|
|
|
|
eq(false, client:supports_method('textDocument/definition'))
|
2020-10-24 21:28:15 -07:00
|
|
|
|
|
|
|
|
|
-- unknown methods are assumed to be supported.
|
2024-11-14 04:53:20 -07:00
|
|
|
|
eq(true, client:supports_method('unknown-method'))
|
2020-10-24 21:28:15 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2020-10-24 21:28:15 -07:00
|
|
|
|
end,
|
2021-06-22 01:35:36 -07:00
|
|
|
|
on_handler = function(...)
|
2021-06-28 14:02:17 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { ... }, 'expected handler')
|
2020-10-24 21:28:15 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2021-10-10 22:32:50 -07:00
|
|
|
|
it('should not call unsupported_method when trying to call an unsupported method', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
2020-10-24 21:28:15 -07:00
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'capabilities_for_client_supports_method',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
vim.lsp.handlers['textDocument/typeDefinition'] = function() end
|
|
|
|
|
vim.cmd(_G.BUFFER .. 'bwipeout')
|
|
|
|
|
end)
|
2020-10-24 21:28:15 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(client)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.buf.type_definition()
|
|
|
|
|
end)
|
2020-12-02 23:00:54 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2020-12-02 23:00:54 -07:00
|
|
|
|
end,
|
2021-06-22 01:35:36 -07:00
|
|
|
|
on_handler = function(...)
|
2021-06-28 14:02:17 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { ... }, 'expected handler')
|
2020-12-02 23:00:54 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2021-10-10 22:32:50 -07:00
|
|
|
|
it(
|
|
|
|
|
'should not call unsupported_method when no client and trying to call an unsupported method',
|
|
|
|
|
function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
2020-12-02 23:00:54 -07:00
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'capabilities_for_client_supports_method',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2021-10-10 22:32:50 -07:00
|
|
|
|
vim.lsp.handlers['textDocument/typeDefinition'] = function() end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-12-02 23:00:54 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(client)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.buf.type_definition()
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
2021-06-22 01:35:36 -07:00
|
|
|
|
on_handler = function(...)
|
2021-06-28 14:02:17 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { ... }, 'expected handler')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
)
|
|
|
|
|
|
2021-10-08 11:19:33 -07:00
|
|
|
|
it('should not forward RequestCancelled to callback', function()
|
|
|
|
|
local expected_handlers = {
|
2021-10-08 14:01:55 -07:00
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
2021-10-08 11:19:33 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-10-08 11:19:33 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_forward_request_cancelled',
|
|
|
|
|
on_init = function(_client)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
_client:request('error_code_test')
|
2021-10-08 11:19:33 -07:00
|
|
|
|
client = _client
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-10-08 11:19:33 -07:00
|
|
|
|
eq(0, #expected_handlers, 'did not call expected handler')
|
|
|
|
|
end,
|
2021-10-08 14:01:55 -07:00
|
|
|
|
on_handler = function(err, _, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-10-08 14:01:55 -07:00
|
|
|
|
end
|
2021-10-08 11:19:33 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2024-11-25 10:48:11 -07:00
|
|
|
|
it('should forward ServerCancelled to callback', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{
|
|
|
|
|
{ code = -32802 },
|
|
|
|
|
NIL,
|
|
|
|
|
{ method = 'error_code_test', bufnr = 1, client_id = 1, version = 0 },
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
local client --- @type vim.lsp.Client
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_forward_server_cancelled',
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
_client:request('error_code_test')
|
|
|
|
|
client = _client
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
|
|
|
|
eq(0, #expected_handlers, 'did not call expected handler')
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, _, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, _, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method ~= 'finish' then
|
|
|
|
|
client:notify('finish')
|
|
|
|
|
end
|
|
|
|
|
if ctx.method == 'finish' then
|
|
|
|
|
client:stop()
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2021-10-08 11:19:33 -07:00
|
|
|
|
it('should forward ContentModified to callback', function()
|
|
|
|
|
local expected_handlers = {
|
2021-10-08 14:01:55 -07:00
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
2024-06-14 02:03:58 -07:00
|
|
|
|
{
|
|
|
|
|
{ code = -32801 },
|
|
|
|
|
NIL,
|
|
|
|
|
{ method = 'error_code_test', bufnr = 1, client_id = 1, version = 0 },
|
|
|
|
|
},
|
2021-10-08 11:19:33 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-10-08 11:19:33 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_forward_content_modified',
|
|
|
|
|
on_init = function(_client)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
_client:request('error_code_test')
|
2021-10-08 11:19:33 -07:00
|
|
|
|
client = _client
|
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-10-08 11:19:33 -07:00
|
|
|
|
eq(0, #expected_handlers, 'did not call expected handler')
|
|
|
|
|
end,
|
2021-10-08 14:01:55 -07:00
|
|
|
|
on_handler = function(err, _, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, _, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method ~= 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2021-10-08 14:01:55 -07:00
|
|
|
|
end
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-10-08 11:19:33 -07:00
|
|
|
|
end
|
2024-01-02 18:09:18 -07:00
|
|
|
|
end,
|
2021-10-08 11:19:33 -07:00
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2021-10-29 05:45:01 -07:00
|
|
|
|
it('should track pending requests to the language server', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
2024-06-14 02:03:58 -07:00
|
|
|
|
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
|
2021-10-29 05:45:01 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-10-29 05:45:01 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_pending_request_tracked',
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:request('slow_request')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local request = exec_lua(function()
|
|
|
|
|
return _G.TEST_RPC_CLIENT.requests[2]
|
|
|
|
|
end)
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq('slow_request', request.method)
|
|
|
|
|
eq('pending', request.type)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('release')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq(0, #expected_handlers, 'did not call expected handler')
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, _, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'slow_request' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local request = exec_lua(function()
|
|
|
|
|
return _G.TEST_RPC_CLIENT.requests[2]
|
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(nil, request)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should track cancel requests to the language server', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-10-29 05:45:01 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_cancel_request_tracked',
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:request('slow_request')
|
|
|
|
|
client:cancel_request(2)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local request = exec_lua(function()
|
|
|
|
|
return _G.TEST_RPC_CLIENT.requests[2]
|
|
|
|
|
end)
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq('slow_request', request.method)
|
|
|
|
|
eq('cancel', request.type)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('release')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq(0, #expected_handlers, 'did not call expected handler')
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, _, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local request = exec_lua(function()
|
|
|
|
|
return _G.TEST_RPC_CLIENT.requests[2]
|
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(nil, request)
|
2021-10-29 05:45:01 -07:00
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should clear pending and cancel requests on reply', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
2024-06-14 02:03:58 -07:00
|
|
|
|
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
|
2021-10-29 05:45:01 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-10-29 05:45:01 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_tracked_requests_cleared',
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:request('slow_request')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local request = exec_lua(function()
|
|
|
|
|
return _G.TEST_RPC_CLIENT.requests[2]
|
|
|
|
|
end)
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq('slow_request', request.method)
|
|
|
|
|
eq('pending', request.type)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:cancel_request(2)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
request = exec_lua(function()
|
|
|
|
|
return _G.TEST_RPC_CLIENT.requests[2]
|
|
|
|
|
end)
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq('slow_request', request.method)
|
|
|
|
|
eq('cancel', request.type)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('release')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq(0, #expected_handlers, 'did not call expected handler')
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, _, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'slow_request' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local request = exec_lua(function()
|
|
|
|
|
return _G.TEST_RPC_CLIENT.requests[2]
|
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(nil, request)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should trigger LspRequest autocmd when requests table changes', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
2024-06-14 02:03:58 -07:00
|
|
|
|
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
|
2021-10-29 05:45:01 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-10-29 05:45:01 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'check_tracked_requests_cleared',
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
command('let g:requests = 0')
|
2023-05-30 11:56:29 -07:00
|
|
|
|
command('autocmd LspRequest * let g:requests+=1')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
client = _client
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:request('slow_request')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq(1, eval('g:requests'))
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:cancel_request(2)
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq(2, eval('g:requests'))
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('release')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
eq(0, #expected_handlers, 'did not call expected handler')
|
|
|
|
|
eq(3, eval('g:requests'))
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, _, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'slow_request' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-10-29 05:45:01 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2019-11-13 13:55:26 -07:00
|
|
|
|
it('should not send didOpen if the buffer closes before init', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_finish',
|
2024-03-21 08:15:20 -07:00
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
assert(_G.TEST_RPC_CLIENT_ID == 1)
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
assert(vim.lsp.buf_is_attached(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
vim.cmd(_G.BUFFER .. 'bwipeout')
|
|
|
|
|
end)
|
2024-03-21 08:15:20 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local full_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(full_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should check the body sent attaching before init', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local full_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(full_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(
|
|
|
|
|
vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID),
|
|
|
|
|
'Already attached, returns true'
|
|
|
|
|
)
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should check the body sent attaching after init', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local full_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(full_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should check the body and didChange full', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open_and_change',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local full_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(full_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'boop',
|
2019-11-21 02:29:54 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-21 02:29:54 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-21 02:29:54 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should check the body and didChange full with noeol', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-21 02:29:54 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-21 02:29:54 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open_and_change_noeol',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-21 02:29:54 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.bo[_G.BUFFER].eol = false
|
|
|
|
|
end)
|
2019-11-21 02:29:54 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local full_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(full_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-21 02:29:54 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-21 02:29:54 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'boop',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2023-09-21 03:06:40 -07:00
|
|
|
|
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://',
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
2023-09-21 03:06:40 -07:00
|
|
|
|
range = {
|
|
|
|
|
start = { line = 0, character = 0 },
|
|
|
|
|
['end'] = { line = 1, character = 3 },
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
2023-09-21 03:06:40 -07:00
|
|
|
|
},
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
client_id = 1,
|
2024-06-14 02:03:58 -07:00
|
|
|
|
version = 0,
|
2023-09-21 03:06:40 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2023-09-21 03:06:40 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'inlay_hint',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2023-09-21 03:06:40 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.bo[_G.BUFFER].eol = false
|
|
|
|
|
end)
|
2023-09-21 03:06:40 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-11-14 04:53:20 -07:00
|
|
|
|
eq(true, client:supports_method('textDocument/inlayHint'))
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2023-09-21 03:06:40 -07:00
|
|
|
|
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
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.inlay_hint.enable(true, { bufnr = _G.BUFFER })
|
|
|
|
|
end)
|
2023-09-21 03:06:40 -07:00
|
|
|
|
end
|
|
|
|
|
if ctx.method == 'textDocument/inlayHint' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2023-09-21 03:06:40 -07:00
|
|
|
|
end
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2023-09-21 03:06:40 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
2021-03-07 18:18:32 -07:00
|
|
|
|
it('should check the body and didChange incremental', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open_and_change_incremental',
|
2022-01-11 10:10:29 -07:00
|
|
|
|
options = {
|
|
|
|
|
allow_incremental_sync = true,
|
|
|
|
|
},
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2022-01-11 10:10:29 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-01-11 10:10:29 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local sync_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Incremental
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2022-01-11 10:10:29 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2022-01-11 10:10:29 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'123boop',
|
2022-01-11 10:10:29 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2022-01-11 10:10:29 -07:00
|
|
|
|
end
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-01-11 10:10:29 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-01-11 10:10:29 -07:00
|
|
|
|
it('should check the body and didChange incremental with debounce', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-01-11 10:10:29 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open_and_change_incremental',
|
|
|
|
|
options = {
|
|
|
|
|
allow_incremental_sync = true,
|
|
|
|
|
debounce_text_changes = 5,
|
|
|
|
|
},
|
2019-11-13 13:55:26 -07:00
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local sync_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Incremental
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'123boop',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
-- TODO(askhan) we don't support full for now, so we can disable these tests.
|
2020-02-08 16:35:28 -07:00
|
|
|
|
pending('should check the body and didChange incremental normal mode editing', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
2021-10-29 05:45:01 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } },
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
2020-02-08 16:35:28 -07:00
|
|
|
|
test_name = 'basic_check_buffer_open_and_change_incremental_editing',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local sync_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Incremental
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-04-20 08:44:13 -07:00
|
|
|
|
n.command('normal! 1Go')
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should check the body and didChange full with 2 changes', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open_and_change_multi',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local sync_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'321',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'boop',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('should check the body and didChange full lifecycle', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_check_buffer_open_and_change_multi_and_close',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local sync_kind = exec_lua(function()
|
|
|
|
|
return require 'vim.lsp.protocol'.TextDocumentSyncKind.Full
|
|
|
|
|
end)
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
|
|
|
|
|
eq(true, client.server_capabilities().textDocumentSync.openClose)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'321',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 1, 2, false, {
|
|
|
|
|
'boop',
|
2019-11-13 13:55:26 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_command(_G.BUFFER .. 'bwipeout')
|
|
|
|
|
end)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:notify('finish')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
describe('parsing tests', function()
|
|
|
|
|
it('should handle invalid content-length correctly', function()
|
2021-06-22 01:35:36 -07:00
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2019-11-13 13:55:26 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2019-11-13 13:55:26 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'invalid_header',
|
|
|
|
|
on_setup = function() end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop(true)
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
2019-11-13 13:55:26 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2021-05-18 15:28:09 -07:00
|
|
|
|
|
|
|
|
|
it('should not trim vim.NIL from the end of a list', function()
|
|
|
|
|
local expected_handlers = {
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
|
|
|
|
{
|
|
|
|
|
NIL,
|
2024-01-02 18:09:18 -07:00
|
|
|
|
{
|
2021-05-18 15:28:09 -07:00
|
|
|
|
arguments = { 'EXTRACT_METHOD', { metadata = {} }, 3, 0, 6123, NIL },
|
|
|
|
|
command = 'refactor.perform',
|
|
|
|
|
title = 'EXTRACT_METHOD',
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ method = 'workspace/executeCommand', client_id = 1 },
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
2021-05-18 15:28:09 -07:00
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-05-18 15:28:09 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'decode_nil',
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.BUFFER = vim.api.nvim_create_buf(false, true)
|
|
|
|
|
vim.api.nvim_buf_set_lines(_G.BUFFER, 0, -1, false, {
|
|
|
|
|
'testing',
|
|
|
|
|
'123',
|
2021-05-18 15:28:09 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2021-05-18 15:28:09 -07:00
|
|
|
|
end,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
assert(vim.lsp.buf_attach_client(_G.BUFFER, _G.TEST_RPC_CLIENT_ID))
|
|
|
|
|
end)
|
2021-05-18 15:28:09 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-05-18 15:28:09 -07:00
|
|
|
|
end,
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'finish' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-05-18 15:28:09 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2020-05-26 05:55:45 -07:00
|
|
|
|
end)
|
2020-01-08 10:20:53 -07:00
|
|
|
|
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
describe('apply vscode text_edits', function()
|
|
|
|
|
it('single replace', function()
|
|
|
|
|
insert('012345678901234567890123456789')
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 3, 0, 6, { 'Hello' } },
|
|
|
|
|
})
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
eq({ '012Hello678901234567890123456789' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
it('two replaces', function()
|
|
|
|
|
insert('012345678901234567890123456789')
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 3, 0, 6, { 'Hello' } },
|
|
|
|
|
{ 0, 6, 0, 9, { 'World' } },
|
|
|
|
|
})
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
eq({ '012HelloWorld901234567890123456789' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
it('same start pos insert are kept in order', function()
|
|
|
|
|
insert('012345678901234567890123456789')
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 3, 0, 3, { 'World' } },
|
|
|
|
|
{ 0, 3, 0, 3, { 'Hello' } },
|
|
|
|
|
})
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
eq({ '012WorldHello345678901234567890123456789' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
it('same start pos insert and replace are kept in order', function()
|
|
|
|
|
insert('012345678901234567890123456789')
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 3, 0, 3, { 'World' } },
|
|
|
|
|
{ 0, 3, 0, 3, { 'Hello' } },
|
|
|
|
|
{ 0, 3, 0, 8, { 'No' } },
|
|
|
|
|
})
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
eq({ '012WorldHelloNo8901234567890123456789' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
it('multiline', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.api.nvim_buf_set_lines(1, 0, 0, true, { ' {', ' "foo": "bar"', ' }' })
|
|
|
|
|
end)
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
eq({ ' {', ' "foo": "bar"', ' }', '' }, buf_lines(1))
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 3, 0, { '' } },
|
|
|
|
|
{ 3, 0, 3, 0, { '{\n' } },
|
|
|
|
|
{ 3, 0, 3, 0, { ' "foo": "bar"\n' } },
|
|
|
|
|
{ 3, 0, 3, 0, { '}\n' } },
|
|
|
|
|
})
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
eq({ '{', ' "foo": "bar"', '}', '' }, buf_lines(1))
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-03 17:05:16 -07:00
|
|
|
|
describe('apply_text_edits', function()
|
2020-01-08 10:46:25 -07:00
|
|
|
|
before_each(function()
|
|
|
|
|
insert(dedent([[
|
|
|
|
|
First line of text
|
|
|
|
|
Second line of text
|
|
|
|
|
Third line of text
|
2020-05-03 17:05:16 -07:00
|
|
|
|
Fourth line of text
|
|
|
|
|
å å ɧ 汉语 ↥ 🤦 🦄]]))
|
2020-01-08 10:46:25 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-08 07:04:41 -07:00
|
|
|
|
it('applies simple edits', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 0, 0, { '123' } },
|
|
|
|
|
{ 1, 0, 1, 1, { '2' } },
|
|
|
|
|
{ 2, 0, 2, 2, { '3' } },
|
|
|
|
|
{ 3, 2, 3, 4, { '' } },
|
|
|
|
|
})
|
2020-01-08 10:20:53 -07:00
|
|
|
|
eq({
|
|
|
|
|
'123First line of text',
|
|
|
|
|
'2econd line of text',
|
|
|
|
|
'3ird line of text',
|
2020-06-04 05:48:48 -07:00
|
|
|
|
'Foth line of text',
|
2020-05-03 17:05:16 -07:00
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
2020-01-08 10:20:53 -07:00
|
|
|
|
}, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-01-08 10:46:25 -07:00
|
|
|
|
it('applies complex edits', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 0, 0, { '', '12' } },
|
|
|
|
|
{ 0, 0, 0, 0, { '3', 'foo' } },
|
|
|
|
|
{ 0, 1, 0, 1, { 'bar', '123' } },
|
|
|
|
|
{ 0, #'First ', 0, #'First line of text', { 'guy' } },
|
|
|
|
|
{ 1, 0, 1, #'Second', { 'baz' } },
|
|
|
|
|
{ 2, #'Th', 2, #'Third', { 'e next' } },
|
|
|
|
|
{ 3, #'', 3, #'Fourth', { 'another line of text', 'before this' } },
|
|
|
|
|
{ 3, #'Fourth', 3, #'Fourth line of text', { '!' } },
|
|
|
|
|
})
|
2020-01-08 10:20:53 -07:00
|
|
|
|
eq({
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
'',
|
|
|
|
|
'123',
|
|
|
|
|
'fooFbar',
|
2020-01-08 10:20:53 -07:00
|
|
|
|
'123irst guy',
|
|
|
|
|
'baz line of text',
|
|
|
|
|
'The next line of text',
|
|
|
|
|
'another line of text',
|
|
|
|
|
'before this!',
|
2020-05-03 17:05:16 -07:00
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
2020-01-08 10:20:53 -07:00
|
|
|
|
}, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-09-18 13:19:21 -07:00
|
|
|
|
it('applies complex edits (reversed range)', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 0, 0, { '', '12' } },
|
|
|
|
|
{ 0, 0, 0, 0, { '3', 'foo' } },
|
|
|
|
|
{ 0, 1, 0, 1, { 'bar', '123' } },
|
|
|
|
|
{ 0, #'First line of text', 0, #'First ', { 'guy' } },
|
|
|
|
|
{ 1, #'Second', 1, 0, { 'baz' } },
|
|
|
|
|
{ 2, #'Third', 2, #'Th', { 'e next' } },
|
|
|
|
|
{ 3, #'Fourth', 3, #'', { 'another line of text', 'before this' } },
|
|
|
|
|
{ 3, #'Fourth line of text', 3, #'Fourth', { '!' } },
|
|
|
|
|
})
|
2021-09-18 13:19:21 -07:00
|
|
|
|
eq({
|
fix(lsp): revert text edit application order change (#29877)
Reverts https://github.com/neovim/neovim/pull/29212 and adds a few
additional test cases
From the spec
> All text edits ranges refer to positions in the document they are
> computed on. They therefore move a document from state S1 to S2 without
> describing any intermediate state. Text edits ranges must never overlap,
> that means no part of the original document must be manipulated by more
> than one edit. However, it is possible that multiple edits have the same
> start position: multiple inserts, or any number of inserts followed by a
> single remove or replace edit. If multiple inserts have the same
> position, the order in the array defines the order in which the inserted
> strings appear in the resulting text.
The previous fix seems wrong. The important part:
> If multiple inserts have the same position, the order in the array
> defines the order in which the inserted strings appear in the
> resulting text.
Emphasis on _appear in the resulting text_
Which means that in:
local edits1 = {
make_edit(0, 3, 0, 3, { 'World' }),
make_edit(0, 3, 0, 3, { 'Hello' }),
}
`World` must appear before `Hello` in the final text. That means the old
logic was correct, and the fix was wrong.
2024-07-27 13:30:14 -07:00
|
|
|
|
'',
|
|
|
|
|
'123',
|
|
|
|
|
'fooFbar',
|
2021-09-18 13:19:21 -07:00
|
|
|
|
'123irst guy',
|
|
|
|
|
'baz line of text',
|
|
|
|
|
'The next line of text',
|
|
|
|
|
'another line of text',
|
|
|
|
|
'before this!',
|
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
|
|
|
|
}, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-08 07:04:41 -07:00
|
|
|
|
it('applies non-ASCII characters edits', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 4, 3, 4, 4, { 'ä' } },
|
|
|
|
|
})
|
2020-05-03 17:05:16 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'Second line of text',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
2020-05-08 07:04:41 -07:00
|
|
|
|
'å ä ɧ 汉语 ↥ 🤦 🦄',
|
2020-01-08 10:20:53 -07:00
|
|
|
|
}, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-02-19 20:20:42 -07:00
|
|
|
|
it('applies text edits at the end of the document', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 5, 0, 5, 0, 'foobar' },
|
|
|
|
|
})
|
2021-02-19 20:20:42 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'Second line of text',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
|
|
|
|
'foobar',
|
|
|
|
|
}, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-01-13 02:28:13 -07:00
|
|
|
|
it('applies multiple text edits at the end of the document', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 4, 0, 5, 0, '' },
|
|
|
|
|
{ 5, 0, 5, 0, 'foobar' },
|
|
|
|
|
})
|
2022-01-13 02:28:13 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'Second line of text',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'foobar',
|
|
|
|
|
}, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2023-06-04 16:45:01 -07:00
|
|
|
|
it('it restores marks', function()
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, api.nvim_buf_set_mark(1, 'a', 2, 1, {}))
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 0, 2, 5, 'foobar' },
|
|
|
|
|
{ 4, 0, 5, 0, 'barfoo' },
|
|
|
|
|
})
|
2023-06-04 16:45:01 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'foobar line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'barfoo',
|
|
|
|
|
}, buf_lines(1))
|
2024-08-11 03:58:15 -07:00
|
|
|
|
eq({ 2, 1 }, api.nvim_buf_get_mark(1, 'a'))
|
2023-06-04 16:45:01 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('it restores marks to last valid col', function()
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, api.nvim_buf_set_mark(1, 'a', 2, 10, {}))
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 0, 2, 15, 'foobar' },
|
|
|
|
|
{ 4, 0, 5, 0, 'barfoo' },
|
|
|
|
|
})
|
2023-06-04 16:45:01 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'foobarext',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'barfoo',
|
|
|
|
|
}, buf_lines(1))
|
2024-08-11 03:58:15 -07:00
|
|
|
|
eq({ 2, 9 }, api.nvim_buf_get_mark(1, 'a'))
|
2023-06-04 16:45:01 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('it restores marks to last valid line', function()
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, api.nvim_buf_set_mark(1, 'a', 4, 1, {}))
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 0, 4, 5, 'foobar' },
|
|
|
|
|
{ 4, 0, 5, 0, 'barfoo' },
|
|
|
|
|
})
|
2023-06-04 16:45:01 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'foobaro',
|
|
|
|
|
}, buf_lines(1))
|
2024-08-11 03:58:15 -07:00
|
|
|
|
eq({ 2, 1 }, api.nvim_buf_get_mark(1, 'a'))
|
2023-06-04 16:45:01 -07:00
|
|
|
|
end)
|
2020-05-17 10:47:14 -07:00
|
|
|
|
|
2021-09-18 13:19:21 -07:00
|
|
|
|
describe('cursor position', function()
|
|
|
|
|
it("don't fix the cursor if the range contains the cursor", function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 6 })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 0, 1, 19, 'Second line of text' },
|
|
|
|
|
})
|
2021-09-18 13:19:21 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'Second line of text',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
|
|
|
|
}, buf_lines(1))
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 2, 6 }, api.nvim_win_get_cursor(0))
|
2021-09-18 13:19:21 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2021-10-18 11:49:33 -07:00
|
|
|
|
it('fix the cursor to the valid col if the content was removed', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 6 })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 0, 1, 6, '' },
|
|
|
|
|
{ 1, 6, 1, 19, '' },
|
|
|
|
|
})
|
2021-09-18 13:19:21 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
|
|
|
|
}, buf_lines(1))
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 2, 0 }, api.nvim_win_get_cursor(0))
|
2021-09-18 13:19:21 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2021-10-18 11:49:33 -07:00
|
|
|
|
it('fix the cursor to the valid row if the content was removed', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 6 })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 0, 1, 6, '' },
|
|
|
|
|
{ 0, 18, 5, 0, '' },
|
|
|
|
|
})
|
2021-10-18 11:49:33 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
}, buf_lines(1))
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 1, 17 }, api.nvim_win_get_cursor(0))
|
2021-10-18 11:49:33 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2021-09-18 13:19:21 -07:00
|
|
|
|
it('fix the cursor row', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 3, 0 })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 0, 2, 0, '' },
|
|
|
|
|
})
|
2021-09-18 13:19:21 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
|
|
|
|
}, buf_lines(1))
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 2, 0 }, api.nvim_win_get_cursor(0))
|
2021-09-18 13:19:21 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('fix the cursor col', function()
|
2023-03-14 04:59:43 -07:00
|
|
|
|
-- append empty last line. See #22636
|
2024-04-02 06:45:19 -07:00
|
|
|
|
api.nvim_buf_set_lines(1, -1, -1, true, { '' })
|
2023-03-14 04:59:43 -07:00
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 11 })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 1, 7, 1, 11, '' },
|
|
|
|
|
})
|
2021-09-18 13:19:21 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'Second of text',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
2023-03-14 04:59:43 -07:00
|
|
|
|
'',
|
2021-09-18 13:19:21 -07:00
|
|
|
|
}, buf_lines(1))
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 2, 7 }, api.nvim_win_get_cursor(0))
|
2021-09-18 13:19:21 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('fix the cursor row and col', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 12 })
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 11, 1, 12, '' },
|
|
|
|
|
})
|
2021-09-18 13:19:21 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First line of text',
|
|
|
|
|
'Third line of text',
|
|
|
|
|
'Fourth line of text',
|
|
|
|
|
'å å ɧ 汉语 ↥ 🤦 🦄',
|
|
|
|
|
}, buf_lines(1))
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 1, 11 }, api.nvim_win_get_cursor(0))
|
2021-09-18 13:19:21 -07:00
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-05-17 10:47:14 -07:00
|
|
|
|
describe('with LSP end line after what Vim considers to be the end line', function()
|
|
|
|
|
it('applies edits when the last linebreak is considered a new line', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 5, 0, { 'All replaced' } },
|
|
|
|
|
})
|
2020-05-17 10:47:14 -07:00
|
|
|
|
eq({ 'All replaced' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-17 10:47:14 -07:00
|
|
|
|
it("applies edits when the end line is 2 larger than vim's", function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 6, 0, { 'All replaced' } },
|
|
|
|
|
})
|
2020-05-17 10:47:14 -07:00
|
|
|
|
eq({ 'All replaced' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-17 10:47:14 -07:00
|
|
|
|
it('applies edits with a column offset', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 5, 2, { 'All replaced' } },
|
|
|
|
|
})
|
2020-05-17 10:47:14 -07:00
|
|
|
|
eq({ 'All replaced' }, buf_lines(1))
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2020-01-08 10:20:53 -07:00
|
|
|
|
end)
|
2020-04-27 01:55:06 -07:00
|
|
|
|
|
2022-09-20 13:14:58 -07:00
|
|
|
|
describe('apply_text_edits regression tests for #20116', function()
|
|
|
|
|
before_each(function()
|
|
|
|
|
insert(dedent([[
|
|
|
|
|
Test line one
|
|
|
|
|
Test line two 21 char]]))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-09-20 13:14:58 -07:00
|
|
|
|
describe('with LSP end column out of bounds and start column at 0', function()
|
|
|
|
|
it('applies edits at the end of the buffer', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' } },
|
|
|
|
|
}, 'utf-8')
|
2022-09-20 13:14:58 -07:00
|
|
|
|
eq({ '#include "whatever.h"', '#include <algorithm>' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-09-20 13:14:58 -07:00
|
|
|
|
it('applies edits in the middle of the buffer', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 0, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' } },
|
|
|
|
|
}, 'utf-8')
|
2022-09-20 13:14:58 -07:00
|
|
|
|
eq(
|
|
|
|
|
{ '#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' },
|
|
|
|
|
buf_lines(1)
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2022-09-20 13:14:58 -07:00
|
|
|
|
end)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-09-20 13:14:58 -07:00
|
|
|
|
describe('with LSP end column out of bounds and start column NOT at 0', function()
|
|
|
|
|
it('applies edits at the end of the buffer', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 2, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' } },
|
|
|
|
|
}, 'utf-8')
|
2022-09-20 13:14:58 -07:00
|
|
|
|
eq({ 'Te#include "whatever.h"', '#include <algorithm>' }, buf_lines(1))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-09-20 13:14:58 -07:00
|
|
|
|
it('applies edits in the middle of the buffer', function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
apply_text_edits({
|
|
|
|
|
{ 0, 2, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' } },
|
|
|
|
|
}, 'utf-8')
|
2022-09-20 13:14:58 -07:00
|
|
|
|
eq(
|
|
|
|
|
{ 'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' },
|
|
|
|
|
buf_lines(1)
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2022-09-20 13:14:58 -07:00
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-04-27 01:55:06 -07:00
|
|
|
|
describe('apply_text_document_edit', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local target_bufnr --- @type integer
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-13 20:14:52 -07:00
|
|
|
|
local text_document_edit = function(editVersion)
|
|
|
|
|
return {
|
|
|
|
|
edits = {
|
|
|
|
|
make_edit(0, 0, 0, 3, 'First ↥ 🤦 🦄'),
|
2021-01-11 09:39:11 -07:00
|
|
|
|
},
|
2020-05-13 20:14:52 -07:00
|
|
|
|
textDocument = {
|
2021-07-07 16:36:27 -07:00
|
|
|
|
uri = 'file:///fake/uri',
|
2020-05-13 20:14:52 -07:00
|
|
|
|
version = editVersion,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
end
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-04-27 01:55:06 -07:00
|
|
|
|
before_each(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
target_bufnr = exec_lua(function()
|
|
|
|
|
local bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
|
|
|
|
local lines = { '1st line of text', '2nd line of 语text' }
|
2020-05-02 21:01:00 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
|
|
|
|
return bufnr
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-04-27 01:55:06 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-02 21:01:00 -07:00
|
|
|
|
it('correctly goes ahead with the edit if all is normal', function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function(text_edit)
|
|
|
|
|
vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16')
|
|
|
|
|
end, text_document_edit(5))
|
2020-04-27 01:55:06 -07:00
|
|
|
|
eq({
|
2020-05-13 20:14:52 -07:00
|
|
|
|
'First ↥ 🤦 🦄 line of text',
|
|
|
|
|
'2nd line of 语text',
|
2020-05-02 21:01:00 -07:00
|
|
|
|
}, buf_lines(target_bufnr))
|
2020-04-27 01:55:06 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-04-14 12:29:32 -07:00
|
|
|
|
it('always accepts edit with version = 0', function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function(text_edit)
|
|
|
|
|
vim.lsp.util.buf_versions[target_bufnr] = 10
|
2022-01-13 03:34:04 -07:00
|
|
|
|
vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16')
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end, text_document_edit(0))
|
2021-04-14 12:29:32 -07:00
|
|
|
|
eq({
|
|
|
|
|
'First ↥ 🤦 🦄 line of text',
|
|
|
|
|
'2nd line of 语text',
|
|
|
|
|
}, buf_lines(target_bufnr))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-04-27 01:55:06 -07:00
|
|
|
|
it('skips the edit if the version of the edit is behind the local buffer ', function()
|
2024-06-07 02:36:46 -07:00
|
|
|
|
local apply_edit_mocking_current_version = function(edit, versionedBuf)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion
|
|
|
|
|
vim.lsp.util.apply_text_document_edit(edit, nil, 'utf-16')
|
|
|
|
|
end)
|
2020-05-13 20:14:52 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local baseText = {
|
|
|
|
|
'1st line of text',
|
|
|
|
|
'2nd line of 语text',
|
2020-04-27 01:55:06 -07:00
|
|
|
|
}
|
2020-05-13 20:14:52 -07:00
|
|
|
|
|
|
|
|
|
eq(baseText, buf_lines(target_bufnr))
|
|
|
|
|
|
|
|
|
|
-- Apply an edit for an old version, should skip
|
2024-06-07 02:36:46 -07:00
|
|
|
|
apply_edit_mocking_current_version(
|
|
|
|
|
text_document_edit(2),
|
|
|
|
|
{ currentVersion = 7, bufnr = target_bufnr }
|
|
|
|
|
)
|
2020-05-13 20:14:52 -07:00
|
|
|
|
eq(baseText, buf_lines(target_bufnr)) -- no change
|
|
|
|
|
|
|
|
|
|
-- Sanity check that next version to current does apply change
|
2024-06-07 02:36:46 -07:00
|
|
|
|
apply_edit_mocking_current_version(
|
|
|
|
|
text_document_edit(8),
|
|
|
|
|
{ currentVersion = 7, bufnr = target_bufnr }
|
|
|
|
|
)
|
2020-04-27 01:55:06 -07:00
|
|
|
|
eq({
|
2020-05-13 20:14:52 -07:00
|
|
|
|
'First ↥ 🤦 🦄 line of text',
|
|
|
|
|
'2nd line of 语text',
|
2020-05-02 21:01:00 -07:00
|
|
|
|
}, buf_lines(target_bufnr))
|
2020-04-27 01:55:06 -07:00
|
|
|
|
end)
|
2020-01-08 10:20:53 -07:00
|
|
|
|
end)
|
2021-01-11 09:39:11 -07:00
|
|
|
|
|
2020-05-11 07:56:35 -07:00
|
|
|
|
describe('workspace_apply_edit', function()
|
|
|
|
|
it('workspace/applyEdit returns ApplyWorkspaceEditResponse', function()
|
2022-01-13 03:34:04 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'test', client_id = 1 } },
|
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_init',
|
|
|
|
|
on_init = function(client, _)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-01-13 03:34:04 -07:00
|
|
|
|
end,
|
|
|
|
|
-- If the program timed out, then code will be nil.
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2022-01-13 03:34:04 -07:00
|
|
|
|
end,
|
|
|
|
|
-- Note that NIL must be used here.
|
|
|
|
|
-- on_handler(err, method, result, client_id)
|
|
|
|
|
on_handler = function(...)
|
|
|
|
|
local expected = {
|
|
|
|
|
applied = true,
|
|
|
|
|
failureReason = nil,
|
|
|
|
|
}
|
|
|
|
|
eq(
|
|
|
|
|
expected,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local apply_edit = {
|
|
|
|
|
label = nil,
|
|
|
|
|
edit = {},
|
|
|
|
|
}
|
|
|
|
|
return vim.lsp.handlers['workspace/applyEdit'](
|
|
|
|
|
nil,
|
|
|
|
|
apply_edit,
|
|
|
|
|
{ client_id = _G.TEST_RPC_CLIENT_ID }
|
|
|
|
|
)
|
|
|
|
|
end)
|
2022-01-13 03:34:04 -07:00
|
|
|
|
)
|
|
|
|
|
eq(table.remove(expected_handlers), { ... })
|
|
|
|
|
end,
|
2020-05-11 07:56:35 -07:00
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2021-01-11 09:39:11 -07:00
|
|
|
|
|
|
|
|
|
describe('apply_workspace_edit', function()
|
|
|
|
|
local replace_line_edit = function(row, new_line, editVersion)
|
|
|
|
|
return {
|
|
|
|
|
edits = {
|
|
|
|
|
-- NOTE: This is a hack if you have a line longer than 1000 it won't replace it
|
|
|
|
|
make_edit(row, 0, row, 1000, new_line),
|
|
|
|
|
},
|
|
|
|
|
textDocument = {
|
2021-07-07 16:36:27 -07:00
|
|
|
|
uri = 'file:///fake/uri',
|
2021-01-11 09:39:11 -07:00
|
|
|
|
version = editVersion,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Some servers send all the edits separately, but with the same version.
|
|
|
|
|
-- We should not stop applying the edits
|
|
|
|
|
local make_workspace_edit = function(changes)
|
|
|
|
|
return {
|
|
|
|
|
documentChanges = changes,
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local target_bufnr --- @type integer
|
|
|
|
|
local changedtick --- @type integer
|
2021-01-11 09:39:11 -07:00
|
|
|
|
|
|
|
|
|
before_each(function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
target_bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
2021-01-11 09:39:11 -07:00
|
|
|
|
local lines = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
'Original Line #1',
|
|
|
|
|
'Original Line #2',
|
2021-01-11 09:39:11 -07:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(target_bufnr, 0, -1, false, lines)
|
2024-06-07 02:36:46 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local function update_changed_tick()
|
|
|
|
|
vim.lsp.util.buf_versions[target_bufnr] = vim.b[target_bufnr].changedtick
|
2024-06-07 02:36:46 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
update_changed_tick()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.api.nvim_buf_attach(target_bufnr, false, {
|
|
|
|
|
on_changedtick = update_changed_tick,
|
2024-06-07 02:36:46 -07:00
|
|
|
|
})
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
changedtick = vim.b[target_bufnr].changedtick
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2021-01-11 09:39:11 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('apply_workspace_edit applies a single edit', function()
|
|
|
|
|
local new_lines = {
|
|
|
|
|
'First Line',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local edits = {}
|
|
|
|
|
for row, line in ipairs(new_lines) do
|
|
|
|
|
table.insert(edits, replace_line_edit(row - 1, line, changedtick))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
eq(
|
|
|
|
|
{
|
|
|
|
|
'First Line',
|
|
|
|
|
'Original Line #2',
|
|
|
|
|
},
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function(workspace_edits)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
|
2021-01-11 09:39:11 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
|
|
|
|
|
end, make_workspace_edit(edits))
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2021-01-11 09:39:11 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('apply_workspace_edit applies multiple edits', function()
|
|
|
|
|
local new_lines = {
|
|
|
|
|
'First Line',
|
|
|
|
|
'Second Line',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local edits = {}
|
|
|
|
|
for row, line in ipairs(new_lines) do
|
|
|
|
|
table.insert(edits, replace_line_edit(row - 1, line, changedtick))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
eq(
|
|
|
|
|
new_lines,
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function(workspace_edits)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
|
2024-08-11 01:27:48 -07:00
|
|
|
|
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
|
|
|
|
|
end, make_workspace_edit(edits))
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2021-01-11 09:39:11 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-18 03:07:06 -07:00
|
|
|
|
it('Supports file creation with CreateFile payload', function()
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local tmpfile = tmpname(false)
|
2021-03-18 03:07:06 -07:00
|
|
|
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
|
|
|
|
local edit = {
|
|
|
|
|
documentChanges = {
|
|
|
|
|
{
|
|
|
|
|
kind = 'create',
|
|
|
|
|
uri = uri,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.util.apply_workspace_edit(edit, 'utf-16')
|
|
|
|
|
end)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
|
2021-03-18 03:07:06 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-09-24 03:46:21 -07:00
|
|
|
|
it(
|
|
|
|
|
'Supports file creation in folder that needs to be created with CreateFile payload',
|
|
|
|
|
function()
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local tmpfile = tmpname(false) .. '/dummy/x/'
|
2022-09-24 03:46:21 -07:00
|
|
|
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
|
|
|
|
local edit = {
|
|
|
|
|
documentChanges = {
|
|
|
|
|
{
|
|
|
|
|
kind = 'create',
|
|
|
|
|
uri = uri,
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
2022-09-24 03:46:21 -07:00
|
|
|
|
},
|
|
|
|
|
}
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.util.apply_workspace_edit(edit, 'utf-16')
|
|
|
|
|
end)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
|
2022-09-24 03:46:21 -07:00
|
|
|
|
end
|
|
|
|
|
)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-18 03:07:06 -07:00
|
|
|
|
it('createFile does not touch file if it exists and ignoreIfExists is set', function()
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local tmpfile = tmpname()
|
2021-03-18 03:07:06 -07:00
|
|
|
|
write_file(tmpfile, 'Dummy content')
|
|
|
|
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
|
|
|
|
local edit = {
|
|
|
|
|
documentChanges = {
|
|
|
|
|
{
|
|
|
|
|
kind = 'create',
|
|
|
|
|
uri = uri,
|
|
|
|
|
options = {
|
|
|
|
|
ignoreIfExists = true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
2022-01-13 03:34:04 -07:00
|
|
|
|
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
|
2021-03-18 03:07:06 -07:00
|
|
|
|
eq('Dummy content', read_file(tmpfile))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-18 03:07:06 -07:00
|
|
|
|
it('createFile overrides file if overwrite is set', function()
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local tmpfile = tmpname()
|
2021-03-18 03:07:06 -07:00
|
|
|
|
write_file(tmpfile, 'Dummy content')
|
|
|
|
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
|
|
|
|
local edit = {
|
|
|
|
|
documentChanges = {
|
|
|
|
|
{
|
|
|
|
|
kind = 'create',
|
|
|
|
|
uri = uri,
|
|
|
|
|
options = {
|
|
|
|
|
overwrite = true,
|
|
|
|
|
ignoreIfExists = true, -- overwrite must win over ignoreIfExists
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
2022-01-13 03:34:04 -07:00
|
|
|
|
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, vim.uv.fs_stat(tmpfile) ~= nil)
|
2021-03-18 03:07:06 -07:00
|
|
|
|
eq('', read_file(tmpfile))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-18 03:32:33 -07:00
|
|
|
|
it('DeleteFile delete file and buffer', function()
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local tmpfile = tmpname()
|
2021-03-18 03:32:33 -07:00
|
|
|
|
write_file(tmpfile, 'Be gone')
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local uri = exec_lua(function()
|
|
|
|
|
local bufnr = vim.fn.bufadd(tmpfile)
|
2021-03-18 03:32:33 -07:00
|
|
|
|
vim.fn.bufload(bufnr)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
return vim.uri_from_fname(tmpfile)
|
|
|
|
|
end)
|
2021-03-18 03:32:33 -07:00
|
|
|
|
local edit = {
|
|
|
|
|
documentChanges = {
|
|
|
|
|
{
|
|
|
|
|
kind = 'delete',
|
|
|
|
|
uri = uri,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
2022-01-13 03:34:04 -07:00
|
|
|
|
eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16'))
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(false, vim.uv.fs_stat(tmpfile) ~= nil)
|
|
|
|
|
eq(false, api.nvim_buf_is_loaded(fn.bufadd(tmpfile)))
|
2021-03-18 03:32:33 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-18 03:32:33 -07:00
|
|
|
|
it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function()
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local tmpfile = tmpname(false)
|
2021-03-18 03:32:33 -07:00
|
|
|
|
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
|
|
|
|
|
local edit = {
|
|
|
|
|
documentChanges = {
|
|
|
|
|
{
|
|
|
|
|
kind = 'delete',
|
|
|
|
|
uri = uri,
|
|
|
|
|
options = {
|
|
|
|
|
ignoreIfNotExists = false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
2024-10-16 05:17:10 -07:00
|
|
|
|
eq(false, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16'))
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(false, vim.uv.fs_stat(tmpfile) ~= nil)
|
2021-03-18 03:32:33 -07:00
|
|
|
|
end)
|
2021-01-11 09:39:11 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2021-03-15 14:34:22 -07:00
|
|
|
|
describe('lsp.util.rename', function()
|
2024-04-20 08:44:13 -07:00
|
|
|
|
local pathsep = n.get_pathsep()
|
2023-02-17 23:43:59 -07:00
|
|
|
|
|
2021-03-15 14:34:22 -07:00
|
|
|
|
it('Can rename an existing file', function()
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local old = tmpname()
|
2021-03-15 14:34:22 -07:00
|
|
|
|
write_file(old, 'Test content')
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local new = tmpname(false)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local lines = exec_lua(function()
|
|
|
|
|
local old_bufnr = vim.fn.bufadd(old)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
vim.fn.bufload(old_bufnr)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.util.rename(old, new)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
-- the existing buffer is renamed in-place and its contents is kept
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local new_bufnr = vim.fn.bufadd(new)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
vim.fn.bufload(new_bufnr)
|
|
|
|
|
return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2021-03-15 14:34:22 -07:00
|
|
|
|
eq({ 'Test content' }, lines)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
local exists = vim.uv.fs_stat(old) ~= nil
|
2021-03-15 14:34:22 -07:00
|
|
|
|
eq(false, exists)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
exists = vim.uv.fs_stat(new) ~= nil
|
2021-03-15 14:34:22 -07:00
|
|
|
|
eq(true, exists)
|
|
|
|
|
os.remove(new)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2023-03-14 05:08:37 -07:00
|
|
|
|
it('Can rename a directory', function()
|
2023-02-17 23:43:59 -07:00
|
|
|
|
-- only reserve the name, file must not exist for the test scenario
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local old_dir = tmpname(false)
|
|
|
|
|
local new_dir = tmpname(false)
|
2023-02-17 23:43:59 -07:00
|
|
|
|
|
2024-04-20 08:44:13 -07:00
|
|
|
|
n.mkdir_p(old_dir)
|
2023-02-17 23:43:59 -07:00
|
|
|
|
|
2023-03-14 05:08:37 -07:00
|
|
|
|
local file = 'file.txt'
|
2023-02-17 23:43:59 -07:00
|
|
|
|
write_file(old_dir .. pathsep .. file, 'Test content')
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local lines = exec_lua(function()
|
|
|
|
|
local old_bufnr = vim.fn.bufadd(old_dir .. pathsep .. file)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
vim.fn.bufload(old_bufnr)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.util.rename(old_dir, new_dir)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
-- the existing buffer is renamed in-place and its contents is kept
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local new_bufnr = vim.fn.bufadd(new_dir .. pathsep .. file)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
vim.fn.bufload(new_bufnr)
|
|
|
|
|
return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
eq({ 'Test content' }, lines)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(false, vim.uv.fs_stat(old_dir) ~= nil)
|
|
|
|
|
eq(true, vim.uv.fs_stat(new_dir) ~= nil)
|
|
|
|
|
eq(true, vim.uv.fs_stat(new_dir .. pathsep .. file) ~= nil)
|
2023-02-17 23:43:59 -07:00
|
|
|
|
|
|
|
|
|
os.remove(new_dir)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-02-24 08:47:34 -07:00
|
|
|
|
it('Does not touch buffers that do not match path prefix', function()
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local old = tmpname(false)
|
|
|
|
|
local new = tmpname(false)
|
2024-04-20 08:44:13 -07:00
|
|
|
|
n.mkdir_p(old)
|
2024-02-24 08:47:34 -07:00
|
|
|
|
|
2024-08-11 03:58:15 -07:00
|
|
|
|
eq(
|
|
|
|
|
true,
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local old_prefixed = 'explorer://' .. old
|
|
|
|
|
local old_suffixed = old .. '.bak'
|
|
|
|
|
local new_prefixed = 'explorer://' .. new
|
|
|
|
|
local new_suffixed = new .. '.bak'
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
|
|
|
|
local old_prefixed_buf = vim.fn.bufadd(old_prefixed)
|
|
|
|
|
local old_suffixed_buf = vim.fn.bufadd(old_suffixed)
|
|
|
|
|
local new_prefixed_buf = vim.fn.bufadd(new_prefixed)
|
|
|
|
|
local new_suffixed_buf = vim.fn.bufadd(new_suffixed)
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.util.rename(old, new)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
|
|
|
|
return vim.api.nvim_buf_is_valid(old_prefixed_buf)
|
|
|
|
|
and vim.api.nvim_buf_is_valid(old_suffixed_buf)
|
|
|
|
|
and vim.api.nvim_buf_is_valid(new_prefixed_buf)
|
|
|
|
|
and vim.api.nvim_buf_is_valid(new_suffixed_buf)
|
|
|
|
|
and vim.api.nvim_buf_get_name(old_prefixed_buf) == old_prefixed
|
|
|
|
|
and vim.api.nvim_buf_get_name(old_suffixed_buf) == old_suffixed
|
|
|
|
|
and vim.api.nvim_buf_get_name(new_prefixed_buf) == new_prefixed
|
|
|
|
|
and vim.api.nvim_buf_get_name(new_suffixed_buf) == new_suffixed
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
)
|
2024-02-24 08:47:34 -07:00
|
|
|
|
|
|
|
|
|
os.remove(new)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-15 14:34:22 -07:00
|
|
|
|
it(
|
|
|
|
|
'Does not rename file if target exists and ignoreIfExists is set or overwrite is false',
|
|
|
|
|
function()
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local old = tmpname()
|
2021-03-15 14:34:22 -07:00
|
|
|
|
write_file(old, 'Old File')
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local new = tmpname()
|
2021-03-15 14:34:22 -07:00
|
|
|
|
write_file(new, 'New file')
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.util.rename(old, new, { ignoreIfExists = true })
|
|
|
|
|
end)
|
2021-03-15 14:34:22 -07:00
|
|
|
|
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, vim.uv.fs_stat(old) ~= nil)
|
2021-03-15 14:34:22 -07:00
|
|
|
|
eq('New file', read_file(new))
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.util.rename(old, new, { overwrite = false })
|
|
|
|
|
end)
|
2021-03-15 14:34:22 -07:00
|
|
|
|
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(true, vim.uv.fs_stat(old) ~= nil)
|
2021-03-15 14:34:22 -07:00
|
|
|
|
eq('New file', read_file(new))
|
|
|
|
|
end
|
|
|
|
|
)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-03-01 10:31:54 -07:00
|
|
|
|
it('Maintains undo information for loaded buffer', function()
|
|
|
|
|
local old = tmpname()
|
|
|
|
|
write_file(old, 'line')
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local new = tmpname(false)
|
2024-03-01 10:31:54 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local undo_kept = exec_lua(function()
|
2024-03-01 10:31:54 -07:00
|
|
|
|
vim.opt.undofile = true
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.cmd.edit(old)
|
2024-03-01 10:31:54 -07:00
|
|
|
|
vim.cmd.normal('dd')
|
|
|
|
|
vim.cmd.write()
|
|
|
|
|
local undotree = vim.fn.undotree()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.util.rename(old, new)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
-- Renaming uses :saveas, which updates the "last write" information.
|
|
|
|
|
-- Other than that, the undotree should remain the same.
|
|
|
|
|
undotree.save_cur = undotree.save_cur + 1
|
|
|
|
|
undotree.save_last = undotree.save_last + 1
|
|
|
|
|
undotree.entries[1].save = undotree.entries[1].save + 1
|
2024-03-01 10:31:54 -07:00
|
|
|
|
return vim.deep_equal(undotree, vim.fn.undotree())
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(false, vim.uv.fs_stat(old) ~= nil)
|
|
|
|
|
eq(true, vim.uv.fs_stat(new) ~= nil)
|
2024-03-01 10:31:54 -07:00
|
|
|
|
eq(true, undo_kept)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-03-01 10:31:54 -07:00
|
|
|
|
it('Maintains undo information for unloaded buffer', function()
|
|
|
|
|
local old = tmpname()
|
|
|
|
|
write_file(old, 'line')
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local new = tmpname(false)
|
2024-03-01 10:31:54 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local undo_kept = exec_lua(function()
|
2024-03-01 10:31:54 -07:00
|
|
|
|
vim.opt.undofile = true
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.cmd.split(old)
|
2024-03-01 10:31:54 -07:00
|
|
|
|
vim.cmd.normal('dd')
|
|
|
|
|
vim.cmd.write()
|
|
|
|
|
local undotree = vim.fn.undotree()
|
|
|
|
|
vim.cmd.bdelete()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.util.rename(old, new)
|
|
|
|
|
vim.cmd.edit(new)
|
2024-03-01 10:31:54 -07:00
|
|
|
|
return vim.deep_equal(undotree, vim.fn.undotree())
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(false, vim.uv.fs_stat(old) ~= nil)
|
|
|
|
|
eq(true, vim.uv.fs_stat(new) ~= nil)
|
2024-03-01 10:31:54 -07:00
|
|
|
|
eq(true, undo_kept)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-03-02 07:21:53 -07:00
|
|
|
|
it('Does not rename file when it conflicts with a buffer without file', function()
|
|
|
|
|
local old = tmpname()
|
|
|
|
|
write_file(old, 'Old File')
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local new = tmpname(false)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local lines = exec_lua(function()
|
|
|
|
|
local old_buf = vim.fn.bufadd(old)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.fn.bufload(old_buf)
|
|
|
|
|
local conflict_buf = vim.api.nvim_create_buf(true, false)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.api.nvim_buf_set_name(conflict_buf, new)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(conflict_buf, 0, -1, true, { 'conflict' })
|
|
|
|
|
vim.api.nvim_win_set_buf(0, conflict_buf)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.util.rename(old, new)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return vim.api.nvim_buf_get_lines(conflict_buf, 0, -1, true)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-03-02 07:21:53 -07:00
|
|
|
|
eq({ 'conflict' }, lines)
|
|
|
|
|
eq('Old File', read_file(old))
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-15 14:34:22 -07:00
|
|
|
|
it('Does override target if overwrite is true', function()
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local old = tmpname()
|
2021-03-15 14:34:22 -07:00
|
|
|
|
write_file(old, 'Old file')
|
2024-01-12 04:28:20 -07:00
|
|
|
|
local new = tmpname()
|
2021-03-15 14:34:22 -07:00
|
|
|
|
write_file(new, 'New file')
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.util.rename(old, new, { overwrite = true })
|
|
|
|
|
end)
|
2021-03-15 14:34:22 -07:00
|
|
|
|
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(false, vim.uv.fs_stat(old) ~= nil)
|
|
|
|
|
eq(true, vim.uv.fs_stat(new) ~= nil)
|
2024-02-28 09:32:25 -07:00
|
|
|
|
eq('Old file', read_file(new))
|
2021-03-15 14:34:22 -07:00
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-06-30 08:48:04 -07:00
|
|
|
|
describe('lsp.util.locations_to_items', function()
|
|
|
|
|
it('Convert Location[] to items', function()
|
2024-09-05 00:23:11 -07:00
|
|
|
|
local expected_template = {
|
2020-06-30 08:48:04 -07:00
|
|
|
|
{
|
2021-07-07 16:36:27 -07:00
|
|
|
|
filename = '/fake/uri',
|
2020-06-30 08:48:04 -07:00
|
|
|
|
lnum = 1,
|
2024-06-09 18:14:55 -07:00
|
|
|
|
end_lnum = 2,
|
2020-06-30 08:48:04 -07:00
|
|
|
|
col = 3,
|
2024-06-09 18:14:55 -07:00
|
|
|
|
end_col = 4,
|
2023-09-07 01:12:02 -07:00
|
|
|
|
text = 'testing',
|
2024-09-05 00:23:11 -07:00
|
|
|
|
user_data = {},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
local test_params = {
|
|
|
|
|
{
|
|
|
|
|
{
|
2023-09-07 01:12:02 -07:00
|
|
|
|
uri = 'file:///fake/uri',
|
|
|
|
|
range = {
|
|
|
|
|
start = { line = 0, character = 2 },
|
2024-06-09 18:14:55 -07:00
|
|
|
|
['end'] = { line = 1, character = 3 },
|
2023-09-07 01:12:02 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
2020-06-30 08:48:04 -07:00
|
|
|
|
},
|
2024-09-05 00:23:11 -07:00
|
|
|
|
{
|
2020-06-30 08:48:04 -07:00
|
|
|
|
{
|
2021-07-07 16:36:27 -07:00
|
|
|
|
uri = 'file:///fake/uri',
|
2020-06-30 08:48:04 -07:00
|
|
|
|
range = {
|
|
|
|
|
start = { line = 0, character = 2 },
|
2024-09-05 00:23:11 -07:00
|
|
|
|
-- LSP spec: if character > line length, default to the line length.
|
|
|
|
|
['end'] = { line = 1, character = 10000 },
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2020-06-30 08:48:04 -07:00
|
|
|
|
},
|
2024-09-05 00:23:11 -07:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, params in ipairs(test_params) do
|
|
|
|
|
local actual = exec_lua(function(params0)
|
|
|
|
|
local bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
|
|
|
|
local lines = { 'testing', '123' }
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
|
|
|
|
return vim.lsp.util.locations_to_items(params0, 'utf-16')
|
|
|
|
|
end, params)
|
|
|
|
|
local expected = vim.deepcopy(expected_template)
|
|
|
|
|
expected[1].user_data = params[1]
|
|
|
|
|
eq(expected, actual)
|
|
|
|
|
end
|
2020-06-30 08:48:04 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-06-30 08:48:04 -07:00
|
|
|
|
it('Convert LocationLink[] to items', function()
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
2021-07-07 16:36:27 -07:00
|
|
|
|
filename = '/fake/uri',
|
2020-06-30 08:48:04 -07:00
|
|
|
|
lnum = 1,
|
2024-06-09 18:14:55 -07:00
|
|
|
|
end_lnum = 1,
|
2020-06-30 08:48:04 -07:00
|
|
|
|
col = 3,
|
2024-06-09 18:14:55 -07:00
|
|
|
|
end_col = 4,
|
2023-09-07 01:12:02 -07:00
|
|
|
|
text = 'testing',
|
|
|
|
|
user_data = {
|
|
|
|
|
targetUri = 'file:///fake/uri',
|
|
|
|
|
targetRange = {
|
|
|
|
|
start = { line = 0, character = 2 },
|
|
|
|
|
['end'] = { line = 0, character = 3 },
|
|
|
|
|
},
|
|
|
|
|
targetSelectionRange = {
|
|
|
|
|
start = { line = 0, character = 2 },
|
|
|
|
|
['end'] = { line = 0, character = 3 },
|
|
|
|
|
},
|
|
|
|
|
},
|
2020-06-30 08:48:04 -07:00
|
|
|
|
},
|
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local actual = exec_lua(function()
|
|
|
|
|
local bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
|
|
|
|
local lines = { 'testing', '123' }
|
2020-06-30 08:48:04 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
|
|
|
|
local locations = {
|
|
|
|
|
{
|
|
|
|
|
targetUri = vim.uri_from_bufnr(bufnr),
|
|
|
|
|
targetRange = {
|
|
|
|
|
start = { line = 0, character = 2 },
|
|
|
|
|
['end'] = { line = 0, character = 3 },
|
|
|
|
|
},
|
|
|
|
|
targetSelectionRange = {
|
|
|
|
|
start = { line = 0, character = 2 },
|
|
|
|
|
['end'] = { line = 0, character = 3 },
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2020-06-30 08:48:04 -07:00
|
|
|
|
},
|
|
|
|
|
}
|
2022-01-13 03:34:04 -07:00
|
|
|
|
return vim.lsp.util.locations_to_items(locations, 'utf-16')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-06-30 08:48:04 -07:00
|
|
|
|
eq(expected, actual)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
|
2020-05-01 23:09:49 -07:00
|
|
|
|
describe('lsp.util.symbols_to_items', function()
|
|
|
|
|
describe('convert DocumentSymbol[] to items', function()
|
|
|
|
|
it('DocumentSymbol has children', function()
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
col = 1,
|
|
|
|
|
filename = '',
|
|
|
|
|
kind = 'File',
|
|
|
|
|
lnum = 2,
|
|
|
|
|
text = '[File] TestA',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
col = 1,
|
|
|
|
|
filename = '',
|
|
|
|
|
kind = 'Module',
|
|
|
|
|
lnum = 4,
|
|
|
|
|
text = '[Module] TestB',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
col = 1,
|
|
|
|
|
filename = '',
|
|
|
|
|
kind = 'Namespace',
|
|
|
|
|
lnum = 6,
|
|
|
|
|
text = '[Namespace] TestC',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
eq(
|
|
|
|
|
expected,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local doc_syms = {
|
|
|
|
|
{
|
|
|
|
|
deprecated = false,
|
|
|
|
|
detail = 'A',
|
|
|
|
|
kind = 1,
|
|
|
|
|
name = 'TestA',
|
|
|
|
|
range = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 1,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 2,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 1,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 4,
|
|
|
|
|
line = 1,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
children = {
|
|
|
|
|
{
|
|
|
|
|
children = {},
|
|
|
|
|
deprecated = false,
|
|
|
|
|
detail = 'B',
|
|
|
|
|
kind = 2,
|
|
|
|
|
name = 'TestB',
|
|
|
|
|
range = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 3,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 4,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 3,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 4,
|
|
|
|
|
line = 3,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
{
|
|
|
|
|
deprecated = false,
|
|
|
|
|
detail = 'C',
|
|
|
|
|
kind = 3,
|
|
|
|
|
name = 'TestC',
|
|
|
|
|
range = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 5,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 6,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 5,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 4,
|
|
|
|
|
line = 5,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return vim.lsp.util.symbols_to_items(doc_syms, nil)
|
|
|
|
|
end)
|
2020-05-01 23:09:49 -07:00
|
|
|
|
)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-05-01 23:09:49 -07:00
|
|
|
|
it('DocumentSymbol has no children', function()
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
col = 1,
|
|
|
|
|
filename = '',
|
|
|
|
|
kind = 'File',
|
|
|
|
|
lnum = 2,
|
|
|
|
|
text = '[File] TestA',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
col = 1,
|
|
|
|
|
filename = '',
|
|
|
|
|
kind = 'Namespace',
|
|
|
|
|
lnum = 6,
|
|
|
|
|
text = '[Namespace] TestC',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
eq(
|
|
|
|
|
expected,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local doc_syms = {
|
|
|
|
|
{
|
|
|
|
|
deprecated = false,
|
|
|
|
|
detail = 'A',
|
|
|
|
|
kind = 1,
|
|
|
|
|
name = 'TestA',
|
|
|
|
|
range = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 1,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 2,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 1,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 4,
|
|
|
|
|
line = 1,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
{
|
|
|
|
|
deprecated = false,
|
|
|
|
|
detail = 'C',
|
|
|
|
|
kind = 3,
|
|
|
|
|
name = 'TestC',
|
|
|
|
|
range = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 5,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 6,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 5,
|
|
|
|
|
},
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 4,
|
|
|
|
|
line = 5,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return vim.lsp.util.symbols_to_items(doc_syms, nil)
|
|
|
|
|
end)
|
2020-05-01 23:09:49 -07:00
|
|
|
|
)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2020-06-11 17:34:34 -07:00
|
|
|
|
it('convert SymbolInformation[] to items', function()
|
2020-05-01 23:09:49 -07:00
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
col = 1,
|
2021-07-07 16:36:27 -07:00
|
|
|
|
filename = '/test_a',
|
2020-05-01 23:09:49 -07:00
|
|
|
|
kind = 'File',
|
|
|
|
|
lnum = 2,
|
|
|
|
|
text = '[File] TestA',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
col = 1,
|
2021-07-07 16:36:27 -07:00
|
|
|
|
filename = '/test_b',
|
2020-05-01 23:09:49 -07:00
|
|
|
|
kind = 'Module',
|
|
|
|
|
lnum = 4,
|
|
|
|
|
text = '[Module] TestB',
|
2024-01-02 18:09:18 -07:00
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
}
|
|
|
|
|
eq(
|
|
|
|
|
expected,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2020-05-01 23:09:49 -07:00
|
|
|
|
local sym_info = {
|
|
|
|
|
{
|
|
|
|
|
deprecated = false,
|
|
|
|
|
kind = 1,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
name = 'TestA',
|
2020-05-01 23:09:49 -07:00
|
|
|
|
location = {
|
|
|
|
|
range = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
line = 1,
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
['end'] = {
|
2020-05-01 23:09:49 -07:00
|
|
|
|
character = 0,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
line = 2,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
uri = 'file:///test_a',
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
containerName = 'TestAContainer',
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
deprecated = false,
|
|
|
|
|
kind = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
name = 'TestB',
|
2020-05-01 23:09:49 -07:00
|
|
|
|
location = {
|
|
|
|
|
range = {
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
line = 3,
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
['end'] = {
|
2020-05-01 23:09:49 -07:00
|
|
|
|
character = 0,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
line = 4,
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
uri = 'file:///test_b',
|
2020-05-01 23:09:49 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
containerName = 'TestBContainer',
|
|
|
|
|
},
|
2020-05-01 23:09:49 -07:00
|
|
|
|
}
|
|
|
|
|
return vim.lsp.util.symbols_to_items(sym_info, nil)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-05-01 23:09:49 -07:00
|
|
|
|
)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2020-05-07 13:23:25 -07:00
|
|
|
|
|
2020-05-18 23:51:10 -07:00
|
|
|
|
describe('lsp.util.jump_to_location', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local target_bufnr --- @type integer
|
2021-04-23 14:50:35 -07:00
|
|
|
|
|
2021-05-19 06:33:32 -07:00
|
|
|
|
before_each(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
target_bufnr = exec_lua(function()
|
|
|
|
|
local bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
|
|
|
|
local lines = { '1st line of text', 'å å ɧ 汉语 ↥ 🤦 🦄' }
|
2020-05-18 23:51:10 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
|
|
|
|
return bufnr
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-05-18 23:51:10 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2021-05-19 06:33:32 -07:00
|
|
|
|
local location = function(start_line, start_char, end_line, end_char)
|
2020-05-18 23:51:10 -07:00
|
|
|
|
return {
|
2021-07-07 16:36:27 -07:00
|
|
|
|
uri = 'file:///fake/uri',
|
2020-05-18 23:51:10 -07:00
|
|
|
|
range = {
|
|
|
|
|
start = { line = start_line, character = start_char },
|
|
|
|
|
['end'] = { line = end_line, character = end_char },
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
2021-05-19 06:33:32 -07:00
|
|
|
|
local jump = function(msg)
|
2022-01-13 03:34:04 -07:00
|
|
|
|
eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, 'utf-16'))
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(target_bufnr, fn.bufnr('%'))
|
2020-05-18 23:51:10 -07:00
|
|
|
|
return {
|
2024-04-02 06:45:19 -07:00
|
|
|
|
line = fn.line('.'),
|
|
|
|
|
col = fn.col('.'),
|
2020-05-18 23:51:10 -07:00
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it('jumps to a Location', function()
|
2021-05-19 06:33:32 -07:00
|
|
|
|
local pos = jump(location(0, 9, 0, 9))
|
2020-05-18 23:51:10 -07:00
|
|
|
|
eq(1, pos.line)
|
|
|
|
|
eq(10, pos.col)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('jumps to a LocationLink', function()
|
2021-05-19 06:33:32 -07:00
|
|
|
|
local pos = jump({
|
2021-07-07 16:36:27 -07:00
|
|
|
|
targetUri = 'file:///fake/uri',
|
2020-05-18 23:51:10 -07:00
|
|
|
|
targetSelectionRange = {
|
|
|
|
|
start = { line = 0, character = 4 },
|
|
|
|
|
['end'] = { line = 0, character = 4 },
|
|
|
|
|
},
|
|
|
|
|
targetRange = {
|
|
|
|
|
start = { line = 1, character = 5 },
|
|
|
|
|
['end'] = { line = 1, character = 5 },
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
eq(1, pos.line)
|
|
|
|
|
eq(5, pos.col)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('jumps to the correct multibyte column', function()
|
2021-05-19 06:33:32 -07:00
|
|
|
|
local pos = jump(location(1, 2, 1, 2))
|
2020-05-18 23:51:10 -07:00
|
|
|
|
eq(2, pos.line)
|
|
|
|
|
eq(4, pos.col)
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq('å', fn.expand('<cword>'))
|
2020-05-18 23:51:10 -07:00
|
|
|
|
end)
|
2021-04-23 14:50:35 -07:00
|
|
|
|
|
2021-05-06 14:51:25 -07:00
|
|
|
|
it('adds current position to jumplist before jumping', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
|
|
|
|
local mark = api.nvim_buf_get_mark(target_bufnr, "'")
|
2021-05-19 06:35:30 -07:00
|
|
|
|
eq({ 1, 0 }, mark)
|
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 3 })
|
2021-05-19 06:35:30 -07:00
|
|
|
|
jump(location(0, 9, 0, 9))
|
2021-05-06 14:51:25 -07:00
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
mark = api.nvim_buf_get_mark(target_bufnr, "'")
|
2021-05-19 06:35:30 -07:00
|
|
|
|
eq({ 2, 3 }, mark)
|
2021-05-06 14:51:25 -07:00
|
|
|
|
end)
|
2020-05-18 23:51:10 -07:00
|
|
|
|
end)
|
2020-06-04 11:23:03 -07:00
|
|
|
|
|
2022-10-08 01:22:25 -07:00
|
|
|
|
describe('lsp.util.show_document', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local target_bufnr --- @type integer
|
|
|
|
|
local target_bufnr2 --- @type integer
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
before_each(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
target_bufnr = exec_lua(function()
|
|
|
|
|
local bufnr = vim.uri_to_bufnr('file:///fake/uri')
|
|
|
|
|
local lines = { '1st line of text', 'å å ɧ 汉语 ↥ 🤦 🦄' }
|
2022-10-08 01:22:25 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
|
|
|
|
return bufnr
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
target_bufnr2 = exec_lua(function()
|
|
|
|
|
local bufnr = vim.uri_to_bufnr('file:///fake/uri2')
|
|
|
|
|
local lines = { '1st line of text', 'å å ɧ 汉语 ↥ 🤦 🦄' }
|
2022-10-08 01:22:25 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
|
|
|
|
|
return bufnr
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
local location = function(start_line, start_char, end_line, end_char, second_uri)
|
|
|
|
|
return {
|
|
|
|
|
uri = second_uri and 'file:///fake/uri2' or 'file:///fake/uri',
|
|
|
|
|
range = {
|
|
|
|
|
start = { line = start_line, character = start_char },
|
|
|
|
|
['end'] = { line = end_line, character = end_char },
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local show_document = function(msg, focus, reuse_win)
|
|
|
|
|
eq(
|
|
|
|
|
true,
|
|
|
|
|
exec_lua(
|
|
|
|
|
'return vim.lsp.util.show_document(...)',
|
|
|
|
|
msg,
|
|
|
|
|
'utf-16',
|
|
|
|
|
{ reuse_win = reuse_win, focus = focus }
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
if focus == true or focus == nil then
|
2024-04-02 06:45:19 -07:00
|
|
|
|
eq(target_bufnr, fn.bufnr('%'))
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end
|
|
|
|
|
return {
|
2024-04-02 06:45:19 -07:00
|
|
|
|
line = fn.line('.'),
|
|
|
|
|
col = fn.col('.'),
|
2022-10-08 01:22:25 -07:00
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
it('jumps to a Location if focus is true', function()
|
|
|
|
|
local pos = show_document(location(0, 9, 0, 9), true, true)
|
|
|
|
|
eq(1, pos.line)
|
|
|
|
|
eq(10, pos.col)
|
|
|
|
|
end)
|
|
|
|
|
|
2022-12-04 07:57:46 -07:00
|
|
|
|
it('jumps to a Location if focus is true via handler', function()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local server = _G._create_server()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd }))
|
2022-12-04 07:57:46 -07:00
|
|
|
|
local result = {
|
|
|
|
|
uri = 'file:///fake/uri',
|
|
|
|
|
selection = {
|
|
|
|
|
start = { line = 0, character = 9 },
|
2024-07-29 03:20:15 -07:00
|
|
|
|
['end'] = { line = 0, character = 9 },
|
2022-12-04 07:57:46 -07:00
|
|
|
|
},
|
|
|
|
|
takeFocus = true,
|
|
|
|
|
}
|
|
|
|
|
local ctx = {
|
|
|
|
|
client_id = client_id,
|
|
|
|
|
method = 'window/showDocument',
|
|
|
|
|
}
|
|
|
|
|
vim.lsp.handlers['window/showDocument'](nil, result, ctx)
|
|
|
|
|
vim.lsp.stop_client(client_id)
|
|
|
|
|
return {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
cursor = vim.api.nvim_win_get_cursor(0),
|
2022-12-04 07:57:46 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-12-04 07:57:46 -07:00
|
|
|
|
eq(1, result.cursor[1])
|
|
|
|
|
eq(9, result.cursor[2])
|
|
|
|
|
end)
|
|
|
|
|
|
2022-10-08 01:22:25 -07:00
|
|
|
|
it('jumps to a Location if focus not set', function()
|
|
|
|
|
local pos = show_document(location(0, 9, 0, 9), nil, true)
|
|
|
|
|
eq(1, pos.line)
|
|
|
|
|
eq(10, pos.col)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('does not add current position to jumplist if not focus', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
|
|
|
|
local mark = api.nvim_buf_get_mark(target_bufnr, "'")
|
2022-10-08 01:22:25 -07:00
|
|
|
|
eq({ 1, 0 }, mark)
|
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 3 })
|
2022-10-08 01:22:25 -07:00
|
|
|
|
show_document(location(0, 9, 0, 9), false, true)
|
|
|
|
|
show_document(location(0, 9, 0, 9, true), false, true)
|
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
mark = api.nvim_buf_get_mark(target_bufnr, "'")
|
2022-10-08 01:22:25 -07:00
|
|
|
|
eq({ 1, 0 }, mark)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('does not change cursor position if not focus and not reuse_win', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
|
|
|
|
local cursor = api.nvim_win_get_cursor(0)
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
show_document(location(0, 9, 0, 9), false, false)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq(cursor, api.nvim_win_get_cursor(0))
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('does not change window if not focus', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
|
|
|
|
local win = api.nvim_get_current_win()
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
-- same document/bufnr
|
|
|
|
|
show_document(location(0, 9, 0, 9), false, true)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq(win, api.nvim_get_current_win())
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
-- different document/bufnr, new window/split
|
|
|
|
|
show_document(location(0, 9, 0, 9, true), false, true)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq(2, #api.nvim_list_wins())
|
|
|
|
|
eq(win, api.nvim_get_current_win())
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it("respects 'reuse_win' parameter", function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
-- does not create a new window if the buffer is already open
|
|
|
|
|
show_document(location(0, 9, 0, 9), false, true)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq(1, #api.nvim_list_wins())
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
-- creates a new window even if the buffer is already open
|
|
|
|
|
show_document(location(0, 9, 0, 9), false, false)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq(2, #api.nvim_list_wins())
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('correctly sets the cursor of the split if range is given without focus', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
show_document(location(0, 9, 0, 9, true), false, true)
|
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local wins = api.nvim_list_wins()
|
2022-10-08 01:22:25 -07:00
|
|
|
|
eq(2, #wins)
|
|
|
|
|
table.sort(wins)
|
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 1, 0 }, api.nvim_win_get_cursor(wins[1]))
|
|
|
|
|
eq({ 1, 9 }, api.nvim_win_get_cursor(wins[2]))
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('does not change cursor of the split if not range and not focus', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 3 })
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.cmd.new()
|
|
|
|
|
end)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr2)
|
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 3 })
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
show_document({ uri = 'file:///fake/uri2' }, false, true)
|
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local wins = api.nvim_list_wins()
|
2022-10-08 01:22:25 -07:00
|
|
|
|
eq(2, #wins)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 2, 3 }, api.nvim_win_get_cursor(wins[1]))
|
|
|
|
|
eq({ 2, 3 }, api.nvim_win_get_cursor(wins[2]))
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('respects existing buffers', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr)
|
|
|
|
|
local win = api.nvim_get_current_win()
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.cmd.new()
|
|
|
|
|
end)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_win_set_buf(0, target_bufnr2)
|
|
|
|
|
api.nvim_win_set_cursor(0, { 2, 3 })
|
|
|
|
|
local split = api.nvim_get_current_win()
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
-- reuse win for open document/bufnr if called from split
|
|
|
|
|
show_document(location(0, 9, 0, 9, true), false, true)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 1, 9 }, api.nvim_win_get_cursor(split))
|
|
|
|
|
eq(2, #api.nvim_list_wins())
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
2024-03-25 12:06:28 -07:00
|
|
|
|
api.nvim_set_current_win(win)
|
2022-10-08 01:22:25 -07:00
|
|
|
|
|
|
|
|
|
-- reuse win for open document/bufnr if called outside the split
|
|
|
|
|
show_document(location(0, 9, 0, 9, true), false, true)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
eq({ 1, 9 }, api.nvim_win_get_cursor(split))
|
|
|
|
|
eq(2, #api.nvim_list_wins())
|
2022-10-08 01:22:25 -07:00
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2020-06-04 11:23:03 -07:00
|
|
|
|
describe('lsp.util._make_floating_popup_size', function()
|
2020-06-11 17:34:34 -07:00
|
|
|
|
before_each(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.contents = { 'text tαxt txtα tex', 'text tααt tααt text', 'text tαxt tαxt' }
|
|
|
|
|
end)
|
2020-06-11 17:34:34 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('calculates size correctly', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
eq(
|
|
|
|
|
{ 19, 3 },
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return { vim.lsp.util._make_floating_popup_size(_G.contents) }
|
|
|
|
|
end)
|
|
|
|
|
)
|
2020-06-11 17:34:34 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('calculates size correctly with wrapping', function()
|
|
|
|
|
eq(
|
|
|
|
|
{ 15, 5 },
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
return {
|
|
|
|
|
vim.lsp.util._make_floating_popup_size(_G.contents, { width = 15, wrap_at = 14 }),
|
|
|
|
|
}
|
|
|
|
|
end)
|
2020-06-11 17:34:34 -07:00
|
|
|
|
)
|
|
|
|
|
end)
|
2023-10-12 00:39:39 -07:00
|
|
|
|
|
|
|
|
|
it('handles NUL bytes in text', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.contents = {
|
|
|
|
|
'\000\001\002\003\004\005\006\007\008\009',
|
|
|
|
|
'\010\011\012\013\014\015\016\017\018\019',
|
|
|
|
|
'\020\021\022\023\024\025\026\027\028\029',
|
|
|
|
|
}
|
|
|
|
|
end)
|
2023-10-12 00:39:39 -07:00
|
|
|
|
command('set list listchars=')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
eq(
|
|
|
|
|
{ 20, 3 },
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return { vim.lsp.util._make_floating_popup_size(_G.contents) }
|
|
|
|
|
end)
|
|
|
|
|
)
|
2023-10-12 00:39:39 -07:00
|
|
|
|
command('set display+=uhex')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
eq(
|
|
|
|
|
{ 40, 3 },
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return { vim.lsp.util._make_floating_popup_size(_G.contents) }
|
|
|
|
|
end)
|
|
|
|
|
)
|
2023-10-12 00:39:39 -07:00
|
|
|
|
end)
|
2020-06-04 11:23:03 -07:00
|
|
|
|
end)
|
2020-05-05 08:23:45 -07:00
|
|
|
|
|
2021-08-10 11:52:30 -07:00
|
|
|
|
describe('lsp.util.trim.trim_empty_lines', function()
|
|
|
|
|
it('properly trims empty lines', function()
|
|
|
|
|
eq(
|
|
|
|
|
{ { 'foo', 'bar' } },
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
--- @diagnostic disable-next-line:deprecated
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return vim.lsp.util.trim_empty_lines({ { 'foo', 'bar' }, nil })
|
|
|
|
|
end)
|
2021-08-10 11:52:30 -07:00
|
|
|
|
)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2022-01-13 02:47:36 -07:00
|
|
|
|
describe('lsp.util.convert_signature_help_to_markdown_lines', function()
|
|
|
|
|
it('can handle negative activeSignature', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
2022-01-13 02:47:36 -07:00
|
|
|
|
local signature_help = {
|
|
|
|
|
activeParameter = 0,
|
|
|
|
|
activeSignature = -1,
|
|
|
|
|
signatures = {
|
|
|
|
|
{
|
2024-07-29 03:20:15 -07:00
|
|
|
|
documentation = 'some doc',
|
|
|
|
|
label = 'TestEntity.TestEntity()',
|
|
|
|
|
parameters = {},
|
2022-01-13 02:47:36 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2022-01-13 02:47:36 -07:00
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return vim.lsp.util.convert_signature_help_to_markdown_lines(signature_help, 'cs', { ',' })
|
|
|
|
|
end)
|
2023-09-12 20:51:21 -07:00
|
|
|
|
local expected = { '```cs', 'TestEntity.TestEntity()', '```', 'some doc' }
|
2022-01-13 02:47:36 -07:00
|
|
|
|
eq(expected, result)
|
|
|
|
|
end)
|
2024-10-15 02:36:04 -07:00
|
|
|
|
|
|
|
|
|
it('highlights active parameters in multiline signature labels', function()
|
|
|
|
|
local _, hl = exec_lua(function()
|
|
|
|
|
local signature_help = {
|
|
|
|
|
activeSignature = 0,
|
|
|
|
|
signatures = {
|
|
|
|
|
{
|
|
|
|
|
activeParameter = 1,
|
|
|
|
|
label = 'fn bar(\n _: void,\n _: void,\n) void',
|
|
|
|
|
parameters = {
|
|
|
|
|
{ label = '_: void' },
|
|
|
|
|
{ label = '_: void' },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
return vim.lsp.util.convert_signature_help_to_markdown_lines(signature_help, 'zig', { '(' })
|
|
|
|
|
end)
|
2024-11-20 15:50:30 -07:00
|
|
|
|
-- Note that although the highlight positions below are 0-indexed, the 2nd parameter
|
2024-10-15 02:36:04 -07:00
|
|
|
|
-- corresponds to the 3rd line because the first line is the ``` from the
|
|
|
|
|
-- Markdown block.
|
|
|
|
|
local expected = { 3, 4, 3, 11 }
|
|
|
|
|
eq(expected, hl)
|
|
|
|
|
end)
|
2022-01-13 02:47:36 -07:00
|
|
|
|
end)
|
|
|
|
|
|
2020-05-05 08:23:45 -07:00
|
|
|
|
describe('lsp.util.get_effective_tabstop', function()
|
2022-03-20 10:41:46 -07:00
|
|
|
|
local function test_tabstop(tabsize, shiftwidth)
|
2020-05-05 08:23:45 -07:00
|
|
|
|
exec_lua(string.format(
|
|
|
|
|
[[
|
2022-12-19 09:37:45 -07:00
|
|
|
|
vim.bo.shiftwidth = %d
|
|
|
|
|
vim.bo.tabstop = 2
|
2022-03-20 10:41:46 -07:00
|
|
|
|
]],
|
|
|
|
|
shiftwidth
|
|
|
|
|
))
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
tabsize,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp.util.get_effective_tabstop()
|
|
|
|
|
end)
|
|
|
|
|
)
|
2020-05-05 08:23:45 -07:00
|
|
|
|
end
|
|
|
|
|
|
2022-03-20 10:41:46 -07:00
|
|
|
|
it('with shiftwidth = 1', function()
|
|
|
|
|
test_tabstop(1, 1)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-03-20 10:41:46 -07:00
|
|
|
|
it('with shiftwidth = 0', function()
|
|
|
|
|
test_tabstop(2, 0)
|
|
|
|
|
end)
|
2020-05-05 08:23:45 -07:00
|
|
|
|
end)
|
2020-07-18 12:10:09 -07:00
|
|
|
|
|
|
|
|
|
describe('vim.lsp.buf.outgoing_calls', function()
|
|
|
|
|
it('does nothing for an empty response', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist_count = exec_lua(function()
|
|
|
|
|
require 'vim.lsp.handlers'['callHierarchy/outgoingCalls'](nil, nil, {}, nil)
|
2020-07-18 12:10:09 -07:00
|
|
|
|
return #vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-07-18 12:10:09 -07:00
|
|
|
|
eq(0, qflist_count)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('opens the quickfix list with the right caller', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist = exec_lua(function()
|
|
|
|
|
local rust_analyzer_response = {
|
|
|
|
|
{
|
|
|
|
|
fromRanges = {
|
|
|
|
|
{
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 7,
|
|
|
|
|
line = 3,
|
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 4,
|
|
|
|
|
line = 3,
|
|
|
|
|
},
|
2020-07-18 12:10:09 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
to = {
|
|
|
|
|
detail = 'fn foo()',
|
|
|
|
|
kind = 12,
|
|
|
|
|
name = 'foo',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 11,
|
|
|
|
|
line = 0,
|
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 0,
|
|
|
|
|
},
|
2020-07-18 12:10:09 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 6,
|
|
|
|
|
line = 0,
|
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 3,
|
|
|
|
|
line = 0,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
uri = 'file:///src/main.rs',
|
2020-07-18 12:10:09 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
local handler = require 'vim.lsp.handlers'['callHierarchy/outgoingCalls']
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
handler(nil, rust_analyzer_response, {})
|
2020-07-18 12:10:09 -07:00
|
|
|
|
return vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-07-18 12:10:09 -07:00
|
|
|
|
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 5,
|
2021-07-31 13:49:25 -07:00
|
|
|
|
end_col = 0,
|
2020-07-18 12:10:09 -07:00
|
|
|
|
lnum = 4,
|
2021-07-31 13:49:25 -07:00
|
|
|
|
end_lnum = 0,
|
2020-07-18 12:10:09 -07:00
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'foo',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eq(expected, qflist)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
describe('vim.lsp.buf.incoming_calls', function()
|
|
|
|
|
it('does nothing for an empty response', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist_count = exec_lua(function()
|
|
|
|
|
require 'vim.lsp.handlers'['callHierarchy/incomingCalls'](nil, nil, {})
|
2020-07-18 12:10:09 -07:00
|
|
|
|
return #vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-07-18 12:10:09 -07:00
|
|
|
|
eq(0, qflist_count)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('opens the quickfix list with the right callee', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist = exec_lua(function()
|
|
|
|
|
local rust_analyzer_response = {
|
|
|
|
|
{
|
|
|
|
|
from = {
|
|
|
|
|
detail = 'fn main()',
|
|
|
|
|
kind = 12,
|
|
|
|
|
name = 'main',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 1,
|
|
|
|
|
line = 4,
|
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 0,
|
|
|
|
|
line = 2,
|
|
|
|
|
},
|
2020-07-18 12:10:09 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 7,
|
|
|
|
|
line = 2,
|
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 3,
|
|
|
|
|
line = 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
uri = 'file:///src/main.rs',
|
2020-07-18 12:10:09 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
fromRanges = {
|
|
|
|
|
{
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 7,
|
|
|
|
|
line = 3,
|
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 4,
|
|
|
|
|
line = 3,
|
|
|
|
|
},
|
2020-07-18 12:10:09 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
}
|
2020-07-18 12:10:09 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local handler = require 'vim.lsp.handlers'['callHierarchy/incomingCalls']
|
feat(lsp)!: change handler signature
Previously, the handler signature was:
function(err, method, params, client_id, bufnr, config)
In order to better support external plugins that wish to extend the
protocol, there is other information which would be advantageous to
forward to the client, such as the original params of the request that
generated the callback.
In order to do this, we would need to break symmetry of the handlers, to
add an additional "params" as the 7th argument.
Instead, this PR changes the signature of the handlers to:
function(err, result, ctx, config)
where ctx (the context) includes params, client_id, and bufnr. This also leaves
flexibility for future use-cases.
BREAKING_CHANGE: changes the signature of the built-in client handlers, requiring
updating handler calls
2021-08-27 21:12:30 -07:00
|
|
|
|
handler(nil, rust_analyzer_response, {})
|
2020-07-18 12:10:09 -07:00
|
|
|
|
return vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2020-07-18 12:10:09 -07:00
|
|
|
|
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 5,
|
2021-07-31 13:49:25 -07:00
|
|
|
|
end_col = 0,
|
2020-07-18 12:10:09 -07:00
|
|
|
|
lnum = 4,
|
2021-07-31 13:49:25 -07:00
|
|
|
|
end_lnum = 0,
|
2020-07-18 12:10:09 -07:00
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'main',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eq(expected, qflist)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2021-09-08 08:00:15 -07:00
|
|
|
|
|
2024-04-23 10:05:01 -07:00
|
|
|
|
describe('vim.lsp.buf.typehierarchy subtypes', function()
|
2024-04-20 06:40:01 -07:00
|
|
|
|
it('does nothing for an empty response', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist_count = exec_lua(function()
|
|
|
|
|
require 'vim.lsp.handlers'['typeHierarchy/subtypes'](nil, nil, {})
|
2024-04-20 06:40:01 -07:00
|
|
|
|
return #vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-04-20 06:40:01 -07:00
|
|
|
|
eq(0, qflist_count)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('opens the quickfix list with the right subtypes', function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist = exec_lua(function()
|
|
|
|
|
local clangd_response = {
|
|
|
|
|
{
|
|
|
|
|
data = {
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {},
|
|
|
|
|
symbolID = '62B3D268A01B9978',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'DC9B0AD433B43BEC',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = '06B5F6A19BA9F6A8',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'EDC336589C09ABB2',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'D2',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
{
|
|
|
|
|
data = {
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {},
|
|
|
|
|
symbolID = '62B3D268A01B9978',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'DC9B0AD433B43BEC',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = '06B5F6A19BA9F6A8',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'AFFCAED15557EF08',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'D1',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
}
|
2024-04-20 06:40:01 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server({
|
2024-04-20 06:40:01 -07:00
|
|
|
|
capabilities = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
positionEncoding = 'utf-8',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/subtypes']
|
2024-09-08 03:44:46 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
|
|
|
|
'class B : public A{};',
|
|
|
|
|
'class C : public B{};',
|
|
|
|
|
'class D1 : public C{};',
|
|
|
|
|
'class D2 : public C{};',
|
|
|
|
|
'class E : public D1, D2 {};',
|
|
|
|
|
})
|
|
|
|
|
handler(nil, clangd_response, { client_id = client_id, bufnr = bufnr })
|
2024-04-20 06:40:01 -07:00
|
|
|
|
return vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-04-20 06:40:01 -07:00
|
|
|
|
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 7,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
lnum = 4,
|
2024-04-20 06:40:01 -07:00
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'D2',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 7,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
lnum = 3,
|
2024-04-20 06:40:01 -07:00
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'D1',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eq(expected, qflist)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('opens the quickfix list with the right subtypes and details', function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist = exec_lua(function()
|
2024-04-20 06:40:01 -07:00
|
|
|
|
local jdtls_response = {
|
|
|
|
|
{
|
|
|
|
|
data = { element = '=hello-java_ed323c3c/_<{Main.java[Main[A' },
|
|
|
|
|
detail = '',
|
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'A',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = { character = 26, line = 3 },
|
|
|
|
|
start = { character = 1, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = { character = 8, line = 3 },
|
|
|
|
|
start = { character = 7, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
tags = {},
|
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello-java/Main.java',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
data = { element = '=hello-java_ed323c3c/_<mylist{MyList.java[MyList[Inner' },
|
|
|
|
|
detail = 'mylist',
|
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'MyList$Inner',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = { character = 37, line = 3 },
|
|
|
|
|
start = { character = 1, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = { character = 19, line = 3 },
|
|
|
|
|
start = { character = 14, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
tags = {},
|
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello-java/mylist/MyList.java',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server({
|
2024-04-20 06:40:01 -07:00
|
|
|
|
capabilities = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
positionEncoding = 'utf-8',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/subtypes']
|
2024-09-08 03:44:46 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
|
|
|
|
'package mylist;',
|
|
|
|
|
'',
|
|
|
|
|
'public class MyList {',
|
|
|
|
|
' static class Inner extends MyList{}',
|
|
|
|
|
'~}',
|
|
|
|
|
})
|
|
|
|
|
handler(nil, jdtls_response, { client_id = client_id, bufnr = bufnr })
|
2024-04-20 06:40:01 -07:00
|
|
|
|
return vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-04-20 06:40:01 -07:00
|
|
|
|
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 2,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
|
|
|
|
lnum = 4,
|
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'A',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
bufnr = 3,
|
|
|
|
|
col = 2,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
|
|
|
|
lnum = 4,
|
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'MyList$Inner mylist',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
eq(expected, qflist)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2024-04-23 10:05:01 -07:00
|
|
|
|
describe('vim.lsp.buf.typehierarchy supertypes', function()
|
2024-04-20 06:40:01 -07:00
|
|
|
|
it('does nothing for an empty response', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist_count = exec_lua(function()
|
|
|
|
|
require 'vim.lsp.handlers'['typeHierarchy/supertypes'](nil, nil, {})
|
2024-04-20 06:40:01 -07:00
|
|
|
|
return #vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-04-20 06:40:01 -07:00
|
|
|
|
eq(0, qflist_count)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('opens the quickfix list with the right supertypes', function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist = exec_lua(function()
|
|
|
|
|
local clangd_response = {
|
|
|
|
|
{
|
|
|
|
|
data = {
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {},
|
|
|
|
|
symbolID = '62B3D268A01B9978',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'DC9B0AD433B43BEC',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = '06B5F6A19BA9F6A8',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'EDC336589C09ABB2',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'D2',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 3,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
{
|
|
|
|
|
data = {
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {
|
|
|
|
|
{
|
|
|
|
|
parents = {},
|
|
|
|
|
symbolID = '62B3D268A01B9978',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'DC9B0AD433B43BEC',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = '06B5F6A19BA9F6A8',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
symbolID = 'AFFCAED15557EF08',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'D1',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = {
|
|
|
|
|
character = 8,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
start = {
|
|
|
|
|
character = 6,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
line = 2,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello.cpp',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
}
|
2024-04-20 06:40:01 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server({
|
2024-04-20 06:40:01 -07:00
|
|
|
|
capabilities = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
positionEncoding = 'utf-8',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/supertypes']
|
2024-09-08 03:44:46 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
|
|
|
|
'class B : public A{};',
|
|
|
|
|
'class C : public B{};',
|
|
|
|
|
'class D1 : public C{};',
|
|
|
|
|
'class D2 : public C{};',
|
|
|
|
|
'class E : public D1, D2 {};',
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
handler(nil, clangd_response, { client_id = client_id, bufnr = bufnr })
|
2024-04-20 06:40:01 -07:00
|
|
|
|
return vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-04-20 06:40:01 -07:00
|
|
|
|
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 7,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
lnum = 4,
|
2024-04-20 06:40:01 -07:00
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'D2',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 7,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
2024-09-08 03:44:46 -07:00
|
|
|
|
lnum = 3,
|
2024-04-20 06:40:01 -07:00
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'D1',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eq(expected, qflist)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('opens the quickfix list with the right supertypes and details', function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local qflist = exec_lua(function()
|
2024-04-20 06:40:01 -07:00
|
|
|
|
local jdtls_response = {
|
|
|
|
|
{
|
|
|
|
|
data = { element = '=hello-java_ed323c3c/_<{Main.java[Main[A' },
|
|
|
|
|
detail = '',
|
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'A',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = { character = 26, line = 3 },
|
|
|
|
|
start = { character = 1, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = { character = 8, line = 3 },
|
|
|
|
|
start = { character = 7, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
tags = {},
|
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello-java/Main.java',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
data = { element = '=hello-java_ed323c3c/_<mylist{MyList.java[MyList[Inner' },
|
|
|
|
|
detail = 'mylist',
|
|
|
|
|
kind = 5,
|
|
|
|
|
name = 'MyList$Inner',
|
|
|
|
|
range = {
|
|
|
|
|
['end'] = { character = 37, line = 3 },
|
|
|
|
|
start = { character = 1, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
selectionRange = {
|
|
|
|
|
['end'] = { character = 19, line = 3 },
|
|
|
|
|
start = { character = 14, line = 3 },
|
|
|
|
|
},
|
|
|
|
|
tags = {},
|
|
|
|
|
uri = 'file:///home/jiangyinzuo/hello-java/mylist/MyList.java',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server({
|
2024-04-20 06:40:01 -07:00
|
|
|
|
capabilities = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
positionEncoding = 'utf-8',
|
2024-04-20 06:40:01 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local handler = require 'vim.lsp.handlers'['typeHierarchy/supertypes']
|
2024-09-08 03:44:46 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {
|
|
|
|
|
'package mylist;',
|
|
|
|
|
'',
|
|
|
|
|
'public class MyList {',
|
|
|
|
|
' static class Inner extends MyList{}',
|
|
|
|
|
'~}',
|
|
|
|
|
})
|
|
|
|
|
handler(nil, jdtls_response, { client_id = client_id, bufnr = bufnr })
|
2024-04-20 06:40:01 -07:00
|
|
|
|
return vim.fn.getqflist()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-04-20 06:40:01 -07:00
|
|
|
|
|
|
|
|
|
local expected = {
|
|
|
|
|
{
|
|
|
|
|
bufnr = 2,
|
|
|
|
|
col = 2,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
|
|
|
|
lnum = 4,
|
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'A',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
bufnr = 3,
|
|
|
|
|
col = 2,
|
|
|
|
|
end_col = 0,
|
|
|
|
|
end_lnum = 0,
|
|
|
|
|
lnum = 4,
|
|
|
|
|
module = '',
|
|
|
|
|
nr = 0,
|
|
|
|
|
pattern = '',
|
|
|
|
|
text = 'MyList$Inner mylist',
|
|
|
|
|
type = '',
|
|
|
|
|
valid = 1,
|
|
|
|
|
vcol = 0,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
eq(expected, qflist)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2021-09-08 08:00:15 -07:00
|
|
|
|
describe('vim.lsp.buf.rename', function()
|
|
|
|
|
for _, test in ipairs({
|
|
|
|
|
{
|
|
|
|
|
it = 'does not attempt to rename on nil response',
|
|
|
|
|
name = 'prepare_rename_nil',
|
|
|
|
|
expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
it = 'handles prepareRename placeholder response',
|
|
|
|
|
name = 'prepare_rename_placeholder',
|
|
|
|
|
expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, NIL, { method = 'textDocument/rename', client_id = 1, bufnr = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
},
|
|
|
|
|
expected_text = 'placeholder', -- see fake lsp response
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
it = 'handles range response',
|
|
|
|
|
name = 'prepare_rename_range',
|
|
|
|
|
expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, NIL, { method = 'textDocument/rename', client_id = 1, bufnr = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
},
|
|
|
|
|
expected_text = 'line', -- see test case and fake lsp response
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
it = 'handles error',
|
|
|
|
|
name = 'prepare_rename_error',
|
|
|
|
|
expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}) do
|
|
|
|
|
it(test.it, function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-09-08 08:00:15 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = test.name,
|
|
|
|
|
on_init = function(_client)
|
|
|
|
|
client = _client
|
2022-04-30 02:22:30 -07:00
|
|
|
|
eq(true, client.server_capabilities().renameProvider.prepareProvider)
|
2021-09-08 08:00:15 -07:00
|
|
|
|
end,
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
vim.lsp._stubs = {}
|
2024-08-11 01:27:48 -07:00
|
|
|
|
--- @diagnostic disable-next-line:duplicate-set-field
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.fn.input = function(opts, _)
|
|
|
|
|
vim.lsp._stubs.input_prompt = opts.prompt
|
|
|
|
|
vim.lsp._stubs.input_text = opts.default
|
|
|
|
|
return 'renameto' -- expect this value in fake lsp
|
|
|
|
|
end
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { '', 'this is line two' })
|
|
|
|
|
vim.fn.cursor(2, 13) -- the space between "line" and "two"
|
|
|
|
|
end)
|
2021-09-08 08:00:15 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-09-08 08:00:15 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
2023-06-11 02:53:37 -07:00
|
|
|
|
-- Don't compare & assert params and version, they're not relevant for the testcase
|
2021-03-11 15:49:59 -07:00
|
|
|
|
-- This allows us to be lazy and avoid declaring them
|
|
|
|
|
ctx.params = nil
|
2023-06-11 02:53:37 -07:00
|
|
|
|
ctx.version = nil
|
2024-01-02 18:09:18 -07:00
|
|
|
|
|
2021-09-08 08:00:15 -07:00
|
|
|
|
eq(table.remove(test.expected_handlers), { err, result, ctx }, 'expected handler')
|
|
|
|
|
if ctx.method == 'start' then
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.buf.rename()
|
|
|
|
|
end)
|
2021-09-08 08:00:15 -07:00
|
|
|
|
end
|
|
|
|
|
if ctx.method == 'shutdown' then
|
|
|
|
|
if test.expected_text then
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
'New Name: ',
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp._stubs.input_prompt
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
eq(
|
|
|
|
|
test.expected_text,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return vim.lsp._stubs.input_text
|
|
|
|
|
end)
|
|
|
|
|
)
|
2024-01-02 18:09:18 -07:00
|
|
|
|
end
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-09-08 08:00:15 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
end
|
|
|
|
|
end)
|
|
|
|
|
|
2021-03-12 02:19:21 -07:00
|
|
|
|
describe('vim.lsp.buf.code_action', function()
|
|
|
|
|
it('Calls client side command if available', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-09-28 14:04:01 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'code_action_with_resolve',
|
|
|
|
|
on_init = function(client_)
|
|
|
|
|
client = client_
|
|
|
|
|
end,
|
|
|
|
|
on_setup = function() end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-09-28 14:04:01 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx })
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.commands['dummy1'] = function(_)
|
|
|
|
|
vim.lsp.commands['dummy2'] = function() end
|
2021-09-28 14:04:01 -07:00
|
|
|
|
end
|
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
--- @diagnostic disable-next-line:duplicate-set-field
|
2021-09-28 14:04:01 -07:00
|
|
|
|
vim.fn.inputlist = function()
|
|
|
|
|
return 1
|
|
|
|
|
end
|
|
|
|
|
vim.lsp.buf.code_action()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2021-09-28 14:04:01 -07:00
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
eq(
|
|
|
|
|
'function',
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return type(vim.lsp.commands['dummy2'])
|
|
|
|
|
end)
|
|
|
|
|
)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-09-28 14:04:01 -07:00
|
|
|
|
end
|
2021-03-12 02:19:21 -07:00
|
|
|
|
end,
|
2021-09-28 14:04:01 -07:00
|
|
|
|
}
|
2021-03-12 02:19:21 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-06-05 07:43:32 -07:00
|
|
|
|
it('Calls workspace/executeCommand if no client side command', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-06-05 07:43:32 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{
|
|
|
|
|
NIL,
|
|
|
|
|
{ command = 'dummy1', title = 'Command 1' },
|
|
|
|
|
{ bufnr = 1, method = 'workspace/executeCommand', client_id = 1 },
|
|
|
|
|
},
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
|
|
|
|
test_rpc_server({
|
|
|
|
|
test_name = 'code_action_server_side_command',
|
|
|
|
|
on_init = function(client_)
|
|
|
|
|
client = client_
|
|
|
|
|
end,
|
|
|
|
|
on_setup = function() end,
|
|
|
|
|
on_exit = function(code, signal)
|
|
|
|
|
eq(0, code, 'exit code', fake_lsp_logfile)
|
|
|
|
|
eq(0, signal, 'exit signal', fake_lsp_logfile)
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
ctx.params = nil -- don't compare in assert
|
2023-06-11 02:53:37 -07:00
|
|
|
|
ctx.version = nil
|
2022-06-05 07:43:32 -07:00
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx })
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2022-06-05 07:43:32 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2022-06-05 07:43:32 -07:00
|
|
|
|
vim.fn.inputlist = function()
|
|
|
|
|
return 1
|
|
|
|
|
end
|
|
|
|
|
vim.lsp.buf.code_action()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-06-05 07:43:32 -07:00
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-06-05 07:43:32 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-04-30 01:14:31 -07:00
|
|
|
|
it('Filters and automatically applies action if requested', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-04-30 01:14:31 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'code_action_filter',
|
|
|
|
|
on_init = function(client_)
|
|
|
|
|
client = client_
|
|
|
|
|
end,
|
|
|
|
|
on_setup = function() end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2022-04-30 01:14:31 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx })
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.commands['preferred_command'] = function(_)
|
|
|
|
|
vim.lsp.commands['executed_preferred'] = function() end
|
2022-04-30 01:14:31 -07:00
|
|
|
|
end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.commands['type_annotate_command'] = function(_)
|
|
|
|
|
vim.lsp.commands['executed_type_annotate'] = function() end
|
2022-05-12 09:48:02 -07:00
|
|
|
|
end
|
2022-04-30 01:14:31 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2022-05-12 09:48:02 -07:00
|
|
|
|
vim.lsp.buf.code_action({
|
2024-07-29 03:20:15 -07:00
|
|
|
|
filter = function(a)
|
|
|
|
|
return a.isPreferred
|
|
|
|
|
end,
|
|
|
|
|
apply = true,
|
2022-05-12 09:48:02 -07:00
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf.code_action({
|
|
|
|
|
-- expect to be returned actions 'type-annotate' and 'type-annotate.foo'
|
|
|
|
|
context = { only = { 'type-annotate' } },
|
|
|
|
|
apply = true,
|
|
|
|
|
filter = function(a)
|
|
|
|
|
if a.kind == 'type-annotate.foo' then
|
|
|
|
|
vim.lsp.commands['filtered_type_annotate_foo'] = function() end
|
|
|
|
|
return false
|
|
|
|
|
elseif a.kind == 'type-annotate' then
|
|
|
|
|
return true
|
|
|
|
|
else
|
|
|
|
|
assert(nil, 'unreachable')
|
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
end)
|
2022-04-30 01:14:31 -07:00
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
eq(
|
|
|
|
|
'function',
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return type(vim.lsp.commands['executed_preferred'])
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
eq(
|
|
|
|
|
'function',
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return type(vim.lsp.commands['filtered_type_annotate_foo'])
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
eq(
|
|
|
|
|
'function',
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return type(vim.lsp.commands['executed_type_annotate'])
|
|
|
|
|
end)
|
|
|
|
|
)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-04-30 01:14:31 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2023-10-02 13:14:19 -07:00
|
|
|
|
it('Fallback to command execution on resolve error', function()
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
2023-10-02 13:14:19 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
executeCommandProvider = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
commands = { 'command:1' },
|
2023-10-02 13:14:19 -07:00
|
|
|
|
},
|
|
|
|
|
codeActionProvider = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
resolveProvider = true,
|
|
|
|
|
},
|
2023-10-02 13:14:19 -07:00
|
|
|
|
},
|
|
|
|
|
handlers = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
['textDocument/codeAction'] = function(_, _, callback)
|
2024-05-23 06:17:53 -07:00
|
|
|
|
callback(nil, {
|
2023-10-02 13:14:19 -07:00
|
|
|
|
{
|
2024-07-29 03:20:15 -07:00
|
|
|
|
title = 'Code Action 1',
|
2023-10-02 13:14:19 -07:00
|
|
|
|
command = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
title = 'Command 1',
|
|
|
|
|
command = 'command:1',
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-05-23 06:17:53 -07:00
|
|
|
|
})
|
2023-10-02 13:14:19 -07:00
|
|
|
|
end,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
['codeAction/resolve'] = function(_, _, callback)
|
|
|
|
|
callback('resolve failed', nil)
|
2023-10-02 13:14:19 -07:00
|
|
|
|
end,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2023-10-02 13:14:19 -07:00
|
|
|
|
})
|
|
|
|
|
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2024-07-29 03:20:15 -07:00
|
|
|
|
name = 'dummy',
|
2023-10-02 13:14:19 -07:00
|
|
|
|
cmd = server.cmd,
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2023-10-02 13:14:19 -07:00
|
|
|
|
|
|
|
|
|
vim.lsp.buf.code_action({ apply = true })
|
|
|
|
|
vim.lsp.stop_client(client_id)
|
|
|
|
|
return server.messages
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2023-10-02 13:14:19 -07:00
|
|
|
|
eq('codeAction/resolve', result[4].method)
|
|
|
|
|
eq('workspace/executeCommand', result[5].method)
|
|
|
|
|
eq('command:1', result[5].params.command)
|
|
|
|
|
end)
|
2021-03-12 02:19:21 -07:00
|
|
|
|
end)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
|
2021-03-12 02:19:21 -07:00
|
|
|
|
describe('vim.lsp.commands', function()
|
|
|
|
|
it('Accepts only string keys', function()
|
|
|
|
|
matches(
|
|
|
|
|
'.*The key for commands in `vim.lsp.commands` must be a string',
|
|
|
|
|
pcall_err(exec_lua, 'vim.lsp.commands[1] = function() end')
|
|
|
|
|
)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2021-03-12 02:19:21 -07:00
|
|
|
|
it('Accepts only function values', function()
|
|
|
|
|
matches(
|
|
|
|
|
'.*Command added to `vim.lsp.commands` must be a function',
|
|
|
|
|
pcall_err(exec_lua, 'vim.lsp.commands.dummy = 10')
|
|
|
|
|
)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
|
2021-11-01 03:14:59 -07:00
|
|
|
|
describe('vim.lsp.codelens', function()
|
|
|
|
|
it('uses client commands', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2021-11-01 03:14:59 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'clientside_commands',
|
|
|
|
|
on_init = function(client_)
|
|
|
|
|
client = client_
|
|
|
|
|
end,
|
|
|
|
|
on_setup = function() end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2021-11-01 03:14:59 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx })
|
|
|
|
|
if ctx.method == 'start' then
|
|
|
|
|
local fake_uri = 'file:///fake/uri'
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local cmd = exec_lua(function()
|
|
|
|
|
local bufnr = vim.uri_to_bufnr(fake_uri)
|
2021-11-01 03:14:59 -07:00
|
|
|
|
vim.fn.bufload(bufnr)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { 'One line' })
|
2021-11-01 03:14:59 -07:00
|
|
|
|
local lenses = {
|
|
|
|
|
{
|
|
|
|
|
range = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
start = { line = 0, character = 0 },
|
|
|
|
|
['end'] = { line = 0, character = 8 },
|
2021-11-01 03:14:59 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
command = { title = 'Lens1', command = 'Dummy' },
|
2021-11-01 03:14:59 -07:00
|
|
|
|
},
|
|
|
|
|
}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.codelens.on_codelens(
|
|
|
|
|
nil,
|
|
|
|
|
lenses,
|
|
|
|
|
{ method = 'textDocument/codeLens', client_id = 1, bufnr = bufnr }
|
|
|
|
|
)
|
2021-11-01 03:14:59 -07:00
|
|
|
|
local cmd_called = nil
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.commands['Dummy'] = function(command0)
|
|
|
|
|
cmd_called = command0
|
2021-11-01 03:14:59 -07:00
|
|
|
|
end
|
|
|
|
|
vim.api.nvim_set_current_buf(bufnr)
|
|
|
|
|
vim.lsp.codelens.run()
|
|
|
|
|
return cmd_called
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2021-11-01 03:14:59 -07:00
|
|
|
|
eq({ command = 'Dummy', title = 'Lens1' }, cmd)
|
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2021-11-01 03:14:59 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
|
|
|
|
|
it('releases buffer refresh lock', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-05-05 09:50:12 -07:00
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'codelens_refresh_lock',
|
|
|
|
|
on_init = function(client_)
|
|
|
|
|
client = client_
|
|
|
|
|
end,
|
|
|
|
|
on_setup = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { 'One line' })
|
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
|
|
|
|
|
|
|
|
|
_G.CALLED = false
|
|
|
|
|
_G.RESPONSE = nil
|
|
|
|
|
local on_codelens = vim.lsp.codelens.on_codelens
|
|
|
|
|
vim.lsp.codelens.on_codelens = function(err, result, ...)
|
|
|
|
|
_G.CALLED = true
|
|
|
|
|
_G.RESPONSE = { err = err, result = result }
|
|
|
|
|
return on_codelens(err, result, ...)
|
|
|
|
|
end
|
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
end,
|
|
|
|
|
on_exit = function(code, signal)
|
2022-05-30 02:40:17 -07:00
|
|
|
|
eq(0, code, 'exit code')
|
|
|
|
|
eq(0, signal, 'exit signal')
|
2022-05-05 09:50:12 -07:00
|
|
|
|
end,
|
|
|
|
|
on_handler = function(err, result, ctx)
|
|
|
|
|
eq(table.remove(expected_handlers), { err, result, ctx })
|
|
|
|
|
if ctx.method == 'start' then
|
|
|
|
|
-- 1. first codelens request errors
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local response = exec_lua(function()
|
|
|
|
|
_G.CALLED = false
|
2022-05-05 09:50:12 -07:00
|
|
|
|
vim.lsp.codelens.refresh()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(100, function()
|
|
|
|
|
return _G.CALLED
|
|
|
|
|
end)
|
|
|
|
|
return _G.RESPONSE
|
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
eq({ err = { code = -32002, message = 'ServerNotInitialized' } }, response)
|
|
|
|
|
|
|
|
|
|
-- 2. second codelens request runs
|
2024-07-29 03:20:15 -07:00
|
|
|
|
response = exec_lua(function()
|
|
|
|
|
_G.CALLED = false
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local cmd_called --- @type string?
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.commands['Dummy'] = function(command0)
|
|
|
|
|
cmd_called = command0
|
2022-05-05 09:50:12 -07:00
|
|
|
|
end
|
|
|
|
|
vim.lsp.codelens.refresh()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(100, function()
|
|
|
|
|
return _G.CALLED
|
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
vim.lsp.codelens.run()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(100, function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
return cmd_called ~= nil
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
return cmd_called
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
eq({ command = 'Dummy', title = 'Lens1' }, response)
|
|
|
|
|
|
|
|
|
|
-- 3. third codelens request runs
|
2024-07-29 03:20:15 -07:00
|
|
|
|
response = exec_lua(function()
|
|
|
|
|
_G.CALLED = false
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local cmd_called --- @type string?
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.commands['Dummy'] = function(command0)
|
|
|
|
|
cmd_called = command0
|
2022-05-05 09:50:12 -07:00
|
|
|
|
end
|
|
|
|
|
vim.lsp.codelens.refresh()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(100, function()
|
|
|
|
|
return _G.CALLED
|
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
vim.lsp.codelens.run()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(100, function()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
return cmd_called ~= nil
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
return cmd_called
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-05-05 09:50:12 -07:00
|
|
|
|
eq({ command = 'Dummy', title = 'Lens2' }, response)
|
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-05-05 09:50:12 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-03-17 13:04:59 -07:00
|
|
|
|
|
|
|
|
|
it('refresh multiple buffers', function()
|
|
|
|
|
local lens_title_per_fake_uri = {
|
|
|
|
|
['file:///fake/uri1'] = 'Lens1',
|
|
|
|
|
['file:///fake/uri2'] = 'Lens2',
|
|
|
|
|
}
|
|
|
|
|
clear()
|
|
|
|
|
exec_lua(create_server_definition)
|
|
|
|
|
|
|
|
|
|
-- setup lsp
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
capabilities = {
|
|
|
|
|
codeLensProvider = {
|
|
|
|
|
resolveProvider = true,
|
2024-03-17 13:04:59 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
handlers = {
|
|
|
|
|
['textDocument/codeLens'] = function(_, params, callback)
|
|
|
|
|
local lenses = {
|
|
|
|
|
{
|
|
|
|
|
range = {
|
|
|
|
|
start = { line = 0, character = 0 },
|
|
|
|
|
['end'] = { line = 0, character = 0 },
|
2024-03-17 13:04:59 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
command = {
|
2024-08-11 01:27:48 -07:00
|
|
|
|
title = lens_title_per_fake_uri[params.textDocument.uri],
|
2024-07-29 03:20:15 -07:00
|
|
|
|
command = 'Dummy',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
callback(nil, lenses)
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
})
|
2024-03-17 13:04:59 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.CLIENT_ID = vim.lsp.start({
|
|
|
|
|
name = 'dummy',
|
|
|
|
|
cmd = server.cmd,
|
|
|
|
|
})
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-03-17 13:04:59 -07:00
|
|
|
|
|
|
|
|
|
-- create buffers and setup handler
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local default_buf = vim.api.nvim_get_current_buf()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
for fake_uri in pairs(lens_title_per_fake_uri) do
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local bufnr = vim.uri_to_bufnr(fake_uri)
|
|
|
|
|
vim.api.nvim_set_current_buf(bufnr)
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { 'Some contents' })
|
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.CLIENT_ID)
|
|
|
|
|
end
|
|
|
|
|
vim.api.nvim_buf_delete(default_buf, { force = true })
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
_G.REQUEST_COUNT = vim.tbl_count(lens_title_per_fake_uri)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.RESPONSES = {}
|
|
|
|
|
local on_codelens = vim.lsp.codelens.on_codelens
|
|
|
|
|
vim.lsp.codelens.on_codelens = function(err, result, ctx, ...)
|
|
|
|
|
table.insert(_G.RESPONSES, { err = err, result = result, ctx = ctx })
|
|
|
|
|
return on_codelens(err, result, ctx, ...)
|
|
|
|
|
end
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-03-17 13:04:59 -07:00
|
|
|
|
|
|
|
|
|
-- call codelens refresh
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local cmds = exec_lua(function()
|
|
|
|
|
_G.RESPONSES = {}
|
2024-03-17 13:04:59 -07:00
|
|
|
|
vim.lsp.codelens.refresh()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(100, function()
|
|
|
|
|
return #_G.RESPONSES >= _G.REQUEST_COUNT
|
|
|
|
|
end)
|
2024-03-17 13:04:59 -07:00
|
|
|
|
|
|
|
|
|
local cmds = {}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
for _, resp in ipairs(_G.RESPONSES) do
|
2024-03-17 13:04:59 -07:00
|
|
|
|
local uri = resp.ctx.params.textDocument.uri
|
|
|
|
|
cmds[uri] = resp.result[1].command
|
|
|
|
|
end
|
|
|
|
|
return cmds
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-03-17 13:04:59 -07:00
|
|
|
|
eq({ command = 'Dummy', title = 'Lens1' }, cmds['file:///fake/uri1'])
|
|
|
|
|
eq({ command = 'Dummy', title = 'Lens2' }, cmds['file:///fake/uri2'])
|
|
|
|
|
end)
|
2021-11-01 03:14:59 -07:00
|
|
|
|
end)
|
2022-04-30 06:36:40 -07:00
|
|
|
|
|
|
|
|
|
describe('vim.lsp.buf.format', function()
|
|
|
|
|
it('Aborts with notify if no client matches filter', function()
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-04-30 06:36:40 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_init',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local notify_msg = exec_lua(function()
|
2022-04-30 06:36:40 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local notify_msg --- @type string?
|
2022-04-30 06:36:40 -07:00
|
|
|
|
local notify = vim.notify
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.notify = function(msg, _)
|
2022-04-30 06:36:40 -07:00
|
|
|
|
notify_msg = msg
|
|
|
|
|
end
|
|
|
|
|
vim.lsp.buf.format({ name = 'does-not-exist' })
|
|
|
|
|
vim.notify = notify
|
|
|
|
|
return notify_msg
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-04-30 06:36:40 -07:00
|
|
|
|
eq('[LSP] Format request failed, no matching language servers.', notify_msg)
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-04-30 06:36:40 -07:00
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-04-30 06:36:40 -07:00
|
|
|
|
it('Sends textDocument/formatting request to format buffer', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-04-30 06:36:40 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_formatting',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
table.remove(expected_handlers)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local notify_msg = exec_lua(function()
|
2022-04-30 06:36:40 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local notify_msg --- @type string?
|
2022-04-30 06:36:40 -07:00
|
|
|
|
local notify = vim.notify
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.notify = function(msg, _)
|
2022-04-30 06:36:40 -07:00
|
|
|
|
notify_msg = msg
|
|
|
|
|
end
|
|
|
|
|
vim.lsp.buf.format({ bufnr = bufnr })
|
|
|
|
|
vim.notify = notify
|
|
|
|
|
return notify_msg
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(nil, notify_msg)
|
2022-04-30 06:36:40 -07:00
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-04-30 06:36:40 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-06-24 07:54:56 -07:00
|
|
|
|
it('Sends textDocument/rangeFormatting request to format a range', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2024-06-24 07:54:56 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'range_formatting',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
table.remove(expected_handlers)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local notify_msg = exec_lua(function()
|
2024-06-24 07:54:56 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'foo', 'bar' })
|
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local notify_msg --- @type string?
|
2024-06-24 07:54:56 -07:00
|
|
|
|
local notify = vim.notify
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.notify = function(msg, _)
|
2024-06-24 07:54:56 -07:00
|
|
|
|
notify_msg = msg
|
|
|
|
|
end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf.format({
|
|
|
|
|
bufnr = bufnr,
|
|
|
|
|
range = {
|
|
|
|
|
start = { 1, 1 },
|
|
|
|
|
['end'] = { 1, 1 },
|
|
|
|
|
},
|
|
|
|
|
})
|
2024-06-24 07:54:56 -07:00
|
|
|
|
vim.notify = notify
|
|
|
|
|
return notify_msg
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(nil, notify_msg)
|
2024-06-24 07:54:56 -07:00
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2024-06-24 07:54:56 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-06-24 07:54:56 -07:00
|
|
|
|
it('Sends textDocument/rangesFormatting request to format multiple ranges', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2024-06-24 07:54:56 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'ranges_formatting',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
table.remove(expected_handlers)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local notify_msg = exec_lua(function()
|
2024-06-24 07:54:56 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'foo', 'bar', 'baz' })
|
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local notify_msg --- @type string?
|
2024-06-24 07:54:56 -07:00
|
|
|
|
local notify = vim.notify
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.notify = function(msg, _)
|
2024-06-24 07:54:56 -07:00
|
|
|
|
notify_msg = msg
|
|
|
|
|
end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf.format({
|
|
|
|
|
bufnr = bufnr,
|
|
|
|
|
range = {
|
|
|
|
|
{
|
|
|
|
|
start = { 1, 1 },
|
|
|
|
|
['end'] = { 1, 1 },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
start = { 2, 2 },
|
|
|
|
|
['end'] = { 2, 2 },
|
|
|
|
|
},
|
2024-06-24 07:54:56 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
})
|
2024-06-24 07:54:56 -07:00
|
|
|
|
vim.notify = notify
|
|
|
|
|
return notify_msg
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(nil, notify_msg)
|
2024-06-24 07:54:56 -07:00
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2024-06-24 07:54:56 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-04-30 08:23:50 -07:00
|
|
|
|
it('Can format async', function()
|
|
|
|
|
local expected_handlers = {
|
|
|
|
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
|
|
|
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
|
|
|
|
}
|
2024-03-25 12:06:28 -07:00
|
|
|
|
local client --- @type vim.lsp.Client
|
2022-04-30 08:23:50 -07:00
|
|
|
|
test_rpc_server {
|
|
|
|
|
test_name = 'basic_formatting',
|
|
|
|
|
on_init = function(c)
|
|
|
|
|
client = c
|
|
|
|
|
end,
|
|
|
|
|
on_handler = function(_, _, ctx)
|
|
|
|
|
table.remove(expected_handlers)
|
|
|
|
|
if ctx.method == 'start' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
2022-04-30 08:23:50 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.buf_attach_client(bufnr, _G.TEST_RPC_CLIENT_ID)
|
2022-04-30 08:23:50 -07:00
|
|
|
|
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local notify_msg --- @type string?
|
2022-04-30 08:23:50 -07:00
|
|
|
|
local notify = vim.notify
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.notify = function(msg, _)
|
2022-04-30 08:23:50 -07:00
|
|
|
|
notify_msg = msg
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local handler = vim.lsp.handlers['textDocument/formatting']
|
|
|
|
|
local handler_called = false
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.handlers['textDocument/formatting'] = function()
|
2022-04-30 08:23:50 -07:00
|
|
|
|
handler_called = true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.lsp.buf.format({ bufnr = bufnr, async = true })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(1000, function()
|
|
|
|
|
return handler_called
|
|
|
|
|
end)
|
2022-04-30 08:23:50 -07:00
|
|
|
|
|
|
|
|
|
vim.notify = notify
|
|
|
|
|
vim.lsp.handlers['textDocument/formatting'] = handler
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return { notify = notify_msg, handler_called = handler_called }
|
|
|
|
|
end)
|
2022-04-30 08:23:50 -07:00
|
|
|
|
eq({ handler_called = true }, result)
|
|
|
|
|
elseif ctx.method == 'shutdown' then
|
2024-11-14 04:53:20 -07:00
|
|
|
|
client:stop()
|
2022-04-30 08:23:50 -07:00
|
|
|
|
end
|
|
|
|
|
end,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2022-09-08 02:33:04 -07:00
|
|
|
|
it('format formats range in visual mode', function()
|
2022-12-04 07:39:22 -07:00
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
capabilities = {
|
|
|
|
|
documentFormattingProvider = true,
|
|
|
|
|
documentRangeFormattingProvider = true,
|
|
|
|
|
},
|
|
|
|
|
})
|
2022-09-08 02:33:04 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd }))
|
2022-09-08 02:33:04 -07:00
|
|
|
|
vim.api.nvim_win_set_buf(0, bufnr)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'foo', 'bar' })
|
2022-09-08 02:33:04 -07:00
|
|
|
|
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
|
|
|
|
vim.cmd.normal('v')
|
|
|
|
|
vim.api.nvim_win_set_cursor(0, { 2, 3 })
|
|
|
|
|
vim.lsp.buf.format({ bufnr = bufnr, false })
|
2023-03-12 01:45:28 -07:00
|
|
|
|
vim.lsp.stop_client(client_id)
|
2022-12-04 07:39:22 -07:00
|
|
|
|
return server.messages
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2022-12-08 02:55:01 -07:00
|
|
|
|
eq('textDocument/rangeFormatting', result[3].method)
|
2022-09-08 02:33:04 -07:00
|
|
|
|
local expected_range = {
|
|
|
|
|
start = { line = 0, character = 0 },
|
|
|
|
|
['end'] = { line = 1, character = 4 },
|
|
|
|
|
}
|
2022-12-08 02:55:01 -07:00
|
|
|
|
eq(expected_range, result[3].params.range)
|
2022-09-08 02:33:04 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2023-03-12 01:45:28 -07:00
|
|
|
|
it('format formats range in visual line mode', function()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
capabilities = {
|
|
|
|
|
documentFormattingProvider = true,
|
|
|
|
|
documentRangeFormattingProvider = true,
|
|
|
|
|
},
|
|
|
|
|
})
|
2023-03-12 01:45:28 -07:00
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd }))
|
2023-03-12 01:45:28 -07:00
|
|
|
|
vim.api.nvim_win_set_buf(0, bufnr)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'foo', 'bar baz' })
|
2023-03-12 01:45:28 -07:00
|
|
|
|
vim.api.nvim_win_set_cursor(0, { 1, 2 })
|
|
|
|
|
vim.cmd.normal('V')
|
|
|
|
|
vim.api.nvim_win_set_cursor(0, { 2, 1 })
|
|
|
|
|
vim.lsp.buf.format({ bufnr = bufnr, false })
|
|
|
|
|
|
|
|
|
|
-- Format again with visual lines going from bottom to top
|
|
|
|
|
-- Must result in same formatting
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.cmd.normal('<ESC>')
|
2023-03-12 01:45:28 -07:00
|
|
|
|
vim.api.nvim_win_set_cursor(0, { 2, 1 })
|
|
|
|
|
vim.cmd.normal('V')
|
|
|
|
|
vim.api.nvim_win_set_cursor(0, { 1, 2 })
|
|
|
|
|
vim.lsp.buf.format({ bufnr = bufnr, false })
|
|
|
|
|
|
|
|
|
|
vim.lsp.stop_client(client_id)
|
|
|
|
|
return server.messages
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2023-03-12 01:45:28 -07:00
|
|
|
|
local expected_methods = {
|
|
|
|
|
'initialize',
|
|
|
|
|
'initialized',
|
|
|
|
|
'textDocument/rangeFormatting',
|
|
|
|
|
'$/cancelRequest',
|
|
|
|
|
'textDocument/rangeFormatting',
|
|
|
|
|
'$/cancelRequest',
|
|
|
|
|
'shutdown',
|
|
|
|
|
'exit',
|
|
|
|
|
}
|
|
|
|
|
eq(
|
|
|
|
|
expected_methods,
|
|
|
|
|
vim.tbl_map(function(x)
|
|
|
|
|
return x.method
|
|
|
|
|
end, result)
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-03-12 01:45:28 -07:00
|
|
|
|
-- uses first column of start line and last column of end line
|
|
|
|
|
local expected_range = {
|
|
|
|
|
start = { line = 0, character = 0 },
|
|
|
|
|
['end'] = { line = 1, character = 7 },
|
|
|
|
|
}
|
|
|
|
|
eq(expected_range, result[3].params.range)
|
|
|
|
|
eq(expected_range, result[5].params.range)
|
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2023-01-23 23:15:43 -07:00
|
|
|
|
it('Aborts with notify if no clients support requested method', function()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2023-01-23 23:15:43 -07:00
|
|
|
|
vim.notify = function(msg, _)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.notify_msg = msg
|
2023-01-23 23:15:43 -07:00
|
|
|
|
end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2023-01-23 23:15:43 -07:00
|
|
|
|
local fail_msg = '[LSP] Format request failed, no matching language servers.'
|
2024-03-25 12:06:28 -07:00
|
|
|
|
--- @param name string
|
|
|
|
|
--- @param formatting boolean
|
|
|
|
|
--- @param range_formatting boolean
|
2023-01-23 23:15:43 -07:00
|
|
|
|
local function check_notify(name, formatting, range_formatting)
|
|
|
|
|
local timeout_msg = '[LSP][' .. name .. '] timeout'
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
capabilities = {
|
2024-08-11 01:27:48 -07:00
|
|
|
|
documentFormattingProvider = formatting,
|
|
|
|
|
documentRangeFormattingProvider = range_formatting,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.start({ name = name, cmd = server.cmd })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.notify_msg = nil
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.buf.format({ name = name, timeout_ms = 1 })
|
|
|
|
|
end)
|
|
|
|
|
eq(
|
|
|
|
|
formatting and timeout_msg or fail_msg,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return _G.notify_msg
|
|
|
|
|
end)
|
|
|
|
|
)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.notify_msg = nil
|
|
|
|
|
vim.lsp.buf.format({
|
|
|
|
|
name = name,
|
|
|
|
|
timeout_ms = 1,
|
|
|
|
|
range = {
|
|
|
|
|
start = { 1, 0 },
|
|
|
|
|
['end'] = {
|
|
|
|
|
1,
|
|
|
|
|
0,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
eq(
|
|
|
|
|
range_formatting and timeout_msg or fail_msg,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
return _G.notify_msg
|
|
|
|
|
end)
|
|
|
|
|
)
|
2023-01-23 23:15:43 -07:00
|
|
|
|
end
|
|
|
|
|
check_notify('none', false, false)
|
|
|
|
|
check_notify('formatting', true, false)
|
|
|
|
|
check_notify('rangeFormatting', false, true)
|
|
|
|
|
check_notify('both', true, true)
|
|
|
|
|
end)
|
2022-04-30 06:36:40 -07:00
|
|
|
|
end)
|
2024-02-03 15:49:28 -07:00
|
|
|
|
|
2024-10-20 14:40:44 -07:00
|
|
|
|
describe('lsp.buf.definition', function()
|
|
|
|
|
it('jumps to single location', function()
|
|
|
|
|
exec_lua(create_server_definition)
|
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
capabilities = {
|
|
|
|
|
definitionProvider = true,
|
|
|
|
|
},
|
|
|
|
|
handlers = {
|
|
|
|
|
['textDocument/definition'] = function(_, _, callback)
|
|
|
|
|
local location = {
|
|
|
|
|
range = {
|
|
|
|
|
start = { line = 0, character = 0 },
|
|
|
|
|
['end'] = { line = 0, character = 0 },
|
|
|
|
|
},
|
|
|
|
|
uri = vim.uri_from_bufnr(bufnr),
|
|
|
|
|
}
|
|
|
|
|
callback(nil, location)
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
local win = vim.api.nvim_get_current_win()
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'local x = 10', '', 'print(x)' })
|
|
|
|
|
vim.api.nvim_win_set_cursor(win, { 3, 6 })
|
|
|
|
|
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = server.cmd }))
|
|
|
|
|
vim.lsp.buf.definition()
|
|
|
|
|
vim.lsp.stop_client(client_id)
|
|
|
|
|
return {
|
|
|
|
|
cursor = vim.api.nvim_win_get_cursor(win),
|
|
|
|
|
messages = server.messages,
|
2024-10-24 01:22:38 -07:00
|
|
|
|
tagstack = vim.fn.gettagstack(win),
|
2024-10-20 14:40:44 -07:00
|
|
|
|
}
|
|
|
|
|
end)
|
|
|
|
|
eq('textDocument/definition', result.messages[3].method)
|
|
|
|
|
eq({ 1, 0 }, result.cursor)
|
2024-10-24 01:22:38 -07:00
|
|
|
|
eq(1, #result.tagstack.items)
|
|
|
|
|
eq('x', result.tagstack.items[1].tagname)
|
|
|
|
|
eq(3, result.tagstack.items[1].from[2])
|
|
|
|
|
eq(7, result.tagstack.items[1].from[3])
|
2024-10-20 14:40:44 -07:00
|
|
|
|
end)
|
|
|
|
|
it('merges results from multiple servers', function()
|
|
|
|
|
exec_lua(create_server_definition)
|
|
|
|
|
local result = exec_lua(function()
|
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
|
local function serveropts(character)
|
|
|
|
|
return {
|
|
|
|
|
capabilities = {
|
|
|
|
|
definitionProvider = true,
|
|
|
|
|
},
|
|
|
|
|
handlers = {
|
|
|
|
|
['textDocument/definition'] = function(_, _, callback)
|
|
|
|
|
local location = {
|
|
|
|
|
range = {
|
|
|
|
|
start = { line = 0, character = character },
|
|
|
|
|
['end'] = { line = 0, character = character },
|
|
|
|
|
},
|
|
|
|
|
uri = vim.uri_from_bufnr(bufnr),
|
|
|
|
|
}
|
|
|
|
|
callback(nil, location)
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
local server1 = _G._create_server(serveropts(0))
|
|
|
|
|
local server2 = _G._create_server(serveropts(7))
|
|
|
|
|
local win = vim.api.nvim_get_current_win()
|
|
|
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'local x = 10', '', 'print(x)' })
|
|
|
|
|
vim.api.nvim_win_set_cursor(win, { 3, 6 })
|
2024-12-13 03:51:33 -07:00
|
|
|
|
local client_id1 = assert(vim.lsp.start({ name = 'dummy1', cmd = server1.cmd }))
|
|
|
|
|
local client_id2 = assert(vim.lsp.start({ name = 'dummy2', cmd = server2.cmd }))
|
2024-10-20 14:40:44 -07:00
|
|
|
|
local response
|
|
|
|
|
vim.lsp.buf.definition({
|
|
|
|
|
on_list = function(r)
|
|
|
|
|
response = r
|
|
|
|
|
end,
|
|
|
|
|
})
|
|
|
|
|
vim.lsp.stop_client(client_id1)
|
|
|
|
|
vim.lsp.stop_client(client_id2)
|
|
|
|
|
return response
|
|
|
|
|
end)
|
|
|
|
|
eq(2, #result.items)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2024-02-03 15:49:28 -07:00
|
|
|
|
describe('vim.lsp.tagfunc', function()
|
|
|
|
|
before_each(function()
|
|
|
|
|
clear()
|
|
|
|
|
---@type lsp.Location[]
|
|
|
|
|
local mock_locations = {
|
|
|
|
|
{
|
|
|
|
|
range = {
|
|
|
|
|
['start'] = { line = 5, character = 23 },
|
|
|
|
|
['end'] = { line = 10, character = 0 },
|
|
|
|
|
},
|
|
|
|
|
uri = 'test://buf',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
range = {
|
|
|
|
|
['start'] = { line = 42, character = 10 },
|
|
|
|
|
['end'] = { line = 44, character = 0 },
|
|
|
|
|
},
|
|
|
|
|
uri = 'test://another-file',
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.mock_locations = mock_locations
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.server = _G._create_server({
|
2024-02-03 15:49:28 -07:00
|
|
|
|
---@type lsp.ServerCapabilities
|
|
|
|
|
capabilities = {
|
|
|
|
|
definitionProvider = true,
|
|
|
|
|
workspaceSymbolProvider = true,
|
|
|
|
|
},
|
|
|
|
|
handlers = {
|
|
|
|
|
---@return lsp.Location[]
|
2024-05-23 06:17:53 -07:00
|
|
|
|
['textDocument/definition'] = function(_, _, callback)
|
|
|
|
|
callback(nil, { _G.mock_locations[1] })
|
2024-02-03 15:49:28 -07:00
|
|
|
|
end,
|
|
|
|
|
---@return lsp.WorkspaceSymbol[]
|
2024-05-23 06:17:53 -07:00
|
|
|
|
['workspace/symbol'] = function(_, request, callback)
|
2024-02-03 15:49:28 -07:00
|
|
|
|
assert(request.query == 'foobar')
|
2024-05-23 06:17:53 -07:00
|
|
|
|
callback(nil, {
|
2024-02-03 15:49:28 -07:00
|
|
|
|
{
|
|
|
|
|
name = 'foobar',
|
|
|
|
|
kind = 13, ---@type lsp.SymbolKind
|
|
|
|
|
location = _G.mock_locations[1],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name = 'vim.foobar',
|
|
|
|
|
kind = 12, ---@type lsp.SymbolKind
|
|
|
|
|
location = _G.mock_locations[2],
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
2024-05-23 06:17:53 -07:00
|
|
|
|
})
|
2024-02-03 15:49:28 -07:00
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.client_id = vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd })
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-02-03 15:49:28 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-02-03 15:49:28 -07:00
|
|
|
|
after_each(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
2024-02-03 15:49:28 -07:00
|
|
|
|
vim.lsp.stop_client(_G.client_id)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-02-03 15:49:28 -07:00
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('with flags=c, returns matching tags using textDocument/definition', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-02-03 15:49:28 -07:00
|
|
|
|
return vim.lsp.tagfunc('foobar', 'c')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-02-03 15:49:28 -07:00
|
|
|
|
eq({
|
|
|
|
|
{
|
|
|
|
|
cmd = '/\\%6l\\%1c/', -- for location (5, 23)
|
|
|
|
|
filename = 'test://buf',
|
|
|
|
|
name = 'foobar',
|
|
|
|
|
},
|
|
|
|
|
}, result)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('without flags=c, returns all matching tags using workspace/symbol', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-02-03 15:49:28 -07:00
|
|
|
|
return vim.lsp.tagfunc('foobar', '')
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-02-03 15:49:28 -07:00
|
|
|
|
eq({
|
|
|
|
|
{
|
|
|
|
|
cmd = '/\\%6l\\%1c/', -- for location (5, 23)
|
|
|
|
|
filename = 'test://buf',
|
|
|
|
|
kind = 'Variable',
|
|
|
|
|
name = 'foobar',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
cmd = '/\\%43l\\%1c/', -- for location (42, 10)
|
|
|
|
|
filename = 'test://another-file',
|
|
|
|
|
kind = 'Function',
|
|
|
|
|
name = 'vim.foobar',
|
|
|
|
|
},
|
|
|
|
|
}, result)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2022-08-24 11:25:34 -07:00
|
|
|
|
describe('cmd', function()
|
2024-09-03 08:10:39 -07:00
|
|
|
|
it('connects to lsp server via rpc.connect using ip address', function()
|
|
|
|
|
exec_lua(create_tcp_echo_server)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-09-03 08:10:39 -07:00
|
|
|
|
local server, port, last_message = _G._create_tcp_server('127.0.0.1')
|
2022-08-24 11:25:34 -07:00
|
|
|
|
vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect('127.0.0.1', port) })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(1000, function()
|
2024-09-03 08:10:39 -07:00
|
|
|
|
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
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-09-03 08:10:39 -07:00
|
|
|
|
local init = last_message()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
assert(init, 'server must receive `initialize` request')
|
2022-08-24 11:25:34 -07:00
|
|
|
|
server:close()
|
|
|
|
|
server:shutdown()
|
|
|
|
|
return vim.json.decode(init)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2024-03-11 07:23:14 -07:00
|
|
|
|
eq('initialize', result.method)
|
2022-08-24 11:25:34 -07:00
|
|
|
|
end)
|
2024-08-11 03:58:15 -07:00
|
|
|
|
|
2024-04-18 06:34:10 -07:00
|
|
|
|
it('can connect to lsp server via pipe or domain_socket', function()
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local tmpfile = is_os('win') and '\\\\.\\\\pipe\\pipe.test' or tmpname(false)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-01-02 02:08:36 -07:00
|
|
|
|
local uv = vim.uv
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local server = assert(uv.new_pipe(false))
|
2024-08-11 01:27:48 -07:00
|
|
|
|
server:bind(tmpfile)
|
2024-01-02 02:08:36 -07:00
|
|
|
|
local init = nil
|
|
|
|
|
|
|
|
|
|
server:listen(127, function(err)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
assert(not err, err)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local client = assert(vim.uv.new_pipe())
|
2024-07-29 03:20:15 -07:00
|
|
|
|
server:accept(client)
|
|
|
|
|
client:read_start(require('vim.lsp.rpc').create_read_loop(function(body)
|
|
|
|
|
init = body
|
|
|
|
|
client:close()
|
|
|
|
|
end))
|
2024-01-02 02:08:36 -07:00
|
|
|
|
end)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect(tmpfile) })
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(1000, function()
|
|
|
|
|
return init ~= nil
|
|
|
|
|
end)
|
|
|
|
|
assert(init, 'server must receive `initialize` request')
|
2024-01-02 02:08:36 -07:00
|
|
|
|
server:close()
|
|
|
|
|
server:shutdown()
|
|
|
|
|
return vim.json.decode(init)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2024-03-11 07:23:14 -07:00
|
|
|
|
eq('initialize', result.method)
|
2024-01-02 02:08:36 -07:00
|
|
|
|
end)
|
2022-08-24 11:25:34 -07:00
|
|
|
|
end)
|
2022-09-20 00:28:23 -07:00
|
|
|
|
|
|
|
|
|
describe('handlers', function()
|
|
|
|
|
it('handler can return false as response', function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local server = assert(vim.uv.new_tcp())
|
2022-09-20 00:28:23 -07:00
|
|
|
|
local messages = {}
|
|
|
|
|
local responses = {}
|
|
|
|
|
server:bind('127.0.0.1', 0)
|
|
|
|
|
server:listen(127, function(err)
|
|
|
|
|
assert(not err, err)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local socket = assert(vim.uv.new_tcp())
|
2022-09-20 00:28:23 -07:00
|
|
|
|
server:accept(socket)
|
|
|
|
|
socket:read_start(require('vim.lsp.rpc').create_read_loop(function(body)
|
|
|
|
|
local payload = vim.json.decode(body)
|
|
|
|
|
if payload.method then
|
|
|
|
|
table.insert(messages, payload.method)
|
|
|
|
|
if payload.method == 'initialize' then
|
|
|
|
|
local msg = vim.json.encode({
|
|
|
|
|
id = payload.id,
|
|
|
|
|
jsonrpc = '2.0',
|
|
|
|
|
result = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
capabilities = {},
|
2022-09-20 00:28:23 -07:00
|
|
|
|
},
|
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
socket:write(table.concat({ 'Content-Length: ', tostring(#msg), '\r\n\r\n', msg }))
|
2022-09-20 00:28:23 -07:00
|
|
|
|
elseif payload.method == 'initialized' then
|
|
|
|
|
local msg = vim.json.encode({
|
|
|
|
|
id = 10,
|
|
|
|
|
jsonrpc = '2.0',
|
|
|
|
|
method = 'dummy',
|
|
|
|
|
params = {},
|
|
|
|
|
})
|
2024-07-29 03:20:15 -07:00
|
|
|
|
socket:write(table.concat({ 'Content-Length: ', tostring(#msg), '\r\n\r\n', msg }))
|
2022-09-20 00:28:23 -07:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
table.insert(responses, payload)
|
|
|
|
|
socket:close()
|
|
|
|
|
end
|
|
|
|
|
end))
|
|
|
|
|
end)
|
|
|
|
|
local port = server:getsockname().port
|
|
|
|
|
local handler_called = false
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.handlers['dummy'] = function(_, _)
|
2022-09-20 00:28:23 -07:00
|
|
|
|
handler_called = true
|
|
|
|
|
return false
|
|
|
|
|
end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local client_id =
|
2024-08-11 03:58:15 -07:00
|
|
|
|
assert(vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect('127.0.0.1', port) }))
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.get_client_by_id(client_id)
|
|
|
|
|
vim.wait(1000, function()
|
|
|
|
|
return #messages == 2 and handler_called and #responses == 1
|
|
|
|
|
end)
|
2022-09-20 00:28:23 -07:00
|
|
|
|
server:close()
|
|
|
|
|
server:shutdown()
|
|
|
|
|
return {
|
|
|
|
|
messages = messages,
|
|
|
|
|
handler_called = handler_called,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
responses = responses,
|
|
|
|
|
}
|
|
|
|
|
end)
|
2022-09-20 00:28:23 -07:00
|
|
|
|
local expected = {
|
|
|
|
|
messages = { 'initialize', 'initialized' },
|
|
|
|
|
handler_called = true,
|
|
|
|
|
responses = {
|
|
|
|
|
{
|
|
|
|
|
id = 10,
|
|
|
|
|
jsonrpc = '2.0',
|
|
|
|
|
result = false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
eq(expected, result)
|
|
|
|
|
end)
|
|
|
|
|
end)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2023-05-27 22:51:28 -07:00
|
|
|
|
describe('#dynamic vim.lsp._dynamic', function()
|
|
|
|
|
it('supports dynamic registration', function()
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local root_dir = tmpname(false)
|
2023-05-27 22:51:28 -07:00
|
|
|
|
mkdir(root_dir)
|
|
|
|
|
local tmpfile = root_dir .. '/dynamic.foo'
|
|
|
|
|
local file = io.open(tmpfile, 'w')
|
2023-12-22 07:03:13 -07:00
|
|
|
|
if file then
|
|
|
|
|
file:close()
|
|
|
|
|
end
|
2023-05-27 22:51:28 -07:00
|
|
|
|
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2023-05-27 22:51:28 -07:00
|
|
|
|
name = 'dynamic-test',
|
|
|
|
|
cmd = server.cmd,
|
2024-08-11 01:27:48 -07:00
|
|
|
|
root_dir = root_dir,
|
2023-12-22 07:03:13 -07:00
|
|
|
|
get_language_id = function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return 'dummy-lang'
|
2023-12-22 07:03:13 -07:00
|
|
|
|
end,
|
2023-05-27 22:51:28 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
textDocument = {
|
|
|
|
|
formatting = {
|
|
|
|
|
dynamicRegistration = true,
|
|
|
|
|
},
|
|
|
|
|
rangeFormatting = {
|
|
|
|
|
dynamicRegistration = true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2023-05-27 22:51:28 -07:00
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'formatting',
|
|
|
|
|
method = 'textDocument/formatting',
|
|
|
|
|
registerOptions = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
documentSelector = {
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
pattern = root_dir .. '/*.foo',
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
2023-05-27 22:51:28 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'range-formatting',
|
|
|
|
|
method = 'textDocument/rangeFormatting',
|
2023-12-22 07:03:13 -07:00
|
|
|
|
registerOptions = {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
documentSelector = {
|
2023-12-22 07:03:13 -07:00
|
|
|
|
{
|
2024-07-29 03:20:15 -07:00
|
|
|
|
language = 'dummy-lang',
|
2023-12-22 07:03:13 -07:00
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
2023-05-27 22:51:28 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'completion',
|
|
|
|
|
method = 'textDocument/completion',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
|
|
|
|
local result = {}
|
|
|
|
|
local function check(method, fname)
|
|
|
|
|
local bufnr = fname and vim.fn.bufadd(fname) or nil
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client = assert(vim.lsp.get_client_by_id(client_id))
|
2023-12-22 07:03:13 -07:00
|
|
|
|
result[#result + 1] = {
|
|
|
|
|
method = method,
|
|
|
|
|
fname = fname,
|
2024-11-14 04:53:20 -07:00
|
|
|
|
supported = client:supports_method(method, { bufnr = bufnr }),
|
2023-12-22 07:03:13 -07:00
|
|
|
|
}
|
2023-05-27 22:51:28 -07:00
|
|
|
|
end
|
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
check('textDocument/formatting')
|
2024-08-11 01:27:48 -07:00
|
|
|
|
check('textDocument/formatting', tmpfile)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
check('textDocument/rangeFormatting')
|
2024-08-11 01:27:48 -07:00
|
|
|
|
check('textDocument/rangeFormatting', tmpfile)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
check('textDocument/completion')
|
2023-05-27 22:51:28 -07:00
|
|
|
|
|
|
|
|
|
return result
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2023-05-27 22:51:28 -07:00
|
|
|
|
|
|
|
|
|
eq(5, #result)
|
|
|
|
|
eq({ method = 'textDocument/formatting', supported = false }, result[1])
|
|
|
|
|
eq({ method = 'textDocument/formatting', supported = true, fname = tmpfile }, result[2])
|
|
|
|
|
eq({ method = 'textDocument/rangeFormatting', supported = true }, result[3])
|
|
|
|
|
eq({ method = 'textDocument/rangeFormatting', supported = true, fname = tmpfile }, result[4])
|
|
|
|
|
eq({ method = 'textDocument/completion', supported = false }, result[5])
|
|
|
|
|
end)
|
|
|
|
|
end)
|
|
|
|
|
|
2023-03-04 23:52:27 -07:00
|
|
|
|
describe('vim.lsp._watchfiles', function()
|
2024-08-11 01:27:48 -07:00
|
|
|
|
--- @type integer, integer, integer
|
|
|
|
|
local created, changed, deleted
|
|
|
|
|
|
|
|
|
|
setup(function()
|
|
|
|
|
clear()
|
|
|
|
|
created = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]])
|
|
|
|
|
changed = exec_lua([[return vim.lsp.protocol.FileChangeType.Changed]])
|
|
|
|
|
deleted = exec_lua([[return vim.lsp.protocol.FileChangeType.Deleted]])
|
|
|
|
|
end)
|
|
|
|
|
|
2024-02-07 04:24:44 -07:00
|
|
|
|
local function test_filechanges(watchfunc)
|
|
|
|
|
it(
|
|
|
|
|
string.format('sends notifications when files change (watchfunc=%s)', watchfunc),
|
|
|
|
|
function()
|
2024-07-06 02:44:19 -07:00
|
|
|
|
if watchfunc == 'inotify' then
|
2024-03-28 15:26:01 -07:00
|
|
|
|
skip(is_os('win'), 'not supported on windows')
|
|
|
|
|
skip(is_os('mac'), 'flaky test on mac')
|
2024-02-07 04:28:35 -07:00
|
|
|
|
skip(
|
2024-07-06 02:44:19 -07:00
|
|
|
|
not is_ci() and fn.executable('inotifywait') == 0,
|
|
|
|
|
'inotify-tools not installed and not on CI'
|
2024-02-07 04:28:35 -07:00
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
2024-03-28 15:26:01 -07:00
|
|
|
|
if watchfunc == 'watch' then
|
|
|
|
|
skip(is_os('mac'), 'flaky test on mac')
|
|
|
|
|
skip(
|
|
|
|
|
is_os('bsd'),
|
|
|
|
|
'Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38'
|
|
|
|
|
)
|
|
|
|
|
else
|
|
|
|
|
skip(
|
|
|
|
|
is_os('bsd'),
|
|
|
|
|
'kqueue only reports events on watched folder itself, not contained files #26110'
|
|
|
|
|
)
|
|
|
|
|
end
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-09-02 10:14:09 -07:00
|
|
|
|
local root_dir = tmpname(false)
|
2024-02-07 04:24:44 -07:00
|
|
|
|
mkdir(root_dir)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-02-07 04:24:44 -07:00
|
|
|
|
exec_lua(create_server_definition)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2024-07-29 03:20:15 -07:00
|
|
|
|
name = 'watchfiles-test',
|
|
|
|
|
cmd = server.cmd,
|
2024-08-11 01:27:48 -07:00
|
|
|
|
root_dir = root_dir,
|
2024-07-29 03:20:15 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
workspace = {
|
|
|
|
|
didChangeWatchedFiles = {
|
|
|
|
|
dynamicRegistration = true,
|
|
|
|
|
},
|
2024-02-07 04:24:44 -07:00
|
|
|
|
},
|
2023-05-19 22:45:39 -07:00
|
|
|
|
},
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
require('vim.lsp._watchfiles')._watchfunc = require('vim._watch')[watchfunc]
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local expected_messages = 0
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local msg_wait_timeout = watchfunc == 'watch' and 200 or 2500
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local function wait_for_message(incr)
|
|
|
|
|
expected_messages = expected_messages + (incr or 1)
|
|
|
|
|
assert(
|
|
|
|
|
vim.wait(msg_wait_timeout, function()
|
|
|
|
|
return #server.messages == expected_messages
|
|
|
|
|
end),
|
|
|
|
|
'Timed out waiting for expected number of messages. Current messages seen so far: '
|
|
|
|
|
.. vim.inspect(server.messages)
|
|
|
|
|
)
|
|
|
|
|
end
|
2024-02-07 04:24:44 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
wait_for_message(2) -- initialize, initialized
|
2024-02-07 04:24:44 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-0',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
registerOptions = {
|
|
|
|
|
watchers = {
|
|
|
|
|
{
|
|
|
|
|
globPattern = '**/watch',
|
|
|
|
|
kind = 7,
|
|
|
|
|
},
|
2024-02-07 04:24:44 -07:00
|
|
|
|
},
|
2023-03-04 23:52:27 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-07-29 03:20:15 -07:00
|
|
|
|
}, { client_id = client_id })
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
if watchfunc ~= 'watch' then
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.wait(100)
|
|
|
|
|
end
|
2023-03-26 02:41:27 -07:00
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local path = root_dir .. '/watch'
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local tmp = vim.fn.tempname()
|
|
|
|
|
io.open(tmp, 'w'):close()
|
|
|
|
|
vim.uv.fs_rename(tmp, path)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
wait_for_message()
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
os.remove(path)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
wait_for_message()
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
vim.lsp.stop_client(client_id)
|
2024-02-07 06:05:33 -07:00
|
|
|
|
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return server.messages
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-02-07 04:24:44 -07:00
|
|
|
|
local uri = vim.uri_from_fname(root_dir .. '/watch')
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
2024-02-07 06:05:33 -07:00
|
|
|
|
eq(6, #result)
|
2024-02-07 04:24:44 -07:00
|
|
|
|
|
|
|
|
|
eq({
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
params = {
|
|
|
|
|
changes = {
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2024-02-07 04:24:44 -07:00
|
|
|
|
uri = uri,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, result[3])
|
|
|
|
|
|
|
|
|
|
eq({
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
params = {
|
|
|
|
|
changes = {
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = deleted,
|
2024-02-07 04:24:44 -07:00
|
|
|
|
uri = uri,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, result[4])
|
|
|
|
|
end
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
test_filechanges('watch')
|
|
|
|
|
test_filechanges('watchdirs')
|
2024-07-06 02:44:19 -07:00
|
|
|
|
test_filechanges('inotify')
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
it('correctly registers and unregisters', function()
|
2023-05-09 09:12:54 -07:00
|
|
|
|
local root_dir = '/some_dir'
|
2023-03-04 23:52:27 -07:00
|
|
|
|
exec_lua(create_server_definition)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2023-03-04 23:52:27 -07:00
|
|
|
|
name = 'watchfiles-test',
|
|
|
|
|
cmd = server.cmd,
|
2024-08-11 01:27:48 -07:00
|
|
|
|
root_dir = root_dir,
|
2023-05-19 22:45:39 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
workspace = {
|
|
|
|
|
didChangeWatchedFiles = {
|
|
|
|
|
dynamicRegistration = true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
local expected_messages = 2 -- initialize, initialized
|
|
|
|
|
local function wait_for_messages()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
assert(
|
|
|
|
|
vim.wait(200, function()
|
|
|
|
|
return #server.messages == expected_messages
|
|
|
|
|
end),
|
|
|
|
|
'Timed out waiting for expected number of messages. Current messages seen so far: '
|
|
|
|
|
.. vim.inspect(server.messages)
|
|
|
|
|
)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wait_for_messages()
|
|
|
|
|
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local send_event --- @type function
|
2023-03-04 23:52:27 -07:00
|
|
|
|
require('vim.lsp._watchfiles')._watchfunc = function(_, _, callback)
|
2023-04-04 10:07:33 -07:00
|
|
|
|
local stopped = false
|
2023-03-04 23:52:27 -07:00
|
|
|
|
send_event = function(...)
|
2023-04-04 10:07:33 -07:00
|
|
|
|
if not stopped then
|
2023-03-04 23:52:27 -07:00
|
|
|
|
callback(...)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
return function()
|
2023-04-04 10:07:33 -07:00
|
|
|
|
stopped = true
|
2023-03-04 23:52:27 -07:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-0',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
registerOptions = {
|
|
|
|
|
watchers = {
|
|
|
|
|
{
|
|
|
|
|
globPattern = '**/*.watch0',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
send_event(root_dir .. '/file.watch0', vim._watch.FileChangeType.Created)
|
|
|
|
|
send_event(root_dir .. '/file.watch1', vim._watch.FileChangeType.Created)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
expected_messages = expected_messages + 1
|
|
|
|
|
wait_for_messages()
|
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-1',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
registerOptions = {
|
|
|
|
|
watchers = {
|
|
|
|
|
{
|
|
|
|
|
globPattern = '**/*.watch1',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/unregisterCapability'](nil, {
|
|
|
|
|
unregisterations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-0',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
2024-08-11 01:27:48 -07:00
|
|
|
|
send_event(root_dir .. '/file.watch0', vim._watch.FileChangeType.Created)
|
|
|
|
|
send_event(root_dir .. '/file.watch1', vim._watch.FileChangeType.Created)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
expected_messages = expected_messages + 1
|
|
|
|
|
wait_for_messages()
|
|
|
|
|
|
|
|
|
|
return server.messages
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
local function watched_uri(fname)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
return vim.uri_from_fname(root_dir .. '/' .. fname)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
eq(4, #result)
|
|
|
|
|
eq('workspace/didChangeWatchedFiles', result[3].method)
|
|
|
|
|
eq({
|
|
|
|
|
changes = {
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('file.watch0'),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, result[3].params)
|
|
|
|
|
eq('workspace/didChangeWatchedFiles', result[4].method)
|
|
|
|
|
eq({
|
|
|
|
|
changes = {
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('file.watch1'),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, result[4].params)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('correctly handles the registered watch kind', function()
|
|
|
|
|
local root_dir = 'some_dir'
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2023-03-04 23:52:27 -07:00
|
|
|
|
name = 'watchfiles-test',
|
|
|
|
|
cmd = server.cmd,
|
2024-08-11 01:27:48 -07:00
|
|
|
|
root_dir = root_dir,
|
2023-05-19 22:45:39 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
workspace = {
|
|
|
|
|
didChangeWatchedFiles = {
|
|
|
|
|
dynamicRegistration = true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
local expected_messages = 2 -- initialize, initialized
|
|
|
|
|
local function wait_for_messages()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
assert(
|
|
|
|
|
vim.wait(200, function()
|
|
|
|
|
return #server.messages == expected_messages
|
|
|
|
|
end),
|
|
|
|
|
'Timed out waiting for expected number of messages. Current messages seen so far: '
|
|
|
|
|
.. vim.inspect(server.messages)
|
|
|
|
|
)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wait_for_messages()
|
|
|
|
|
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local watch_callbacks = {} --- @type function[]
|
2023-03-04 23:52:27 -07:00
|
|
|
|
local function send_event(...)
|
|
|
|
|
for _, cb in ipairs(watch_callbacks) do
|
|
|
|
|
cb(...)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
require('vim.lsp._watchfiles')._watchfunc = function(_, _, callback)
|
|
|
|
|
table.insert(watch_callbacks, callback)
|
|
|
|
|
return function()
|
|
|
|
|
-- noop because this test never stops the watch
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local protocol = require('vim.lsp.protocol')
|
|
|
|
|
|
|
|
|
|
local watchers = {}
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local max_kind = protocol.WatchKind.Create
|
|
|
|
|
+ protocol.WatchKind.Change
|
|
|
|
|
+ protocol.WatchKind.Delete
|
2023-03-04 23:52:27 -07:00
|
|
|
|
for i = 0, max_kind do
|
|
|
|
|
table.insert(watchers, {
|
|
|
|
|
globPattern = {
|
2023-05-09 09:12:54 -07:00
|
|
|
|
baseUri = vim.uri_from_fname('/dir'),
|
2024-07-29 03:20:15 -07:00
|
|
|
|
pattern = 'watch' .. tostring(i),
|
2023-03-04 23:52:27 -07:00
|
|
|
|
},
|
|
|
|
|
kind = i,
|
|
|
|
|
})
|
|
|
|
|
end
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-kind',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
registerOptions = {
|
|
|
|
|
watchers = watchers,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
|
|
|
|
for i = 0, max_kind do
|
2023-05-09 09:12:54 -07:00
|
|
|
|
local filename = '/dir/watch' .. tostring(i)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
send_event(filename, vim._watch.FileChangeType.Created)
|
|
|
|
|
send_event(filename, vim._watch.FileChangeType.Changed)
|
|
|
|
|
send_event(filename, vim._watch.FileChangeType.Deleted)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
expected_messages = expected_messages + 1
|
|
|
|
|
wait_for_messages()
|
|
|
|
|
|
|
|
|
|
return server.messages
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
local function watched_uri(fname)
|
2024-03-25 12:06:28 -07:00
|
|
|
|
return vim.uri_from_fname('/dir/' .. fname)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
eq(3, #result)
|
|
|
|
|
eq('workspace/didChangeWatchedFiles', result[3].method)
|
|
|
|
|
eq({
|
|
|
|
|
changes = {
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch1'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = changed,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch2'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch3'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = changed,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch3'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = deleted,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch4'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch5'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = deleted,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch5'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = changed,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch6'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = deleted,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch6'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch7'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = changed,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch7'),
|
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = deleted,
|
2023-03-04 23:52:27 -07:00
|
|
|
|
uri = watched_uri('watch7'),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, result[3].params)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('prunes duplicate events', function()
|
|
|
|
|
local root_dir = 'some_dir'
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
local result = exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
local server = _G._create_server()
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2023-03-04 23:52:27 -07:00
|
|
|
|
name = 'watchfiles-test',
|
|
|
|
|
cmd = server.cmd,
|
2024-08-11 01:27:48 -07:00
|
|
|
|
root_dir = root_dir,
|
2023-05-19 22:45:39 -07:00
|
|
|
|
capabilities = {
|
|
|
|
|
workspace = {
|
|
|
|
|
didChangeWatchedFiles = {
|
|
|
|
|
dynamicRegistration = true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
local expected_messages = 2 -- initialize, initialized
|
|
|
|
|
local function wait_for_messages()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
assert(
|
|
|
|
|
vim.wait(200, function()
|
|
|
|
|
return #server.messages == expected_messages
|
|
|
|
|
end),
|
|
|
|
|
'Timed out waiting for expected number of messages. Current messages seen so far: '
|
|
|
|
|
.. vim.inspect(server.messages)
|
|
|
|
|
)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
wait_for_messages()
|
|
|
|
|
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local send_event --- @type function
|
2023-03-04 23:52:27 -07:00
|
|
|
|
require('vim.lsp._watchfiles')._watchfunc = function(_, _, callback)
|
|
|
|
|
send_event = callback
|
|
|
|
|
return function()
|
|
|
|
|
-- noop because this test never stops the watch
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-kind',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
registerOptions = {
|
|
|
|
|
watchers = {
|
|
|
|
|
{
|
|
|
|
|
globPattern = '**/*',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
|
|
|
|
send_event('file1', vim._watch.FileChangeType.Created)
|
|
|
|
|
send_event('file1', vim._watch.FileChangeType.Created) -- pruned
|
|
|
|
|
send_event('file1', vim._watch.FileChangeType.Changed)
|
|
|
|
|
send_event('file2', vim._watch.FileChangeType.Created)
|
|
|
|
|
send_event('file1', vim._watch.FileChangeType.Changed) -- pruned
|
|
|
|
|
|
|
|
|
|
expected_messages = expected_messages + 1
|
|
|
|
|
wait_for_messages()
|
|
|
|
|
|
|
|
|
|
return server.messages
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
|
|
|
|
|
eq(3, #result)
|
|
|
|
|
eq('workspace/didChangeWatchedFiles', result[3].method)
|
|
|
|
|
eq({
|
|
|
|
|
changes = {
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2024-03-25 12:06:28 -07:00
|
|
|
|
uri = vim.uri_from_fname('file1'),
|
2023-03-04 23:52:27 -07:00
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = changed,
|
2024-03-25 12:06:28 -07:00
|
|
|
|
uri = vim.uri_from_fname('file1'),
|
2023-03-04 23:52:27 -07:00
|
|
|
|
},
|
|
|
|
|
{
|
2024-08-11 01:27:48 -07:00
|
|
|
|
type = created,
|
2024-03-25 12:06:28 -07:00
|
|
|
|
uri = vim.uri_from_fname('file2'),
|
2023-03-04 23:52:27 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}, result[3].params)
|
|
|
|
|
end)
|
2023-05-19 22:45:39 -07:00
|
|
|
|
|
|
|
|
|
it("ignores registrations by servers when the client doesn't advertise support", function()
|
|
|
|
|
exec_lua(create_server_definition)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
exec_lua(function()
|
|
|
|
|
_G.server = _G._create_server()
|
|
|
|
|
require('vim.lsp._watchfiles')._watchfunc = function(_, _, _)
|
2023-05-19 22:45:39 -07:00
|
|
|
|
-- Since the registration is ignored, this should not execute and `watching` should stay false
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.watching = true
|
2023-05-19 22:45:39 -07:00
|
|
|
|
return function() end
|
|
|
|
|
end
|
2024-07-29 03:20:15 -07:00
|
|
|
|
end)
|
2023-05-19 22:45:39 -07:00
|
|
|
|
|
2023-08-03 23:10:54 -07:00
|
|
|
|
local function check_registered(capabilities)
|
2024-08-11 01:27:48 -07:00
|
|
|
|
return exec_lua(function()
|
2024-07-29 03:20:15 -07:00
|
|
|
|
_G.watching = false
|
2024-08-11 03:58:15 -07:00
|
|
|
|
local client_id = assert(vim.lsp.start({
|
2023-08-03 23:10:54 -07:00
|
|
|
|
name = 'watchfiles-test',
|
2024-07-29 03:20:15 -07:00
|
|
|
|
cmd = _G.server.cmd,
|
2023-08-03 23:10:54 -07:00
|
|
|
|
root_dir = 'some_dir',
|
2024-08-11 01:27:48 -07:00
|
|
|
|
capabilities = capabilities,
|
2023-08-03 23:10:54 -07:00
|
|
|
|
}, {
|
2024-07-29 03:20:15 -07:00
|
|
|
|
reuse_client = function()
|
|
|
|
|
return false
|
|
|
|
|
end,
|
2024-08-11 03:58:15 -07:00
|
|
|
|
}))
|
2023-08-03 23:10:54 -07:00
|
|
|
|
|
|
|
|
|
vim.lsp.handlers['client/registerCapability'](nil, {
|
|
|
|
|
registrations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-kind',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
registerOptions = {
|
|
|
|
|
watchers = {
|
|
|
|
|
{
|
|
|
|
|
globPattern = '**/*',
|
|
|
|
|
},
|
2023-05-19 22:45:39 -07:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-08-03 23:10:54 -07:00
|
|
|
|
}, { client_id = client_id })
|
|
|
|
|
|
|
|
|
|
-- Ensure no errors occur when unregistering something that was never really registered.
|
|
|
|
|
vim.lsp.handlers['client/unregisterCapability'](nil, {
|
|
|
|
|
unregisterations = {
|
|
|
|
|
{
|
|
|
|
|
id = 'watchfiles-test-kind',
|
|
|
|
|
method = 'workspace/didChangeWatchedFiles',
|
|
|
|
|
},
|
2023-05-19 22:45:39 -07:00
|
|
|
|
},
|
2023-08-03 23:10:54 -07:00
|
|
|
|
}, { client_id = client_id })
|
2023-05-19 22:45:39 -07:00
|
|
|
|
|
2023-08-03 23:10:54 -07:00
|
|
|
|
vim.lsp.stop_client(client_id, true)
|
2024-07-29 03:20:15 -07:00
|
|
|
|
return _G.watching
|
2024-08-11 01:27:48 -07:00
|
|
|
|
end)
|
2023-08-03 23:10:54 -07:00
|
|
|
|
end
|
2023-05-19 22:45:39 -07:00
|
|
|
|
|
2024-05-10 05:47:30 -07:00
|
|
|
|
eq(is_os('mac') or is_os('win'), check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
|
2023-08-03 23:10:54 -07:00
|
|
|
|
eq(
|
|
|
|
|
false,
|
|
|
|
|
check_registered({
|
|
|
|
|
workspace = {
|
|
|
|
|
didChangeWatchedFiles = {
|
|
|
|
|
dynamicRegistration = false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-08-03 23:10:54 -07:00
|
|
|
|
eq(
|
|
|
|
|
true,
|
|
|
|
|
check_registered({
|
|
|
|
|
workspace = {
|
|
|
|
|
didChangeWatchedFiles = {
|
|
|
|
|
dynamicRegistration = true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
2024-01-02 18:09:18 -07:00
|
|
|
|
)
|
2023-05-19 22:45:39 -07:00
|
|
|
|
end)
|
2023-03-04 23:52:27 -07:00
|
|
|
|
end)
|
2024-11-01 09:31:51 -07:00
|
|
|
|
|
|
|
|
|
describe('vim.lsp.config() and vim.lsp.enable()', function()
|
|
|
|
|
it('can merge settings from "*"', function()
|
|
|
|
|
eq(
|
|
|
|
|
{
|
|
|
|
|
name = 'foo',
|
|
|
|
|
cmd = { 'foo' },
|
|
|
|
|
root_markers = { '.git' },
|
|
|
|
|
},
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.config('*', { root_markers = { '.git' } })
|
|
|
|
|
vim.lsp.config('foo', { cmd = { 'foo' } })
|
|
|
|
|
|
|
|
|
|
return vim.lsp._resolve_config('foo')
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('sets up an autocmd', function()
|
|
|
|
|
eq(
|
|
|
|
|
1,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
vim.lsp.config('foo', {
|
|
|
|
|
cmd = { 'foo' },
|
|
|
|
|
root_markers = { '.foorc' },
|
|
|
|
|
})
|
|
|
|
|
vim.lsp.enable('foo')
|
|
|
|
|
return #vim.api.nvim_get_autocmds({
|
|
|
|
|
group = 'nvim.lsp.enable',
|
|
|
|
|
event = 'FileType',
|
|
|
|
|
})
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
it('attaches to buffers', function()
|
|
|
|
|
exec_lua(create_server_definition)
|
|
|
|
|
|
|
|
|
|
local tmp1 = t.tmpname(true)
|
|
|
|
|
local tmp2 = t.tmpname(true)
|
|
|
|
|
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
handlers = {
|
|
|
|
|
initialize = function(_, _, callback)
|
|
|
|
|
callback(nil, { capabilities = {} })
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
vim.lsp.config('foo', {
|
|
|
|
|
cmd = server.cmd,
|
|
|
|
|
filetypes = { 'foo' },
|
|
|
|
|
root_markers = { '.foorc' },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
vim.lsp.config('bar', {
|
|
|
|
|
cmd = server.cmd,
|
|
|
|
|
filetypes = { 'bar' },
|
|
|
|
|
root_markers = { '.foorc' },
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
vim.lsp.enable('foo')
|
|
|
|
|
vim.lsp.enable('bar')
|
|
|
|
|
|
|
|
|
|
vim.cmd.edit(tmp1)
|
|
|
|
|
vim.bo.filetype = 'foo'
|
|
|
|
|
_G.foo_buf = vim.api.nvim_get_current_buf()
|
|
|
|
|
|
|
|
|
|
vim.cmd.edit(tmp2)
|
|
|
|
|
vim.bo.filetype = 'bar'
|
|
|
|
|
_G.bar_buf = vim.api.nvim_get_current_buf()
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
eq(
|
|
|
|
|
{ 1, 'foo', 1, 'bar' },
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
local foos = vim.lsp.get_clients({ bufnr = assert(_G.foo_buf) })
|
|
|
|
|
local bars = vim.lsp.get_clients({ bufnr = assert(_G.bar_buf) })
|
|
|
|
|
return { #foos, foos[1].name, #bars, bars[1].name }
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
end)
|
2024-12-13 03:51:33 -07:00
|
|
|
|
|
|
|
|
|
it('does not attach to buffers more than once if no root_dir', function()
|
|
|
|
|
exec_lua(create_server_definition)
|
|
|
|
|
|
|
|
|
|
local tmp1 = t.tmpname(true)
|
|
|
|
|
|
|
|
|
|
eq(
|
|
|
|
|
1,
|
|
|
|
|
exec_lua(function()
|
|
|
|
|
local server = _G._create_server({
|
|
|
|
|
handlers = {
|
|
|
|
|
initialize = function(_, _, callback)
|
|
|
|
|
callback(nil, { capabilities = {} })
|
|
|
|
|
end,
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
vim.lsp.config('foo', { cmd = server.cmd, filetypes = { 'foo' } })
|
|
|
|
|
vim.lsp.enable('foo')
|
|
|
|
|
|
|
|
|
|
vim.cmd.edit(assert(tmp1))
|
|
|
|
|
vim.bo.filetype = 'foo'
|
|
|
|
|
vim.bo.filetype = 'foo'
|
|
|
|
|
|
|
|
|
|
return #vim.lsp.get_clients({ bufnr = vim.api.nvim_get_current_buf() })
|
|
|
|
|
end)
|
|
|
|
|
)
|
|
|
|
|
end)
|
2024-11-01 09:31:51 -07:00
|
|
|
|
end)
|
2020-04-20 08:35:54 -07:00
|
|
|
|
end)
|