aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin/lsp_spec.lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/plugin/lsp_spec.lua')
-rw-r--r--test/functional/plugin/lsp_spec.lua2834
1 files changed, 1660 insertions, 1174 deletions
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 56d31a0e44..4826153edb 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -11,19 +11,20 @@ local eq = helpers.eq
local eval = helpers.eval
local matches = helpers.matches
local pcall_err = helpers.pcall_err
-local pesc = helpers.pesc
+local pesc = vim.pesc
local insert = helpers.insert
-local funcs = helpers.funcs
+local fn = helpers.fn
local retry = helpers.retry
local stop = helpers.stop
-local NIL = helpers.NIL
+local NIL = vim.NIL
local read_file = require('test.helpers').read_file
local write_file = require('test.helpers').write_file
local is_ci = helpers.is_ci
-local meths = helpers.meths
+local api = helpers.api
local is_os = helpers.is_os
local skip = helpers.skip
local mkdir = helpers.mkdir
+local tmpname = helpers.tmpname
local clear_notrace = lsp_helpers.clear_notrace
local create_server_definition = lsp_helpers.create_server_definition
@@ -32,14 +33,16 @@ local fake_lsp_logfile = lsp_helpers.fake_lsp_logfile
local test_rpc_server = lsp_helpers.test_rpc_server
local function get_buf_option(name, bufnr)
- bufnr = bufnr or "BUFFER"
- return exec_lua(
- string.format("return vim.api.nvim_get_option_value('%s', { buf = %s })", name, bufnr)
- )
+ bufnr = bufnr or 'BUFFER'
+ return exec_lua(
+ string.format("return vim.api.nvim_get_option_value('%s', { buf = %s })", name, bufnr)
+ )
end
-- TODO(justinmk): hangs on Windows https://github.com/neovim/neovim/pull/11837
-if skip(is_os('win')) then return end
+if skip(is_os('win')) then
+ return
+end
teardown(function()
os.remove(fake_lsp_logfile)
@@ -51,8 +54,9 @@ describe('LSP', 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"
- exec_lua([=[
+ local test_name = 'basic_init'
+ exec_lua(
+ [=[
lsp = require('vim.lsp')
local test_name, fake_lsp_code, fake_lsp_logfile = ...
function test__start_client()
@@ -71,12 +75,16 @@ describe('LSP', function()
}
end
TEST_CLIENT1 = test__start_client()
- ]=], test_name, fake_lsp_code, fake_lsp_logfile)
+ ]=],
+ test_name,
+ fake_lsp_code,
+ fake_lsp_logfile
+ )
end)
after_each(function()
exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
- -- exec_lua("lsp.stop_all_clients(true)")
+ -- exec_lua("lsp.stop_all_clients(true)")
end)
describe('server_name specified', function()
@@ -84,14 +92,20 @@ describe('LSP', function()
retry(nil, 4000, function()
eq(1, exec_lua('return #lsp.get_clients()'))
end)
- eq(2, exec_lua([[
+ eq(
+ 2,
+ exec_lua([[
TEST_CLIENT2 = test__start_client()
return TEST_CLIENT2
- ]]))
- eq(3, exec_lua([[
+ ]])
+ )
+ eq(
+ 3,
+ exec_lua([[
TEST_CLIENT3 = test__start_client()
return TEST_CLIENT3
- ]]))
+ ]])
+ )
retry(nil, 4000, function()
eq(3, exec_lua('return #lsp.get_clients()'))
end)
@@ -125,80 +139,62 @@ describe('LSP', function()
end)
end)
end)
-
- describe('lsp._cmd_parts test', function()
- local function _cmd_parts(input)
- return exec_lua([[
- lsp = require('vim.lsp')
- return lsp._cmd_parts(...)
- ]], input)
- end
- it('should valid cmd argument', function()
- eq(true, pcall(_cmd_parts, {"nvim"}))
- eq(true, pcall(_cmd_parts, {"nvim", "--head"}))
- end)
-
- it('should invalid cmd argument', function()
- eq('.../lsp.lua:0: cmd: expected list, got nvim',
- pcall_err(_cmd_parts, 'nvim'))
- eq('.../lsp.lua:0: cmd argument: expected string, got number',
- pcall_err(_cmd_parts, {'nvim', 1}))
- end)
- end)
end)
describe('LSP', function()
describe('basic_init test', function()
after_each(function()
stop()
- exec_lua("lsp.stop_client(lsp.get_clients(), true)")
+ exec_lua('lsp.stop_client(lsp.get_clients(), true)')
exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
end)
it('should run correctly', function()
local expected_handlers = {
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client, _)
-- client is a dummy object which will queue up commands to be run
-- once the server initializes. It can't accept lua callbacks or
-- other types that may be unserializable for now.
client.stop()
- end;
+ end,
-- If the program timed out, then code will be nil.
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
-- Note that NIL must be used here.
-- on_handler(err, method, result, client_id)
on_handler = function(...)
- eq(table.remove(expected_handlers), {...})
- end;
+ eq(table.remove(expected_handlers), { ... })
+ end,
}
end)
it('should fail', function()
local expected_handlers = {
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client)
client.notify('test')
client.stop()
- end;
+ end,
on_exit = function(code, signal)
- eq(101, code, "exit code") -- See fake-lsp-server.lua
- eq(0, signal, "exit signal")
- assert_log(pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]),
- fake_lsp_logfile)
- end;
+ eq(101, code, 'exit code') -- See fake-lsp-server.lua
+ eq(0, signal, 'exit signal')
+ assert_log(
+ pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]),
+ fake_lsp_logfile
+ )
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
@@ -209,8 +205,8 @@ describe('LSP', function()
client.stop()
end,
on_exit = function(code, signal)
- eq(0, code, 'exit code', fake_lsp_logfile)
- eq(0, signal, 'exit signal', fake_lsp_logfile)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
end,
settings = {
dummy = 1,
@@ -218,10 +214,12 @@ describe('LSP', function()
})
end)
- it("should set the client's offset_encoding when positionEncoding capability is supported", function()
- clear()
- exec_lua(create_server_definition)
- local result = exec_lua([[
+ it(
+ "should set the client's offset_encoding when positionEncoding capability is supported",
+ function()
+ clear()
+ exec_lua(create_server_definition)
+ local result = exec_lua([[
local server = _create_server({
capabilities = {
positionEncoding = "utf-8"
@@ -243,8 +241,9 @@ describe('LSP', function()
end
return client.offset_encoding
]])
- eq('utf-8', result)
- end)
+ eq('utf-8', result)
+ end
+ )
it('should succeed with manual shutdown', function()
if is_ci() then
@@ -254,68 +253,68 @@ describe('LSP', function()
return
end
local expected_handlers = {
- {NIL, {}, {method="shutdown", bufnr=1, client_id=1}};
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client)
eq(0, client.server_capabilities().textDocumentSync.change)
client.request('shutdown')
client.notify('exit')
client.stop()
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
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}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_finish";
+ test_name = 'basic_finish',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
]]
- eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
- eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
+ eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)'))
+ eq(true, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)'))
exec_lua [[
vim.api.nvim_command(BUFFER.."bwipeout")
]]
- end;
+ end,
on_init = function(_client)
client = _client
client.notify('finish')
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ 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")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
- exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)")
- eq(false, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
+ exec_lua('return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)')
+ eq(false, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)'))
client.stop()
end
- end;
+ end,
}
end)
it('should fire autocommands on attach and detach', function()
local client
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -332,69 +331,75 @@ describe('LSP', function()
end,
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
+ eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)'))
client.notify('finish')
- end;
+ end,
on_handler = function(_, _, ctx)
if ctx.method == 'finish' then
- eq('basic_init', meths.get_var('lsp_attached'))
- exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)")
- eq('basic_init', meths.get_var('lsp_detached'))
+ eq('basic_init', api.nvim_get_var('lsp_attached'))
+ exec_lua('return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)')
+ eq('basic_init', api.nvim_get_var('lsp_detached'))
client.stop()
end
- end;
+ end,
}
end)
it('should set default options on attach', function()
local client
test_rpc_server {
- test_name = "set_defaults_all_capabilities";
+ test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
client = _client
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
]]
- end;
+ 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"))
- eq('', get_buf_option("keywordprg"))
- eq(true, exec_lua[[
+ 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'))
+ eq('', get_buf_option('keywordprg'))
+ eq(
+ true,
+ exec_lua [[
local keymap
vim.api.nvim_buf_call(BUFFER, function()
keymap = vim.fn.maparg("K", "n", false, true)
end)
return keymap.callback == vim.lsp.buf.hover
- ]])
+ ]]
+ )
client.stop()
end
- end;
+ end,
on_exit = function(_, _)
- eq('', get_buf_option("tagfunc"))
- eq('', get_buf_option("omnifunc"))
- eq('', get_buf_option("formatexpr"))
- eq('', exec_lua[[
+ eq('', get_buf_option('tagfunc'))
+ eq('', get_buf_option('omnifunc'))
+ eq('', get_buf_option('formatexpr'))
+ eq(
+ '',
+ exec_lua [[
local keymap
vim.api.nvim_buf_call(BUFFER, function()
keymap = vim.fn.maparg("K", "n", false, false)
end)
return keymap
- ]])
- end;
+ ]]
+ )
+ end,
}
end)
it('should overwrite options set by ftplugins', function()
local client
test_rpc_server {
- test_name = "set_defaults_all_capabilities";
+ test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
client = _client
exec_lua [[
@@ -406,35 +411,35 @@ describe('LSP', function()
]]
-- Sanity check to ensure that some values are set after setting filetype.
- 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"))
+ 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'))
exec_lua [[
lsp.buf_attach_client(BUFFER_1, TEST_RPC_CLIENT_ID)
lsp.buf_attach_client(BUFFER_2, TEST_RPC_CLIENT_ID)
]]
- end;
+ end,
on_handler = function(_, _, ctx)
if ctx.method == 'test' then
- 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"))
+ 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'))
client.stop()
end
- end;
+ end,
on_exit = function(_, _)
- eq('', get_buf_option("tagfunc", "BUFFER_1"))
- eq('', get_buf_option("omnifunc", "BUFFER_2"))
- eq('', get_buf_option("formatexpr", "BUFFER_2"))
- end;
+ eq('', get_buf_option('tagfunc', 'BUFFER_1'))
+ eq('', get_buf_option('omnifunc', 'BUFFER_2'))
+ eq('', get_buf_option('formatexpr', 'BUFFER_2'))
+ end,
}
end)
it('should not overwrite user-defined options', function()
local client
test_rpc_server {
- test_name = "set_defaults_all_capabilities";
+ test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
client = _client
exec_lua [[
@@ -444,20 +449,20 @@ describe('LSP', function()
vim.api.nvim_set_option_value('formatexpr', 'fex', { buf = BUFFER })
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
]]
- end;
+ 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"))
+ eq('tfu', get_buf_option('tagfunc'))
+ eq('ofu', get_buf_option('omnifunc'))
+ eq('fex', get_buf_option('formatexpr'))
client.stop()
end
- end;
+ end,
on_exit = function(_, _)
- eq('tfu', get_buf_option("tagfunc"))
- eq('ofu', get_buf_option("omnifunc"))
- eq('fex', get_buf_option("formatexpr"))
- end;
+ eq('tfu', get_buf_option('tagfunc'))
+ eq('ofu', get_buf_option('omnifunc'))
+ eq('fex', get_buf_option('formatexpr'))
+ end,
}
end)
@@ -481,62 +486,76 @@ describe('LSP', function()
num_attached_after = num_attached_after,
}
]])
- eq(true, result ~= nil, "exec_lua must return result")
+ eq(true, result ~= nil, 'exec_lua must return result')
eq(1, result.num_attached_before)
eq(0, result.num_attached_after)
end)
it('client should return settings via workspace/configuration handler', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, { items = {
- { section = "testSetting1" };
- { section = "testSetting2" };
- { section = "test.Setting3" };
- { section = "test.Setting4" };
- }}, { method="workspace/configuration", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ {
+ NIL,
+ {
+ items = {
+ { section = 'testSetting1' },
+ { section = 'testSetting2' },
+ { section = 'test.Setting3' },
+ { section = 'test.Setting4' },
+ },
+ },
+ { method = 'workspace/configuration', client_id = 1 },
+ },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_workspace_configuration";
+ test_name = 'check_workspace_configuration',
on_init = function(_client)
client = _client
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ 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")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'start' then
exec_lua([=[
local client = vim.lsp.get_client_by_id(TEST_RPC_CLIENT_ID)
- client.config.settings = {
+ client.settings = {
testSetting1 = true;
testSetting2 = false;
test = {Setting3 = 'nested' };
}]=])
end
if ctx.method == 'workspace/configuration' then
- local server_result = exec_lua([=[
+ local server_result = exec_lua(
+ [=[
local method, params = ...
- return require'vim.lsp.handlers'['workspace/configuration'](err, params, {method=method, client_id=TEST_RPC_CLIENT_ID})]=], ctx.method, result)
+ return require'vim.lsp.handlers'['workspace/configuration'](err, params, {method=method, client_id=TEST_RPC_CLIENT_ID})]=],
+ ctx.method,
+ result
+ )
client.notify('workspace/configuration', server_result)
end
if ctx.method == 'shutdown' then
client.stop()
end
- end;
+ end,
}
end)
- it('workspace/configuration returns NIL per section if client was started without config.settings', function()
- local result = nil
- test_rpc_server {
- test_name = 'basic_init';
- on_init = function(c) c.stop() end,
- on_setup = function()
- result = exec_lua [[
+ it(
+ 'workspace/configuration returns NIL per section if client was started without config.settings',
+ function()
+ local result = nil
+ test_rpc_server {
+ test_name = 'basic_init',
+ on_init = function(c)
+ c.stop()
+ end,
+ on_setup = function()
+ result = exec_lua [[
local result = {
items = {
{section = 'foo'},
@@ -545,52 +564,53 @@ describe('LSP', function()
}
return vim.lsp.handlers['workspace/configuration'](nil, result, {client_id=TEST_RPC_CLIENT_ID})
]]
- end
- }
- eq({ NIL, NIL }, result)
- end)
+ end,
+ }
+ eq({ NIL, NIL }, result)
+ end
+ )
it('should verify capabilities sent', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_check_capabilities";
+ test_name = 'basic_check_capabilities',
on_init = function(client)
client.stop()
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
eq(full_kind, client.server_capabilities().textDocumentSync.change)
- eq({includeText = false}, client.server_capabilities().textDocumentSync.save)
+ eq({ includeText = false }, client.server_capabilities().textDocumentSync.save)
eq(false, client.server_capabilities().codeLensProvider)
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
it('BufWritePost sends didSave with bool textDocumentSync.save', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "text_document_sync_save_bool";
+ test_name = 'text_document_sync_save_bool',
on_init = function(c)
client = c
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ 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
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
+ if ctx.method == 'start' then
exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
@@ -599,7 +619,7 @@ describe('LSP', function()
else
client.stop()
end
- end;
+ end,
}
end)
@@ -664,7 +684,7 @@ describe('LSP', function()
local messages = result.messages
eq('textDocument/willSave', messages[3].method)
eq('textDocument/willSaveWaitUntil', messages[4].method)
- eq({'Hello'}, result.lines)
+ eq({ 'Hello' }, result.lines)
end)
it('saveas sends didOpen if filename changed', function()
@@ -685,8 +705,8 @@ describe('LSP', function()
on_handler = function(err, result, ctx)
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'start' then
- local tmpfile_old = helpers.tmpname()
- local tmpfile_new = helpers.tmpname()
+ local tmpfile_old = tmpname()
+ local tmpfile_new = tmpname()
os.remove(tmpfile_new)
exec_lua(
[=[
@@ -709,22 +729,22 @@ describe('LSP', function()
it('BufWritePost sends didSave including text if server capability is set', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "text_document_sync_save_includeText";
+ test_name = 'text_document_sync_save_includeText',
on_init = function(c)
client = c
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ 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
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
+ if ctx.method == 'start' then
exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_set_lines(BUFFER, 0, -1, true, {"help me"})
@@ -734,16 +754,16 @@ describe('LSP', function()
else
client.stop()
end
- end;
+ end,
}
end)
it('client.supports_methods() should validate capabilities', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
}
test_rpc_server {
- test_name = "capabilities_for_client_supports_method";
+ test_name = 'capabilities_for_client_supports_method',
on_init = function(client)
client.stop()
local expected_sync_capabilities = {
@@ -761,268 +781,285 @@ describe('LSP', function()
eq(true, client.server_capabilities().codeLensProvider.resolveProvider)
-- known methods for resolved capabilities
- eq(true, client.supports_method("textDocument/hover"))
- eq(false, client.supports_method("textDocument/definition"))
+ eq(true, client.supports_method('textDocument/hover'))
+ eq(false, client.supports_method('textDocument/definition'))
-- unknown methods are assumed to be supported.
- eq(true, client.supports_method("unknown-method"))
- end;
+ eq(true, client.supports_method('unknown-method'))
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
it('should not call unsupported_method when trying to call an unsupported method', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
}
test_rpc_server {
- test_name = "capabilities_for_client_supports_method";
+ test_name = 'capabilities_for_client_supports_method',
on_setup = function()
- exec_lua([=[
+ exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
vim.lsp.handlers['textDocument/typeDefinition'] = function() end
]=])
- end;
+ end,
on_init = function(client)
client.stop()
- exec_lua("vim.lsp.buf.type_definition()")
+ exec_lua('vim.lsp.buf.type_definition()')
exec_lua [[
vim.api.nvim_command(BUFFER.."bwipeout")
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
- it('should not call unsupported_method when no client and trying to call an unsupported method', function()
- local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- }
- test_rpc_server {
- test_name = "capabilities_for_client_supports_method";
- on_setup = function()
+ it(
+ 'should not call unsupported_method when no client and trying to call an unsupported method',
+ function()
+ local expected_handlers = {
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ }
+ test_rpc_server {
+ test_name = 'capabilities_for_client_supports_method',
+ on_setup = function()
exec_lua([=[
vim.lsp.handlers['textDocument/typeDefinition'] = function() end
]=])
- end;
- on_init = function(client)
- client.stop()
- exec_lua("vim.lsp.buf.type_definition()")
- end;
- on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
- on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
- }
- end)
+ end,
+ on_init = function(client)
+ client.stop()
+ exec_lua('vim.lsp.buf.type_definition()')
+ end,
+ on_exit = function(code, signal)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
+ on_handler = function(...)
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
+ }
+ end
+ )
it('should not forward RequestCancelled to callback', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_forward_request_cancelled";
+ test_name = 'check_forward_request_cancelled',
on_init = function(_client)
- _client.request("error_code_test")
+ _client.request('error_code_test')
client = _client
- end;
+ 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;
+ 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.stop() end
- end;
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should forward ContentModified to callback', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {{code = -32801}, NIL, {method = "error_code_test", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { { code = -32801 }, NIL, { method = 'error_code_test', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_forward_content_modified";
+ test_name = 'check_forward_content_modified',
on_init = function(_client)
- _client.request("error_code_test")
+ _client.request('error_code_test')
client = _client
- end;
+ 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;
+ 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")
+ eq(table.remove(expected_handlers), { err, _, ctx }, 'expected handler')
-- if ctx.method == 'error_code_test' then client.notify("finish") end
- if ctx.method ~= 'finish' then client.notify('finish') end
- if ctx.method == 'finish' then client.stop() end
- end;
+ if ctx.method ~= 'finish' then
+ client.notify('finish')
+ end
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should track pending requests to the language server', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="slow_request", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_pending_request_tracked";
+ test_name = 'check_pending_request_tracked',
on_init = function(_client)
client = _client
- client.request("slow_request")
+ client.request('slow_request')
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("pending", request.type)
- client.notify("release")
- end;
+ eq('slow_request', request.method)
+ eq('pending', request.type)
+ client.notify('release')
+ 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;
+ 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")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
if ctx.method == 'slow_request' then
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
eq(NIL, request)
- client.notify("finish")
+ client.notify('finish')
+ end
+ if ctx.method == 'finish' then
+ client.stop()
end
- if ctx.method == 'finish' then client.stop() end
- end;
+ end,
}
end)
it('should track cancel requests to the language server', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_cancel_request_tracked";
+ test_name = 'check_cancel_request_tracked',
on_init = function(_client)
client = _client
- client.request("slow_request")
+ client.request('slow_request')
client.cancel_request(2)
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("cancel", request.type)
- client.notify("release")
- end;
+ eq('slow_request', request.method)
+ eq('cancel', request.type)
+ client.notify('release')
+ 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;
+ 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")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
eq(NIL, request)
- if ctx.method == 'finish' then client.stop() end
- end;
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should clear pending and cancel requests on reply', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="slow_request", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_tracked_requests_cleared";
+ test_name = 'check_tracked_requests_cleared',
on_init = function(_client)
client = _client
- client.request("slow_request")
+ client.request('slow_request')
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("pending", request.type)
+ eq('slow_request', request.method)
+ eq('pending', request.type)
client.cancel_request(2)
request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("cancel", request.type)
- client.notify("release")
- end;
+ eq('slow_request', request.method)
+ eq('cancel', request.type)
+ client.notify('release')
+ 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;
+ 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")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
if ctx.method == 'slow_request' then
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
eq(NIL, request)
- client.notify("finish")
+ client.notify('finish')
end
- if ctx.method == 'finish' then client.stop() end
- end;
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should trigger LspRequest autocmd when requests table changes', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="slow_request", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_tracked_requests_cleared";
+ test_name = 'check_tracked_requests_cleared',
on_init = function(_client)
command('let g:requests = 0')
command('autocmd LspRequest * let g:requests+=1')
client = _client
- client.request("slow_request")
+ client.request('slow_request')
eq(1, eval('g:requests'))
client.cancel_request(2)
eq(2, eval('g:requests'))
- client.notify("release")
- end;
+ client.notify('release')
+ 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")
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ eq(0, #expected_handlers, 'did not call expected handler')
eq(3, eval('g:requests'))
- end;
+ end,
on_handler = function(err, _, ctx)
- eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
if ctx.method == 'slow_request' then
- client.notify("finish")
+ client.notify('finish')
+ end
+ if ctx.method == 'finish' then
+ client.stop()
end
- if ctx.method == 'finish' then client.stop() end
- end;
+ end,
}
end)
it('should not send didOpen if the buffer closes before init', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_finish";
+ test_name = 'basic_finish',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1031,42 +1068,42 @@ describe('LSP', function()
"123";
})
]]
- eq(1, exec_lua("return TEST_RPC_CLIENT_ID"))
- eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
- eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
+ eq(1, exec_lua('return TEST_RPC_CLIENT_ID'))
+ eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)'))
+ eq(true, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)'))
exec_lua [[
vim.api.nvim_command(BUFFER.."bwipeout")
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
eq(full_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
client.notify('finish')
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ 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")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body sent attaching before init', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open";
+ test_name = 'basic_check_buffer_open',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1078,7 +1115,7 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1087,32 +1124,32 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID), "Already attached, returns true")
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body sent attaching after init', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open";
+ test_name = 'basic_check_buffer_open',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1121,7 +1158,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1130,32 +1167,32 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change";
+ test_name = 'basic_check_buffer_open_and_change',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1164,7 +1201,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1173,11 +1210,11 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1187,23 +1224,23 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full with noeol', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_noeol";
+ test_name = 'basic_check_buffer_open_and_change_noeol',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1213,7 +1250,7 @@ describe('LSP', function()
})
vim.bo[BUFFER].eol = false
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1222,11 +1259,11 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1236,37 +1273,41 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should send correct range for inlay hints with noeol', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {
- method="textDocument/inlayHint",
- params = {
- textDocument = {
- uri = 'file://',
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ {
+ NIL,
+ {},
+ {
+ method = 'textDocument/inlayHint',
+ params = {
+ textDocument = {
+ uri = 'file://',
+ },
+ range = {
+ start = { line = 0, character = 0 },
+ ['end'] = { line = 1, character = 3 },
+ },
},
- range = {
- start = { line = 0, character = 0 },
- ['end'] = { line = 1, character = 3 },
- }
+ bufnr = 2,
+ client_id = 1,
},
- bufnr=2,
- client_id=1,
- }};
- {NIL, {}, {method="start", client_id=1}};
+ },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "inlay_hint";
+ test_name = 'inlay_hint',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1276,18 +1317,18 @@ describe('LSP', function()
})
vim.bo[BUFFER].eol = false
]]
- end;
+ end,
on_init = function(_client)
client = _client
eq(true, client.supports_method('textDocument/inlayHint'))
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1297,26 +1338,26 @@ describe('LSP', function()
if ctx.method == 'textDocument/inlayHint' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange incremental', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_incremental";
+ test_name = 'basic_check_buffer_open_and_change_incremental',
options = {
allow_incremental_sync = true,
- };
+ },
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1325,20 +1366,21 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
+ local sync_kind =
+ exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1348,26 +1390,26 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
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}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_incremental";
+ test_name = 'basic_check_buffer_open_and_change_incremental',
options = {
allow_incremental_sync = true,
- debounce_text_changes = 5
- };
+ debounce_text_changes = 5,
+ },
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1376,20 +1418,21 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
+ local sync_kind =
+ exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1399,24 +1442,24 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
-- TODO(askhan) we don't support full for now, so we can disable these tests.
pending('should check the body and didChange incremental normal mode editing', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", bufnr=1, client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_incremental_editing";
+ test_name = 'basic_check_buffer_open_and_change_incremental_editing',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1425,42 +1468,43 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
+ local sync_kind =
+ exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
- helpers.command("normal! 1Go")
+ helpers.command('normal! 1Go')
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full with 2 changes', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_multi";
+ test_name = 'basic_check_buffer_open_and_change_multi',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1469,7 +1513,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1478,11 +1522,11 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1495,23 +1539,23 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full lifecycle', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_multi_and_close";
+ test_name = 'basic_check_buffer_open_and_change_multi_and_close',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1520,7 +1564,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1529,12 +1573,12 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
- on_handler = function(err, result,ctx)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
+ on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
@@ -1547,55 +1591,58 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
end)
- describe("parsing tests", function()
+ describe('parsing tests', function()
it('should handle invalid content-length correctly', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "invalid_header";
- on_setup = function()
- end;
+ test_name = 'invalid_header',
+ on_setup = function() end,
on_init = function(_client)
client = _client
client.stop(true)
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ 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")
- end;
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
+ end,
}
end)
it('should not trim vim.NIL from the end of a list', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL,{
- arguments = { "EXTRACT_METHOD", {metadata = {}}, 3, 0, 6123, NIL },
- command = "refactor.perform",
- title = "EXTRACT_METHOD"
- }, {method="workspace/executeCommand", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ {
+ NIL,
+ {
+ arguments = { 'EXTRACT_METHOD', { metadata = {} }, 3, 0, 6123, NIL },
+ command = 'refactor.perform',
+ title = 'EXTRACT_METHOD',
+ },
+ { method = 'workspace/executeCommand', client_id = 1 },
+ },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "decode_nil";
+ test_name = 'decode_nil',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1604,23 +1651,23 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ 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")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
end)
@@ -1634,10 +1681,10 @@ describe('LSP', function()
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 "");
+ 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
@@ -1652,121 +1699,121 @@ describe('LSP', function()
end)
it('applies simple edits', function()
local edits = {
- make_edit(0, 0, 0, 0, {"123"});
- make_edit(1, 0, 1, 1, {"2"});
- make_edit(2, 0, 2, 2, {"3"});
- make_edit(3, 2, 3, 4, {""});
+ make_edit(0, 0, 0, 0, { '123' }),
+ make_edit(1, 0, 1, 1, { '2' }),
+ make_edit(2, 0, 2, 2, { '3' }),
+ make_edit(3, 2, 3, 4, { '' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- '123First line of text';
- '2econd line of text';
- '3ird line of text';
- 'Foth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ '123First line of text',
+ '2econd line of text',
+ '3ird line of text',
+ 'Foth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies complex edits', function()
local edits = {
- make_edit(0, 0, 0, 0, {"", "12"});
- make_edit(0, 0, 0, 0, {"3", "foo"});
- make_edit(0, 1, 0, 1, {"bar", "123"});
- make_edit(0, #"First ", 0, #"First line of text", {"guy"});
- make_edit(1, 0, 1, #'Second', {"baz"});
- make_edit(2, #'Th', 2, #"Third", {"e next"});
- make_edit(3, #'', 3, #"Fourth", {"another line of text", "before this"});
- make_edit(3, #'Fourth', 3, #"Fourth line of text", {"!"});
+ make_edit(0, 0, 0, 0, { '', '12' }),
+ make_edit(0, 0, 0, 0, { '3', 'foo' }),
+ make_edit(0, 1, 0, 1, { 'bar', '123' }),
+ make_edit(0, #'First ', 0, #'First line of text', { 'guy' }),
+ make_edit(1, 0, 1, #'Second', { 'baz' }),
+ make_edit(2, #'Th', 2, #'Third', { 'e next' }),
+ make_edit(3, #'', 3, #'Fourth', { 'another line of text', 'before this' }),
+ make_edit(3, #'Fourth', 3, #'Fourth line of text', { '!' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- '';
- '123';
- 'fooFbar';
- '123irst guy';
- 'baz line of text';
- 'The next line of text';
- 'another line of text';
- 'before this!';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ '',
+ '123',
+ 'fooFbar',
+ '123irst guy',
+ 'baz line of text',
+ 'The next line of text',
+ 'another line of text',
+ 'before this!',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies complex edits (reversed range)', function()
local edits = {
- make_edit(0, 0, 0, 0, {"", "12"});
- make_edit(0, 0, 0, 0, {"3", "foo"});
- make_edit(0, 1, 0, 1, {"bar", "123"});
- make_edit(0, #"First line of text", 0, #"First ", {"guy"});
- make_edit(1, #'Second', 1, 0, {"baz"});
- make_edit(2, #"Third", 2, #'Th', {"e next"});
- make_edit(3, #"Fourth", 3, #'', {"another line of text", "before this"});
- make_edit(3, #"Fourth line of text", 3, #'Fourth', {"!"});
+ make_edit(0, 0, 0, 0, { '', '12' }),
+ make_edit(0, 0, 0, 0, { '3', 'foo' }),
+ make_edit(0, 1, 0, 1, { 'bar', '123' }),
+ make_edit(0, #'First line of text', 0, #'First ', { 'guy' }),
+ make_edit(1, #'Second', 1, 0, { 'baz' }),
+ make_edit(2, #'Third', 2, #'Th', { 'e next' }),
+ make_edit(3, #'Fourth', 3, #'', { 'another line of text', 'before this' }),
+ make_edit(3, #'Fourth line of text', 3, #'Fourth', { '!' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- '';
- '123';
- 'fooFbar';
- '123irst guy';
- 'baz line of text';
- 'The next line of text';
- 'another line of text';
- 'before this!';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ '',
+ '123',
+ 'fooFbar',
+ '123irst guy',
+ 'baz line of text',
+ 'The next line of text',
+ 'another line of text',
+ 'before this!',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies non-ASCII characters edits', function()
local edits = {
- make_edit(4, 3, 4, 4, {"ä"});
+ make_edit(4, 3, 4, 4, { 'ä' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å ä ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å ä ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies text edits at the end of the document', function()
local edits = {
- make_edit(5, 0, 5, 0, "foobar");
+ make_edit(5, 0, 5, 0, 'foobar'),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
- 'foobar';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
+ 'foobar',
}, buf_lines(1))
end)
it('applies multiple text edits at the end of the document', function()
local edits = {
- make_edit(4, 0, 5, 0, "");
- make_edit(5, 0, 5, 0, "foobar");
+ make_edit(4, 0, 5, 0, ''),
+ make_edit(5, 0, 5, 0, 'foobar'),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'foobar';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'foobar',
}, buf_lines(1))
end)
it('it restores marks', function()
local edits = {
- make_edit(1, 0, 2, 5, "foobar");
- make_edit(4, 0, 5, 0, "barfoo");
+ make_edit(1, 0, 2, 5, 'foobar'),
+ make_edit(4, 0, 5, 0, 'barfoo'),
}
eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 1, {})'))
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'foobar line of text';
- 'Fourth line of text';
- 'barfoo';
+ 'First line of text',
+ 'foobar line of text',
+ 'Fourth line of text',
+ 'barfoo',
}, buf_lines(1))
local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
eq({ 2, 1 }, mark)
@@ -1774,16 +1821,16 @@ describe('LSP', function()
it('it restores marks to last valid col', function()
local edits = {
- make_edit(1, 0, 2, 15, "foobar");
- make_edit(4, 0, 5, 0, "barfoo");
+ make_edit(1, 0, 2, 15, 'foobar'),
+ make_edit(4, 0, 5, 0, 'barfoo'),
}
eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 10, {})'))
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'foobarext';
- 'Fourth line of text';
- 'barfoo';
+ 'First line of text',
+ 'foobarext',
+ 'Fourth line of text',
+ 'barfoo',
}, buf_lines(1))
local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
eq({ 2, 9 }, mark)
@@ -1791,138 +1838,138 @@ describe('LSP', function()
it('it restores marks to last valid line', function()
local edits = {
- make_edit(1, 0, 4, 5, "foobar");
- make_edit(4, 0, 5, 0, "barfoo");
+ make_edit(1, 0, 4, 5, 'foobar'),
+ make_edit(4, 0, 5, 0, 'barfoo'),
}
eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 4, 1, {})'))
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'foobaro';
+ 'First line of text',
+ 'foobaro',
}, buf_lines(1))
local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
eq({ 2, 1 }, mark)
end)
describe('cursor position', function()
- it('don\'t fix the cursor if the range contains the cursor', function()
- funcs.nvim_win_set_cursor(0, { 2, 6 })
+ it("don't fix the cursor if the range contains the cursor", function()
+ fn.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
- make_edit(1, 0, 1, 19, 'Second line of text')
+ make_edit(1, 0, 1, 19, 'Second line of text'),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 6 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 6 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor to the valid col if the content was removed', function()
- funcs.nvim_win_set_cursor(0, { 2, 6 })
+ fn.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
make_edit(1, 0, 1, 6, ''),
- make_edit(1, 6, 1, 19, '')
+ make_edit(1, 6, 1, 19, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- '';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ '',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 0 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 0 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor to the valid row if the content was removed', function()
- funcs.nvim_win_set_cursor(0, { 2, 6 })
+ fn.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
make_edit(1, 0, 1, 6, ''),
- make_edit(0, 18, 5, 0, '')
+ make_edit(0, 18, 5, 0, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
+ 'First line of text',
}, buf_lines(1))
- eq({ 1, 17 }, funcs.nvim_win_get_cursor(0))
+ eq({ 1, 17 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor row', function()
- funcs.nvim_win_set_cursor(0, { 3, 0 })
+ fn.nvim_win_set_cursor(0, { 3, 0 })
local edits = {
- make_edit(1, 0, 2, 0, '')
+ make_edit(1, 0, 2, 0, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 0 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 0 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor col', function()
-- append empty last line. See #22636
- exec_lua('vim.api.nvim_buf_set_lines(...)', 1, -1, -1, true, {''})
+ exec_lua('vim.api.nvim_buf_set_lines(...)', 1, -1, -1, true, { '' })
- funcs.nvim_win_set_cursor(0, { 2, 11 })
+ fn.nvim_win_set_cursor(0, { 2, 11 })
local edits = {
- make_edit(1, 7, 1, 11, '')
+ make_edit(1, 7, 1, 11, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
- '';
+ 'First line of text',
+ 'Second of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
+ '',
}, buf_lines(1))
- eq({ 2, 7 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 7 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor row and col', function()
- funcs.nvim_win_set_cursor(0, { 2, 12 })
+ fn.nvim_win_set_cursor(0, { 2, 12 })
local edits = {
- make_edit(0, 11, 1, 12, '')
+ make_edit(0, 11, 1, 12, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 1, 11 }, funcs.nvim_win_get_cursor(0))
+ eq({ 1, 11 }, fn.nvim_win_get_cursor(0))
end)
end)
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()
local edits = {
- make_edit(0, 0, 5, 0, {"All replaced"});
+ make_edit(0, 0, 5, 0, { 'All replaced' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
- eq({'All replaced'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
+ eq({ 'All replaced' }, buf_lines(1))
end)
- it('applies edits when the end line is 2 larger than vim\'s', function()
+ it("applies edits when the end line is 2 larger than vim's", function()
local edits = {
- make_edit(0, 0, 6, 0, {"All replaced"});
+ make_edit(0, 0, 6, 0, { 'All replaced' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
- eq({'All replaced'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
+ eq({ 'All replaced' }, buf_lines(1))
end)
it('applies edits with a column offset', function()
local edits = {
- make_edit(0, 0, 5, 2, {"All replaced"});
+ make_edit(0, 0, 5, 2, { 'All replaced' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
- eq({'All replaced'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
+ eq({ 'All replaced' }, buf_lines(1))
end)
end)
end)
@@ -1936,33 +1983,39 @@ describe('LSP', function()
describe('with LSP end column out of bounds and start column at 0', function()
it('applies edits at the end of the buffer', function()
local edits = {
- make_edit(0, 0, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 0, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'#include "whatever.h"', '#include <algorithm>'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq({ '#include "whatever.h"', '#include <algorithm>' }, buf_lines(1))
end)
it('applies edits in the middle of the buffer', function()
local edits = {
- make_edit(0, 0, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 0, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq(
+ { '#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' },
+ buf_lines(1)
+ )
end)
end)
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()
local edits = {
- make_edit(0, 2, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 2, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'Te#include "whatever.h"', '#include <algorithm>'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq({ 'Te#include "whatever.h"', '#include <algorithm>' }, buf_lines(1))
end)
it('applies edits in the middle of the buffer', function()
local edits = {
- make_edit(0, 2, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 2, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq(
+ { 'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' },
+ buf_lines(1)
+ )
end)
end)
end)
@@ -1972,12 +2025,12 @@ describe('LSP', function()
local text_document_edit = function(editVersion)
return {
edits = {
- make_edit(0, 0, 0, 3, "First ↥ 🤦 🦄")
+ make_edit(0, 0, 0, 3, 'First ↥ 🤦 🦄'),
},
textDocument = {
- uri = "file:///fake/uri";
- version = editVersion
- }
+ uri = 'file:///fake/uri',
+ version = editVersion,
+ },
}
end
before_each(function()
@@ -1991,49 +2044,63 @@ describe('LSP', function()
it('correctly goes ahead with the edit if all is normal', function()
exec_lua("vim.lsp.util.apply_text_document_edit(..., nil, 'utf-16')", text_document_edit(5))
eq({
- 'First ↥ 🤦 🦄 line of text';
- '2nd line of 语text';
+ 'First ↥ 🤦 🦄 line of text',
+ '2nd line of 语text',
}, buf_lines(target_bufnr))
end)
it('always accepts edit with version = 0', function()
- exec_lua([[
+ exec_lua(
+ [[
local args = {...}
local bufnr = select(1, ...)
local text_edit = select(2, ...)
vim.lsp.util.buf_versions[bufnr] = 10
vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16')
- ]], target_bufnr, text_document_edit(0))
+ ]],
+ target_bufnr,
+ text_document_edit(0)
+ )
eq({
- 'First ↥ 🤦 🦄 line of text';
- '2nd line of 语text';
+ 'First ↥ 🤦 🦄 line of text',
+ '2nd line of 语text',
}, buf_lines(target_bufnr))
end)
it('skips the edit if the version of the edit is behind the local buffer ', function()
local apply_edit_mocking_current_version = function(edit, versionedBuf)
- exec_lua([[
+ exec_lua(
+ [[
local args = {...}
local versionedBuf = args[2]
vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion
vim.lsp.util.apply_text_document_edit(args[1], nil, 'utf-16')
- ]], edit, versionedBuf)
+ ]],
+ edit,
+ versionedBuf
+ )
end
local baseText = {
- '1st line of text';
- '2nd line of 语text';
+ '1st line of text',
+ '2nd line of 语text',
}
eq(baseText, buf_lines(target_bufnr))
-- Apply an edit for an old version, should skip
- apply_edit_mocking_current_version(text_document_edit(2), {currentVersion=7; bufnr=target_bufnr})
+ apply_edit_mocking_current_version(
+ text_document_edit(2),
+ { currentVersion = 7, bufnr = target_bufnr }
+ )
eq(baseText, buf_lines(target_bufnr)) -- no change
-- Sanity check that next version to current does apply change
- apply_edit_mocking_current_version(text_document_edit(8), {currentVersion=7; bufnr=target_bufnr})
+ apply_edit_mocking_current_version(
+ text_document_edit(8),
+ { currentVersion = 7, bufnr = target_bufnr }
+ )
eq({
- 'First ↥ 🤦 🦄 line of text';
- '2nd line of 语text';
+ 'First ↥ 🤦 🦄 line of text',
+ '2nd line of 语text',
}, buf_lines(target_bufnr))
end)
end)
@@ -2041,34 +2108,37 @@ describe('LSP', function()
describe('workspace_apply_edit', function()
it('workspace/applyEdit returns ApplyWorkspaceEditResponse', function()
local expected_handlers = {
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client, _)
client.stop()
- end;
+ end,
-- If the program timed out, then code will be nil.
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
-- Note that NIL must be used here.
-- on_handler(err, method, result, client_id)
on_handler = function(...)
local expected = {
- applied = true;
- failureReason = nil;
+ applied = true,
+ failureReason = nil,
}
- eq(expected, exec_lua [[
+ eq(
+ expected,
+ exec_lua [[
local apply_edit = {
label = nil;
edit = {};
}
return vim.lsp.handlers['workspace/applyEdit'](nil, apply_edit, {client_id = TEST_RPC_CLIENT_ID})
- ]])
- eq(table.remove(expected_handlers), {...})
- end;
+ ]]
+ )
+ eq(table.remove(expected_handlers), { ... })
+ end,
}
end)
end)
@@ -2078,12 +2148,12 @@ describe('LSP', function()
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)
+ make_edit(row, 0, row, 1000, new_line),
},
textDocument = {
- uri = "file:///fake/uri";
- version = editVersion
- }
+ uri = 'file:///fake/uri',
+ version = editVersion,
+ },
}
end
@@ -2091,7 +2161,7 @@ describe('LSP', function()
-- We should not stop applying the edits
local make_workspace_edit = function(changes)
return {
- documentChanges = changes
+ documentChanges = changes,
}
end
@@ -2127,7 +2197,7 @@ describe('LSP', function()
it('apply_workspace_edit applies a single edit', function()
local new_lines = {
- "First Line",
+ 'First Line',
}
local edits = {}
@@ -2135,10 +2205,13 @@ describe('LSP', function()
table.insert(edits, replace_line_edit(row - 1, line, changedtick))
end
- eq({
- "First Line",
- "Original Line #2",
- }, exec_lua([[
+ eq(
+ {
+ 'First Line',
+ 'Original Line #2',
+ },
+ exec_lua(
+ [[
local args = {...}
local workspace_edits = args[1]
local target_bufnr = args[2]
@@ -2146,13 +2219,17 @@ describe('LSP', function()
vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
- ]], make_workspace_edit(edits), target_bufnr))
+ ]],
+ make_workspace_edit(edits),
+ target_bufnr
+ )
+ )
end)
it('apply_workspace_edit applies multiple edits', function()
local new_lines = {
- "First Line",
- "Second Line",
+ 'First Line',
+ 'Second Line',
}
local edits = {}
@@ -2160,7 +2237,10 @@ describe('LSP', function()
table.insert(edits, replace_line_edit(row - 1, line, changedtick))
end
- eq(new_lines, exec_lua([[
+ eq(
+ new_lines,
+ exec_lua(
+ [[
local args = {...}
local workspace_edits = args[1]
local target_bufnr = args[2]
@@ -2168,10 +2248,14 @@ describe('LSP', function()
vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
- ]], make_workspace_edit(edits), target_bufnr))
+ ]],
+ make_workspace_edit(edits),
+ target_bufnr
+ )
+ )
end)
it('Supports file creation with CreateFile payload', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
os.remove(tmpfile) -- Should not exist, only interested in a tmpname
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2180,29 +2264,32 @@ describe('LSP', function()
kind = 'create',
uri = uri,
},
- }
+ },
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
end)
- it('Supports file creation in folder that needs to be created with CreateFile payload', function()
- local tmpfile = helpers.tmpname()
- os.remove(tmpfile) -- Should not exist, only interested in a tmpname
- tmpfile = tmpfile .. '/dummy/x/'
- local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
- local edit = {
- documentChanges = {
- {
- kind = 'create',
- uri = uri,
+ it(
+ 'Supports file creation in folder that needs to be created with CreateFile payload',
+ function()
+ local tmpfile = tmpname()
+ os.remove(tmpfile) -- Should not exist, only interested in a tmpname
+ tmpfile = tmpfile .. '/dummy/x/'
+ local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
+ local edit = {
+ documentChanges = {
+ {
+ kind = 'create',
+ uri = uri,
+ },
},
}
- }
- exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
- end)
+ exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
+ end
+ )
it('createFile does not touch file if it exists and ignoreIfExists is set', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
write_file(tmpfile, 'Dummy content')
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2214,14 +2301,14 @@ describe('LSP', function()
ignoreIfExists = true,
},
},
- }
+ },
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
eq('Dummy content', read_file(tmpfile))
end)
it('createFile overrides file if overwrite is set', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
write_file(tmpfile, 'Dummy content')
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2234,35 +2321,38 @@ describe('LSP', function()
ignoreIfExists = true, -- overwrite must win over ignoreIfExists
},
},
- }
+ },
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
eq('', read_file(tmpfile))
end)
it('DeleteFile delete file and buffer', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
write_file(tmpfile, 'Be gone')
- local uri = exec_lua([[
+ local uri = exec_lua(
+ [[
local fname = select(1, ...)
local bufnr = vim.fn.bufadd(fname)
vim.fn.bufload(bufnr)
return vim.uri_from_fname(fname)
- ]], tmpfile)
+ ]],
+ tmpfile
+ )
local edit = {
documentChanges = {
{
kind = 'delete',
uri = uri,
- }
- }
+ },
+ },
}
eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16'))
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
eq(false, exec_lua('return vim.api.nvim_buf_is_loaded(vim.fn.bufadd(...))', tmpfile))
end)
it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
os.remove(tmpfile)
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2272,9 +2362,9 @@ describe('LSP', function()
uri = uri,
options = {
ignoreIfNotExists = false,
- }
- }
- }
+ },
+ },
+ },
}
eq(false, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit))
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
@@ -2285,46 +2375,36 @@ describe('LSP', function()
local pathsep = helpers.get_pathsep()
it('Can rename an existing file', function()
- local old = helpers.tmpname()
+ local old = tmpname()
write_file(old, 'Test content')
- local new = helpers.tmpname()
- os.remove(new) -- only reserve the name, file must not exist for the test scenario
- local lines = exec_lua([[
+ local new = tmpname()
+ os.remove(new) -- only reserve the name, file must not exist for the test scenario
+ local lines = exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
+ local old_bufnr = vim.fn.bufadd(old)
+ vim.fn.bufload(old_bufnr)
vim.lsp.util.rename(old, new)
-
- -- after rename the target file must have the contents of the source file
- local bufnr = vim.fn.bufadd(new)
- vim.fn.bufload(new)
- return vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
- ]], old, new)
- eq({'Test content'}, lines)
+ -- the existing buffer is renamed in-place and its contents is kept
+ local new_bufnr = vim.fn.bufadd(new)
+ vim.fn.bufload(new_bufnr)
+ return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true)
+ ]],
+ old,
+ new
+ )
+ eq({ 'Test content' }, lines)
local exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', old)
eq(false, exists)
exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', new)
eq(true, exists)
os.remove(new)
end)
- it("Kills old buffer after renaming an existing file", function()
- local old = helpers.tmpname()
- write_file(old, 'Test content')
- local new = helpers.tmpname()
- os.remove(new) -- only reserve the name, file must not exist for the test scenario
- local lines = exec_lua([[
- local old = select(1, ...)
- local oldbufnr = vim.fn.bufadd(old)
- local new = select(2, ...)
- vim.lsp.util.rename(old, new)
- return vim.fn.bufloaded(oldbufnr)
- ]], old, new)
- eq(0, lines)
- os.remove(new)
- end)
it('Can rename a directory', function()
-- only reserve the name, file must not exist for the test scenario
- local old_dir = helpers.tmpname()
- local new_dir = helpers.tmpname()
+ local old_dir = tmpname()
+ local new_dir = tmpname()
os.remove(old_dir)
os.remove(new_dir)
@@ -2333,64 +2413,211 @@ describe('LSP', function()
local file = 'file.txt'
write_file(old_dir .. pathsep .. file, 'Test content')
- local lines = exec_lua([[
+ local lines = exec_lua(
+ [[
local old_dir = select(1, ...)
local new_dir = select(2, ...)
- local pathsep = select(3, ...)
- local oldbufnr = vim.fn.bufadd(old_dir .. pathsep .. 'file')
-
+ local pathsep = select(3, ...)
+ local file = select(4, ...)
+ local old_bufnr = vim.fn.bufadd(old_dir .. pathsep .. file)
+ vim.fn.bufload(old_bufnr)
vim.lsp.util.rename(old_dir, new_dir)
- return vim.fn.bufloaded(oldbufnr)
- ]], old_dir, new_dir, pathsep)
- eq(0, lines)
+ -- the existing buffer is renamed in-place and its contents is kept
+ local new_bufnr = vim.fn.bufadd(new_dir .. pathsep .. file)
+ vim.fn.bufload(new_bufnr)
+ return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true)
+ ]],
+ old_dir,
+ new_dir,
+ pathsep,
+ file
+ )
+ eq({ 'Test content' }, lines)
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old_dir))
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir))
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir .. pathsep .. file))
- eq('Test content', read_file(new_dir .. pathsep .. file))
os.remove(new_dir)
end)
- it('Does not rename file if target exists and ignoreIfExists is set or overwrite is false', function()
- local old = helpers.tmpname()
- write_file(old, 'Old File')
- local new = helpers.tmpname()
- write_file(new, 'New file')
+ it('Does not touch buffers that do not match path prefix', function()
+ local old = tmpname()
+ local new = tmpname()
+ os.remove(old)
+ os.remove(new)
+ helpers.mkdir_p(old)
- exec_lua([[
+ local result = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+
+ local old_prefixed = 'explorer://' .. old
+ local old_suffixed = old .. '.bak'
+ local new_prefixed = 'explorer://' .. new
+ local new_suffixed = new .. '.bak'
+
+ 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)
+
+ vim.lsp.util.rename(old, new)
+
+ 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
+ ]],
+ old,
+ new
+ )
+ eq(true, result)
+
+ os.remove(new)
+ end)
+ it(
+ 'Does not rename file if target exists and ignoreIfExists is set or overwrite is false',
+ function()
+ local old = tmpname()
+ write_file(old, 'Old File')
+ local new = tmpname()
+ write_file(new, 'New file')
+
+ exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
vim.lsp.util.rename(old, new, { ignoreIfExists = true })
- ]], old, new)
+ ]],
+ old,
+ new
+ )
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
- eq('New file', read_file(new))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq('New file', read_file(new))
- exec_lua([[
+ exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
vim.lsp.util.rename(old, new, { overwrite = false })
- ]], old, new)
+ ]],
+ old,
+ new
+ )
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
- eq('New file', read_file(new))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq('New file', read_file(new))
+ end
+ )
+ it('Maintains undo information for loaded buffer', function()
+ local old = tmpname()
+ write_file(old, 'line')
+ local new = tmpname()
+ os.remove(new)
+
+ local undo_kept = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+ vim.opt.undofile = true
+ vim.cmd.edit(old)
+ vim.cmd.normal('dd')
+ vim.cmd.write()
+ local undotree = vim.fn.undotree()
+ vim.lsp.util.rename(old, new)
+ -- 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
+ return vim.deep_equal(undotree, vim.fn.undotree())
+ ]],
+ old,
+ new
+ )
+ eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
+ eq(true, undo_kept)
+ end)
+ it('Maintains undo information for unloaded buffer', function()
+ local old = tmpname()
+ write_file(old, 'line')
+ local new = tmpname()
+ os.remove(new)
+
+ local undo_kept = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+ vim.opt.undofile = true
+ vim.cmd.split(old)
+ vim.cmd.normal('dd')
+ vim.cmd.write()
+ local undotree = vim.fn.undotree()
+ vim.cmd.bdelete()
+ vim.lsp.util.rename(old, new)
+ vim.cmd.edit(new)
+ return vim.deep_equal(undotree, vim.fn.undotree())
+ ]],
+ old,
+ new
+ )
+ eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
+ eq(true, undo_kept)
+ end)
+ it('Does not rename file when it conflicts with a buffer without file', function()
+ local old = tmpname()
+ write_file(old, 'Old File')
+ local new = tmpname()
+ os.remove(new)
+
+ local lines = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+ local old_buf = vim.fn.bufadd(old)
+ vim.fn.bufload(old_buf)
+ local conflict_buf = vim.api.nvim_create_buf(true, false)
+ vim.api.nvim_buf_set_name(conflict_buf, new)
+ vim.api.nvim_buf_set_lines(conflict_buf, 0, -1, true, {'conflict'})
+ vim.api.nvim_win_set_buf(0, conflict_buf)
+ vim.lsp.util.rename(old, new)
+ return vim.api.nvim_buf_get_lines(conflict_buf, 0, -1, true)
+ ]],
+ old,
+ new
+ )
+ eq({ 'conflict' }, lines)
+ eq('Old File', read_file(old))
end)
it('Does override target if overwrite is true', function()
- local old = helpers.tmpname()
+ local old = tmpname()
write_file(old, 'Old file')
- local new = helpers.tmpname()
+ local new = tmpname()
write_file(new, 'New file')
- exec_lua([[
+ exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
vim.lsp.util.rename(old, new, { overwrite = true })
- ]], old, new)
+ ]],
+ old,
+ new
+ )
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
- eq('Old file\n', read_file(new))
+ eq('Old file', read_file(new))
end)
end)
@@ -2407,8 +2634,8 @@ describe('LSP', function()
range = {
start = { line = 0, character = 2 },
['end'] = { line = 0, character = 3 },
- }
- }
+ },
+ },
},
}
local actual = exec_lua [[
@@ -2436,7 +2663,7 @@ describe('LSP', function()
col = 3,
text = 'testing',
user_data = {
- targetUri = "file:///fake/uri",
+ targetUri = 'file:///fake/uri',
targetRange = {
start = { line = 0, character = 2 },
['end'] = { line = 0, character = 3 },
@@ -2444,8 +2671,8 @@ describe('LSP', function()
targetSelectionRange = {
start = { line = 0, character = 2 },
['end'] = { line = 0, character = 3 },
- }
- }
+ },
+ },
},
}
local actual = exec_lua [[
@@ -2479,24 +2706,26 @@ describe('LSP', function()
filename = '',
kind = 'File',
lnum = 2,
- text = '[File] TestA'
+ text = '[File] TestA',
},
{
col = 1,
filename = '',
kind = 'Module',
lnum = 4,
- text = '[Module] TestB'
+ text = '[Module] TestB',
},
{
col = 1,
filename = '',
kind = 'Namespace',
lnum = 6,
- text = '[Namespace] TestC'
- }
+ text = '[Namespace] TestC',
+ },
}
- eq(expected, exec_lua [[
+ eq(
+ expected,
+ exec_lua [[
local doc_syms = {
{
deprecated = false,
@@ -2581,7 +2810,8 @@ describe('LSP', function()
}
}
return vim.lsp.util.symbols_to_items(doc_syms, nil)
- ]])
+ ]]
+ )
end)
it('DocumentSymbol has no children', function()
local expected = {
@@ -2590,17 +2820,19 @@ describe('LSP', function()
filename = '',
kind = 'File',
lnum = 2,
- text = '[File] TestA'
+ text = '[File] TestA',
},
{
col = 1,
filename = '',
kind = 'Namespace',
lnum = 6,
- text = '[Namespace] TestC'
- }
+ text = '[Namespace] TestC',
+ },
}
- eq(expected, exec_lua [[
+ eq(
+ expected,
+ exec_lua [[
local doc_syms = {
{
deprecated = false,
@@ -2656,27 +2888,30 @@ describe('LSP', function()
}
}
return vim.lsp.util.symbols_to_items(doc_syms, nil)
- ]])
+ ]]
+ )
end)
end)
it('convert SymbolInformation[] to items', function()
- local expected = {
- {
- col = 1,
- filename = '/test_a',
- kind = 'File',
- lnum = 2,
- text = '[File] TestA'
- },
- {
- col = 1,
- filename = '/test_b',
- kind = 'Module',
- lnum = 4,
- text = '[Module] TestB'
- }
- }
- eq(expected, exec_lua [[
+ local expected = {
+ {
+ col = 1,
+ filename = '/test_a',
+ kind = 'File',
+ lnum = 2,
+ text = '[File] TestA',
+ },
+ {
+ col = 1,
+ filename = '/test_b',
+ kind = 'Module',
+ lnum = 4,
+ text = '[Module] TestB',
+ },
+ }
+ eq(
+ expected,
+ exec_lua [[
local sym_info = {
{
deprecated = false,
@@ -2718,19 +2953,20 @@ describe('LSP', function()
}
}
return vim.lsp.util.symbols_to_items(sym_info, nil)
- ]])
+ ]]
+ )
end)
end)
describe('lsp.util._get_symbol_kind_name', function()
it('returns the name specified by protocol', function()
- eq("File", exec_lua("return vim.lsp.util._get_symbol_kind_name(1)"))
- eq("TypeParameter", exec_lua("return vim.lsp.util._get_symbol_kind_name(26)"))
+ eq('File', exec_lua('return vim.lsp.util._get_symbol_kind_name(1)'))
+ eq('TypeParameter', exec_lua('return vim.lsp.util._get_symbol_kind_name(26)'))
end)
it('returns the name not specified by protocol', function()
- eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(nil)"))
- eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(vim.NIL)"))
- eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(1000)"))
+ eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(nil)'))
+ eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(vim.NIL)'))
+ eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(1000)'))
end)
end)
@@ -2748,20 +2984,20 @@ describe('LSP', function()
local location = function(start_line, start_char, end_line, end_char)
return {
- uri = "file:///fake/uri",
+ uri = 'file:///fake/uri',
range = {
start = { line = start_line, character = start_char },
- ["end"] = { line = end_line, character = end_char },
+ ['end'] = { line = end_line, character = end_char },
},
}
end
local jump = function(msg)
- eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, "utf-16"))
- eq(target_bufnr, exec_lua[[return vim.fn.bufnr('%')]])
+ eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, 'utf-16'))
+ eq(target_bufnr, exec_lua [[return vim.fn.bufnr('%')]])
return {
- line = exec_lua[[return vim.fn.line('.')]],
- col = exec_lua[[return vim.fn.col('.')]],
+ line = exec_lua [[return vim.fn.line('.')]],
+ col = exec_lua [[return vim.fn.col('.')]],
}
end
@@ -2773,16 +3009,16 @@ describe('LSP', function()
it('jumps to a LocationLink', function()
local pos = jump({
- targetUri = "file:///fake/uri",
- targetSelectionRange = {
- start = { line = 0, character = 4 },
- ["end"] = { line = 0, character = 4 },
- },
- targetRange = {
- start = { line = 1, character = 5 },
- ["end"] = { line = 1, character = 5 },
- },
- })
+ targetUri = 'file:///fake/uri',
+ 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)
@@ -2791,18 +3027,18 @@ describe('LSP', function()
local pos = jump(location(1, 2, 1, 2))
eq(2, pos.line)
eq(4, pos.col)
- eq('Ã¥', exec_lua[[return vim.fn.expand('<cword>')]])
+ eq('Ã¥', exec_lua [[return vim.fn.expand('<cword>')]])
end)
it('adds current position to jumplist before jumping', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_cursor(0, { 2, 3 })
jump(location(0, 9, 0, 9))
- mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 2, 3 }, mark)
end)
end)
@@ -2896,101 +3132,101 @@ describe('LSP', function()
end)
it('does not add current position to jumplist if not focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_cursor(0, { 2, 3 })
show_document(location(0, 9, 0, 9), false, true)
show_document(location(0, 9, 0, 9, true), false, true)
- mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
end)
it('does not change cursor position if not focus and not reuse_win', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local cursor = funcs.nvim_win_get_cursor(0)
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local cursor = fn.nvim_win_get_cursor(0)
show_document(location(0, 9, 0, 9), false, false)
- eq(cursor, funcs.nvim_win_get_cursor(0))
+ eq(cursor, fn.nvim_win_get_cursor(0))
end)
it('does not change window if not focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local win = funcs.nvim_get_current_win()
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local win = fn.nvim_get_current_win()
-- same document/bufnr
show_document(location(0, 9, 0, 9), false, true)
- eq(win, funcs.nvim_get_current_win())
+ eq(win, fn.nvim_get_current_win())
-- different document/bufnr, new window/split
show_document(location(0, 9, 0, 9, true), false, true)
- eq(2, #funcs.nvim_list_wins())
- eq(win, funcs.nvim_get_current_win())
+ eq(2, #fn.nvim_list_wins())
+ eq(win, fn.nvim_get_current_win())
end)
it("respects 'reuse_win' parameter", function()
- funcs.nvim_win_set_buf(0, target_bufnr)
+ fn.nvim_win_set_buf(0, target_bufnr)
-- does not create a new window if the buffer is already open
show_document(location(0, 9, 0, 9), false, true)
- eq(1, #funcs.nvim_list_wins())
+ eq(1, #fn.nvim_list_wins())
-- creates a new window even if the buffer is already open
show_document(location(0, 9, 0, 9), false, false)
- eq(2, #funcs.nvim_list_wins())
+ eq(2, #fn.nvim_list_wins())
end)
it('correctly sets the cursor of the split if range is given without focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
+ fn.nvim_win_set_buf(0, target_bufnr)
show_document(location(0, 9, 0, 9, true), false, true)
- local wins = funcs.nvim_list_wins()
+ local wins = fn.nvim_list_wins()
eq(2, #wins)
table.sort(wins)
- eq({ 1, 0 }, funcs.nvim_win_get_cursor(wins[1]))
- eq({ 1, 9 }, funcs.nvim_win_get_cursor(wins[2]))
+ eq({ 1, 0 }, fn.nvim_win_get_cursor(wins[1]))
+ eq({ 1, 9 }, fn.nvim_win_get_cursor(wins[2]))
end)
it('does not change cursor of the split if not range and not focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_buf(0, target_bufnr)
+ fn.nvim_win_set_cursor(0, { 2, 3 })
exec_lua([[vim.cmd.new()]])
- funcs.nvim_win_set_buf(0, target_bufnr2)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_buf(0, target_bufnr2)
+ fn.nvim_win_set_cursor(0, { 2, 3 })
show_document({ uri = 'file:///fake/uri2' }, false, true)
- local wins = funcs.nvim_list_wins()
+ local wins = fn.nvim_list_wins()
eq(2, #wins)
- eq({ 2, 3 }, funcs.nvim_win_get_cursor(wins[1]))
- eq({ 2, 3 }, funcs.nvim_win_get_cursor(wins[2]))
+ eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[1]))
+ eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[2]))
end)
it('respects existing buffers', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local win = funcs.nvim_get_current_win()
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local win = fn.nvim_get_current_win()
exec_lua([[vim.cmd.new()]])
- funcs.nvim_win_set_buf(0, target_bufnr2)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
- local split = funcs.nvim_get_current_win()
+ fn.nvim_win_set_buf(0, target_bufnr2)
+ fn.nvim_win_set_cursor(0, { 2, 3 })
+ local split = fn.nvim_get_current_win()
-- reuse win for open document/bufnr if called from split
show_document(location(0, 9, 0, 9, true), false, true)
- eq({ 1, 9 }, funcs.nvim_win_get_cursor(split))
- eq(2, #funcs.nvim_list_wins())
+ eq({ 1, 9 }, fn.nvim_win_get_cursor(split))
+ eq(2, #fn.nvim_list_wins())
- funcs.nvim_set_current_win(win)
+ fn.nvim_set_current_win(win)
-- reuse win for open document/bufnr if called outside the split
show_document(location(0, 9, 0, 9, true), false, true)
- eq({ 1, 9 }, funcs.nvim_win_get_cursor(split))
- eq(2, #funcs.nvim_list_wins())
+ eq({ 1, 9 }, fn.nvim_win_get_cursor(split))
+ eq(2, #fn.nvim_list_wins())
end)
end)
@@ -3004,11 +3240,14 @@ describe('LSP', function()
end)
it('calculates size correctly', function()
- eq({19,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
+ eq({ 19, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
end)
it('calculates size correctly with wrapping', function()
- eq({15,5}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]])
+ eq(
+ { 15, 5 },
+ exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]]
+ )
end)
it('handles NUL bytes in text', function()
@@ -3018,21 +3257,24 @@ describe('LSP', function()
'\020\021\022\023\024\025\026\027\028\029',
} ]])
command('set list listchars=')
- eq({20,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
+ eq({ 20, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
command('set display+=uhex')
- eq({40,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
+ eq({ 40, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
end)
end)
describe('lsp.util.trim.trim_empty_lines', function()
it('properly trims empty lines', function()
- eq({{"foo", "bar"}}, exec_lua[[ return vim.lsp.util.trim_empty_lines({{ "foo", "bar" }, nil}) ]])
+ eq(
+ { { 'foo', 'bar' } },
+ exec_lua [[ return vim.lsp.util.trim_empty_lines({{ "foo", "bar" }, nil}) ]]
+ )
end)
end)
describe('lsp.util.convert_signature_help_to_markdown_lines', function()
it('can handle negative activeSignature', function()
- local result = exec_lua[[
+ local result = exec_lua [[
local signature_help = {
activeParameter = 0,
activeSignature = -1,
@@ -3046,22 +3288,29 @@ describe('LSP', function()
}
return vim.lsp.util.convert_signature_help_to_markdown_lines(signature_help, 'cs', {','})
]]
- local expected = {'```cs', 'TestEntity.TestEntity()', '```', 'some doc'}
+ local expected = { '```cs', 'TestEntity.TestEntity()', '```', 'some doc' }
eq(expected, result)
end)
end)
describe('lsp.util.get_effective_tabstop', function()
local function test_tabstop(tabsize, shiftwidth)
- exec_lua(string.format([[
+ exec_lua(string.format(
+ [[
vim.bo.shiftwidth = %d
vim.bo.tabstop = 2
- ]], shiftwidth))
+ ]],
+ shiftwidth
+ ))
eq(tabsize, exec_lua('return vim.lsp.util.get_effective_tabstop()'))
end
- it('with shiftwidth = 1', function() test_tabstop(1, 1) end)
- it('with shiftwidth = 0', function() test_tabstop(2, 0) end)
+ it('with shiftwidth = 1', function()
+ test_tabstop(1, 1)
+ end)
+ it('with shiftwidth = 0', function()
+ test_tabstop(2, 0)
+ end)
end)
describe('vim.lsp.buf.outgoing_calls', function()
@@ -3118,20 +3367,22 @@ describe('LSP', function()
return vim.fn.getqflist()
]=])
- local expected = { {
- bufnr = 2,
- col = 5,
- end_col = 0,
- lnum = 4,
- end_lnum = 0,
- module = "",
- nr = 0,
- pattern = "",
- text = "foo",
- type = "",
- valid = 1,
- vcol = 0
- } }
+ local expected = {
+ {
+ bufnr = 2,
+ col = 5,
+ end_col = 0,
+ lnum = 4,
+ end_lnum = 0,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'foo',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
eq(expected, qflist)
end)
@@ -3192,20 +3443,22 @@ describe('LSP', function()
return vim.fn.getqflist()
]=])
- local expected = { {
- bufnr = 2,
- col = 5,
- end_col = 0,
- lnum = 4,
- end_lnum = 0,
- module = "",
- nr = 0,
- pattern = "",
- text = "main",
- type = "",
- valid = 1,
- vcol = 0
- } }
+ local expected = {
+ {
+ bufnr = 2,
+ col = 5,
+ end_col = 0,
+ lnum = 4,
+ end_lnum = 0,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'main',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
eq(expected, qflist)
end)
@@ -3214,52 +3467,52 @@ describe('LSP', function()
describe('vim.lsp.buf.rename', function()
for _, test in ipairs({
{
- it = "does not attempt to rename on nil response",
- name = "prepare_rename_nil",
+ 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}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
},
},
{
- it = "handles prepareRename placeholder response",
- name = "prepare_rename_placeholder",
+ 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}};
+ { 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
+ expected_text = 'placeholder', -- see fake lsp response
},
{
- it = "handles range response",
- name = "prepare_rename_range",
+ 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}};
+ { 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
+ expected_text = 'line', -- see test case and fake lsp response
},
{
- it = "handles error",
- name = "prepare_rename_error",
+ it = 'handles error',
+ name = 'prepare_rename_error',
expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
},
},
}) do
- it(test.it, function()
- local client
- test_rpc_server {
- test_name = test.name;
- on_init = function(_client)
- client = _client
- eq(true, client.server_capabilities().renameProvider.prepareProvider)
- end;
- on_setup = function()
- exec_lua([=[
+ it(test.it, function()
+ local client
+ test_rpc_server {
+ test_name = test.name,
+ on_init = function(_client)
+ client = _client
+ eq(true, client.server_capabilities().renameProvider.prepareProvider)
+ end,
+ on_setup = function()
+ exec_lua([=[
local bufnr = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
vim.lsp._stubs = {}
@@ -3271,31 +3524,31 @@ describe('LSP', function()
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;
- on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
- on_handler = function(err, result, ctx)
- -- Don't compare & assert params and version, they're not relevant for the testcase
- -- This allows us to be lazy and avoid declaring them
- ctx.params = nil
- ctx.version = nil
-
- eq(table.remove(test.expected_handlers), {err, result, ctx}, "expected handler")
- if ctx.method == 'start' then
- exec_lua("vim.lsp.buf.rename()")
- end
- if ctx.method == 'shutdown' then
- if test.expected_text then
- eq("New Name: ", exec_lua("return vim.lsp._stubs.input_prompt"))
- eq(test.expected_text, exec_lua("return vim.lsp._stubs.input_text"))
+ end,
+ on_exit = function(code, signal)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
+ on_handler = function(err, result, ctx)
+ -- Don't compare & assert params and version, they're not relevant for the testcase
+ -- This allows us to be lazy and avoid declaring them
+ ctx.params = nil
+ ctx.version = nil
+
+ eq(table.remove(test.expected_handlers), { err, result, ctx }, 'expected handler')
+ if ctx.method == 'start' then
+ exec_lua('vim.lsp.buf.rename()')
end
- client.stop()
- end
- end;
- }
- end)
+ if ctx.method == 'shutdown' then
+ if test.expected_text then
+ eq('New Name: ', exec_lua('return vim.lsp._stubs.input_prompt'))
+ eq(test.expected_text, exec_lua('return vim.lsp._stubs.input_text'))
+ end
+ client.stop()
+ end
+ end,
+ }
+ end)
end
end)
@@ -3303,22 +3556,21 @@ describe('LSP', function()
it('Calls client side command if available', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { 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_setup = function() end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit 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})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
exec_lua([[
vim.lsp.commands['dummy1'] = function(cmd)
@@ -3333,10 +3585,10 @@ describe('LSP', function()
vim.lsp.buf.code_action()
]])
elseif ctx.method == 'shutdown' then
- eq('function', exec_lua[[return type(vim.lsp.commands['dummy2'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['dummy2'])]])
client.stop()
end
- end
+ end,
}
end)
it('Calls workspace/executeCommand if no client side command', function()
@@ -3382,22 +3634,21 @@ describe('LSP', function()
it('Filters and automatically applies action if requested', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { 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_setup = function() end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit 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})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
exec_lua([[
vim.lsp.commands['preferred_command'] = function(cmd)
@@ -3428,15 +3679,15 @@ describe('LSP', function()
})
]])
elseif ctx.method == 'shutdown' then
- eq('function', exec_lua[[return type(vim.lsp.commands['executed_preferred'])]])
- eq('function', exec_lua[[return type(vim.lsp.commands['filtered_type_annotate_foo'])]])
- eq('function', exec_lua[[return type(vim.lsp.commands['executed_type_annotate'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['executed_preferred'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['filtered_type_annotate_foo'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['executed_type_annotate'])]])
client.stop()
end
- end
+ end,
}
end)
- it("Fallback to command execution on resolve error", function()
+ it('Fallback to command execution on resolve error', function()
clear()
exec_lua(create_server_definition)
local result = exec_lua([[
@@ -3476,9 +3727,9 @@ describe('LSP', function()
vim.lsp.stop_client(client_id)
return server.messages
]])
- eq("codeAction/resolve", result[4].method)
- eq("workspace/executeCommand", result[5].method)
- eq("command:1", result[5].params.command)
+ eq('codeAction/resolve', result[4].method)
+ eq('workspace/executeCommand', result[5].method)
+ eq('command:1', result[5].params.command)
end)
end)
describe('vim.lsp.commands', function()
@@ -3499,25 +3750,25 @@ describe('LSP', function()
it('uses client commands', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { 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_setup = function() end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit 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})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
- local fake_uri = "file:///fake/uri"
- local cmd = exec_lua([[
+ local fake_uri = 'file:///fake/uri'
+ local cmd = exec_lua(
+ [[
fake_uri = ...
local bufnr = vim.uri_to_bufnr(fake_uri)
vim.fn.bufload(bufnr)
@@ -3539,20 +3790,22 @@ describe('LSP', function()
vim.api.nvim_set_current_buf(bufnr)
vim.lsp.codelens.run()
return cmd_called
- ]], fake_uri)
- eq({ command = 'Dummy', title = 'Lens1' }, cmd)
- elseif ctx.method == 'shutdown' then
- client.stop()
+ ]],
+ fake_uri
+ )
+ eq({ command = 'Dummy', title = 'Lens1' }, cmd)
+ elseif ctx.method == 'shutdown' then
+ client.stop()
end
- end
+ end,
}
end)
it('releases buffer refresh lock', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
test_rpc_server {
test_name = 'codelens_refresh_lock',
@@ -3576,11 +3829,11 @@ describe('LSP', function()
]=])
end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit 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})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
-- 1. first codelens request errors
local response = exec_lua([=[
@@ -3589,7 +3842,7 @@ describe('LSP', function()
vim.wait(100, function () return CALLED end)
return RESPONSE
]=])
- eq( { err = { code = -32002, message = "ServerNotInitialized" } }, response)
+ eq({ err = { code = -32002, message = 'ServerNotInitialized' } }, response)
-- 2. second codelens request runs
response = exec_lua([=[
@@ -3604,7 +3857,7 @@ describe('LSP', function()
vim.wait(100, function () return cmd_called end)
return cmd_called
]=])
- eq( { command = "Dummy", title = "Lens1" }, response)
+ eq({ command = 'Dummy', title = 'Lens1' }, response)
-- 3. third codelens request runs
response = exec_lua([=[
@@ -3619,20 +3872,20 @@ describe('LSP', function()
vim.wait(100, function () return cmd_called end)
return cmd_called
]=])
- eq( { command = "Dummy", title = "Lens2" }, response)
- elseif ctx.method == 'shutdown' then
- client.stop()
+ eq({ command = 'Dummy', title = 'Lens2' }, response)
+ elseif ctx.method == 'shutdown' then
+ client.stop()
end
- end
+ end,
}
end)
end)
- describe("vim.lsp.buf.format", function()
- it("Aborts with notify if no client matches filter", function()
+ describe('vim.lsp.buf.format', function()
+ it('Aborts with notify if no client matches filter', function()
local client
test_rpc_server {
- test_name = "basic_init",
+ test_name = 'basic_init',
on_init = function(c)
client = c
end,
@@ -3649,25 +3902,25 @@ describe('LSP', function()
vim.notify = notify
return notify_msg
]])
- eq("[LSP] Format request failed, no matching language servers.", notify_msg)
+ eq('[LSP] Format request failed, no matching language servers.', notify_msg)
client.stop()
end,
}
end)
- it("Sends textDocument/formatting request to format buffer", function()
+ it('Sends textDocument/formatting request to format buffer', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_formatting",
+ test_name = 'basic_formatting',
on_init = function(c)
client = c
end,
on_handler = function(_, _, ctx)
table.remove(expected_handlers)
- if ctx.method == "start" then
+ if ctx.method == 'start' then
local notify_msg = exec_lua([[
local bufnr = vim.api.nvim_get_current_buf()
vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
@@ -3681,7 +3934,7 @@ describe('LSP', function()
return notify_msg
]])
eq(NIL, notify_msg)
- elseif ctx.method == "shutdown" then
+ elseif ctx.method == 'shutdown' then
client.stop()
end
end,
@@ -3689,18 +3942,18 @@ describe('LSP', function()
end)
it('Can format async', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_formatting",
+ test_name = 'basic_formatting',
on_init = function(c)
client = c
end,
on_handler = function(_, _, ctx)
table.remove(expected_handlers)
- if ctx.method == "start" then
+ if ctx.method == 'start' then
local result = exec_lua([[
local bufnr = vim.api.nvim_get_current_buf()
vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
@@ -3724,8 +3977,8 @@ describe('LSP', function()
vim.lsp.handlers['textDocument/formatting'] = handler
return {notify = notify_msg, handler_called = handler_called}
]])
- eq({handler_called=true}, result)
- elseif ctx.method == "shutdown" then
+ eq({ handler_called = true }, result)
+ elseif ctx.method == 'shutdown' then
client.stop()
end
end,
@@ -3749,7 +4002,7 @@ describe('LSP', function()
vim.lsp.stop_client(client_id)
return server.messages
]])
- eq("textDocument/rangeFormatting", result[3].method)
+ eq('textDocument/rangeFormatting', result[3].method)
local expected_range = {
start = { line = 0, character = 0 },
['end'] = { line = 1, character = 4 },
@@ -3784,16 +4037,21 @@ describe('LSP', function()
return server.messages
]])
local expected_methods = {
- "initialize",
- "initialized",
- "textDocument/rangeFormatting",
- "$/cancelRequest",
- "textDocument/rangeFormatting",
- "$/cancelRequest",
- "shutdown",
- "exit",
+ 'initialize',
+ 'initialized',
+ 'textDocument/rangeFormatting',
+ '$/cancelRequest',
+ 'textDocument/rangeFormatting',
+ '$/cancelRequest',
+ 'shutdown',
+ 'exit',
}
- eq(expected_methods, vim.tbl_map(function(x) return x.method end, result))
+ eq(
+ expected_methods,
+ vim.tbl_map(function(x)
+ return x.method
+ end, result)
+ )
-- uses first column of start line and last column of end line
local expected_range = {
start = { line = 0, character = 0 },
@@ -3809,10 +4067,11 @@ describe('LSP', function()
notify_msg = msg
end
]])
- local fail_msg = "[LSP] Format request failed, no matching language servers."
+ local fail_msg = '[LSP] Format request failed, no matching language servers.'
local function check_notify(name, formatting, range_formatting)
- local timeout_msg = "[LSP][" .. name .. "] timeout"
- exec_lua([[
+ local timeout_msg = '[LSP][' .. name .. '] timeout'
+ exec_lua(
+ [[
local formatting, range_formatting, name = ...
local server = _create_server({ capabilities = {
documentFormattingProvider = formatting,
@@ -3821,7 +4080,11 @@ describe('LSP', function()
vim.lsp.start({ name = name, cmd = server.cmd })
notify_msg = nil
vim.lsp.buf.format({ name = name, timeout_ms = 1 })
- ]], formatting, range_formatting, name)
+ ]],
+ formatting,
+ range_formatting,
+ name
+ )
eq(formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
exec_lua([[
notify_msg = nil
@@ -3829,12 +4092,111 @@ describe('LSP', function()
]])
eq(range_formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
end
- check_notify("none", false, false)
- check_notify("formatting", true, false)
- check_notify("rangeFormatting", false, true)
- check_notify("both", true, true)
+ check_notify('none', false, false)
+ check_notify('formatting', true, false)
+ check_notify('rangeFormatting', false, true)
+ check_notify('both', true, true)
+ end)
+ end)
+
+ 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)
+ exec_lua(
+ [[
+ _G.mock_locations = ...
+ _G.server = _create_server({
+ ---@type lsp.ServerCapabilities
+ capabilities = {
+ definitionProvider = true,
+ workspaceSymbolProvider = true,
+ },
+ handlers = {
+ ---@return lsp.Location[]
+ ['textDocument/definition'] = function()
+ return { _G.mock_locations[1] }
+ end,
+ ---@return lsp.WorkspaceSymbol[]
+ ['workspace/symbol'] = function(_, request)
+ assert(request.query == 'foobar')
+ return {
+ {
+ 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],
+ }
+ }
+ end,
+ },
+ })
+ _G.client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ ]],
+ mock_locations
+ )
+ end)
+ after_each(function()
+ exec_lua [[
+ vim.lsp.stop_client(_G.client_id)
+ ]]
+ end)
+
+ it('with flags=c, returns matching tags using textDocument/definition', function()
+ local result = exec_lua [[
+ return vim.lsp.tagfunc('foobar', 'c')
+ ]]
+ 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()
+ local result = exec_lua [[
+ return vim.lsp.tagfunc('foobar', '')
+ ]]
+ 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)
+
describe('cmd', function()
it('can connect to lsp server via rpc.connect', function()
local result = exec_lua [[
@@ -3859,7 +4221,43 @@ describe('LSP', function()
server:shutdown()
return vim.json.decode(init)
]]
- eq(result.method, "initialize")
+ eq(result.method, 'initialize')
+ end)
+ it('can connect to lsp server via rpc.domain_socket_connect', function()
+ local tmpfile
+ if is_os('win') then
+ tmpfile = '\\\\.\\\\pipe\\pipe.test'
+ else
+ tmpfile = tmpname()
+ os.remove(tmpfile)
+ end
+ local result = exec_lua(
+ [[
+ local SOCK = ...
+ local uv = vim.uv
+ local server = uv.new_pipe(false)
+ server:bind(SOCK)
+ local init = nil
+
+ server:listen(127, function(err)
+ assert(not err, err)
+ local client = uv.new_pipe()
+ server:accept(client)
+ client:read_start(require("vim.lsp.rpc").create_read_loop(function(body)
+ init = body
+ client:close()
+ end))
+ end)
+ vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.domain_socket_connect(SOCK) })
+ vim.wait(1000, function() return init ~= nil end)
+ assert(init, "server must receive `initialize` request")
+ server:close()
+ server:shutdown()
+ return vim.json.decode(init)
+ ]],
+ tmpfile
+ )
+ eq(result.method, 'initialize')
end)
end)
@@ -3926,9 +4324,9 @@ describe('LSP', function()
{
id = 10,
jsonrpc = '2.0',
- result = false
- }
- }
+ result = false,
+ },
+ },
}
eq(expected, result)
end)
@@ -3936,15 +4334,19 @@ describe('LSP', function()
describe('#dynamic vim.lsp._dynamic', function()
it('supports dynamic registration', function()
- local root_dir = helpers.tmpname()
+ ---@type string
+ local root_dir = tmpname()
os.remove(root_dir)
mkdir(root_dir)
local tmpfile = root_dir .. '/dynamic.foo'
local file = io.open(tmpfile, 'w')
- file:close()
+ if file then
+ file:close()
+ end
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir, tmpfile = ...
local server = _create_server()
@@ -3952,6 +4354,9 @@ describe('LSP', function()
name = 'dynamic-test',
cmd = server.cmd,
root_dir = root_dir,
+ get_language_id = function()
+ return "dummy-lang"
+ end,
capabilities = {
textDocument = {
formatting = {
@@ -3985,6 +4390,13 @@ describe('LSP', function()
{
id = 'range-formatting',
method = 'textDocument/rangeFormatting',
+ registerOptions = {
+ documentSelector = {
+ {
+ language = "dummy-lang"
+ },
+ }
+ }
},
},
}, { client_id = client_id })
@@ -4002,7 +4414,11 @@ describe('LSP', function()
local function check(method, fname)
local bufnr = fname and vim.fn.bufadd(fname) or nil
local client = vim.lsp.get_client_by_id(client_id)
- result[#result + 1] = {method = method, fname = fname, supported = client.supports_method(method, {bufnr = bufnr})}
+ result[#result + 1] = {
+ method = method,
+ fname = fname,
+ supported = client.supports_method(method, {bufnr = bufnr})
+ }
end
@@ -4013,120 +4429,161 @@ describe('LSP', function()
check("textDocument/completion")
return result
- ]], root_dir, tmpfile)
+ ]],
+ root_dir,
+ tmpfile
+ )
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])
+ 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)
describe('vim.lsp._watchfiles', function()
- it('sends notifications when files change', function()
- skip(is_os('bsd'), "bsd only reports rename on folders if file inside change")
- local root_dir = helpers.tmpname()
- os.remove(root_dir)
- mkdir(root_dir)
+ local function test_filechanges(watchfunc)
+ it(
+ string.format('sends notifications when files change (watchfunc=%s)', watchfunc),
+ function()
+ if watchfunc == 'fswatch' then
+ skip(
+ not is_ci() and fn.executable('fswatch') == 0,
+ 'fswatch not installed and not on CI'
+ )
+ skip(is_os('win'), 'not supported on windows')
+ skip(is_os('mac'), 'flaky')
+ end
- exec_lua(create_server_definition)
- local result = exec_lua([[
- local root_dir = ...
+ skip(
+ is_os('bsd'),
+ 'kqueue only reports events on watched folder itself, not contained files #26110'
+ )
- local server = _create_server()
- local client_id = vim.lsp.start({
- name = 'watchfiles-test',
- cmd = server.cmd,
- root_dir = root_dir,
- capabilities = {
- workspace = {
- didChangeWatchedFiles = {
- dynamicRegistration = true,
+ local root_dir = tmpname()
+ os.remove(root_dir)
+ mkdir(root_dir)
+
+ exec_lua(create_server_definition)
+ local result = exec_lua(
+ [[
+ local root_dir, watchfunc = ...
+
+ local server = _create_server()
+ local client_id = vim.lsp.start({
+ name = 'watchfiles-test',
+ cmd = server.cmd,
+ root_dir = root_dir,
+ capabilities = {
+ workspace = {
+ didChangeWatchedFiles = {
+ dynamicRegistration = true,
+ },
},
},
- },
- })
+ })
- local expected_messages = 2 -- initialize, initialized
+ require('vim.lsp._watchfiles')._watchfunc = require('vim._watch')[watchfunc]
- local watchfunc = require('vim.lsp._watchfiles')._watchfunc
- local msg_wait_timeout = watchfunc == vim._watch.poll and 2500 or 200
- local function wait_for_messages()
- 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
+ local expected_messages = 0
- wait_for_messages()
+ local msg_wait_timeout = watchfunc == 'watch' and 200 or 2500
- vim.lsp.handlers['client/registerCapability'](nil, {
- registrations = {
- {
- id = 'watchfiles-test-0',
- method = 'workspace/didChangeWatchedFiles',
- registerOptions = {
- watchers = {
- {
- globPattern = '**/watch',
- kind = 7,
+ 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
+
+ wait_for_message(2) -- initialize, initialized
+
+ vim.lsp.handlers['client/registerCapability'](nil, {
+ registrations = {
+ {
+ id = 'watchfiles-test-0',
+ method = 'workspace/didChangeWatchedFiles',
+ registerOptions = {
+ watchers = {
+ {
+ globPattern = '**/watch',
+ kind = 7,
+ },
},
},
},
},
- },
- }, { client_id = client_id })
+ }, { client_id = client_id })
- if watchfunc == vim._watch.poll then
- vim.wait(100)
- end
+ if watchfunc ~= 'watch' then
+ vim.wait(100)
+ end
- local path = root_dir .. '/watch'
- local file = io.open(path, 'w')
- file:close()
+ local path = root_dir .. '/watch'
+ local tmp = vim.fn.tempname()
+ io.open(tmp, 'w'):close()
+ vim.uv.fs_rename(tmp, path)
- expected_messages = expected_messages + 1
- wait_for_messages()
+ wait_for_message()
- os.remove(path)
+ os.remove(path)
- expected_messages = expected_messages + 1
- wait_for_messages()
+ wait_for_message()
- return server.messages
- ]], root_dir)
+ vim.lsp.stop_client(client_id)
- local function watched_uri(fname)
- return exec_lua([[
- local root_dir, fname = ...
- return vim.uri_from_fname(root_dir .. '/' .. fname)
- ]], root_dir, fname)
- end
+ return server.messages
+ ]],
+ root_dir,
+ watchfunc
+ )
- eq(4, #result)
- eq('workspace/didChangeWatchedFiles', result[3].method)
- eq({
- changes = {
- {
- type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]),
- uri = watched_uri('watch'),
- },
- },
- }, result[3].params)
- eq('workspace/didChangeWatchedFiles', result[4].method)
- eq({
- changes = {
- {
- type = exec_lua([[return vim.lsp.protocol.FileChangeType.Deleted]]),
- uri = watched_uri('watch'),
- },
- },
- }, result[4].params)
- end)
+ local uri = vim.uri_from_fname(root_dir .. '/watch')
+
+ eq(6, #result)
+
+ eq({
+ method = 'workspace/didChangeWatchedFiles',
+ params = {
+ changes = {
+ {
+ type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]),
+ uri = uri,
+ },
+ },
+ },
+ }, result[3])
+
+ eq({
+ method = 'workspace/didChangeWatchedFiles',
+ params = {
+ changes = {
+ {
+ type = exec_lua([[return vim.lsp.protocol.FileChangeType.Deleted]]),
+ uri = uri,
+ },
+ },
+ },
+ }, result[4])
+ end
+ )
+ end
+
+ test_filechanges('watch')
+ test_filechanges('watchdirs')
+ test_filechanges('fswatch')
it('correctly registers and unregisters', function()
local root_dir = '/some_dir'
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir = ...
local server = _create_server()
@@ -4217,13 +4674,19 @@ describe('LSP', function()
wait_for_messages()
return server.messages
- ]], root_dir)
+ ]],
+ root_dir
+ )
local function watched_uri(fname)
- return exec_lua([[
+ return exec_lua(
+ [[
local root_dir, fname = ...
return vim.uri_from_fname(root_dir .. '/' .. fname)
- ]], root_dir, fname)
+ ]],
+ root_dir,
+ fname
+ )
end
eq(4, #result)
@@ -4250,7 +4713,8 @@ describe('LSP', function()
it('correctly handles the registered watch kind', function()
local root_dir = 'some_dir'
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir = ...
local server = _create_server()
@@ -4323,13 +4787,18 @@ describe('LSP', function()
wait_for_messages()
return server.messages
- ]], root_dir)
+ ]],
+ root_dir
+ )
local function watched_uri(fname)
- return exec_lua([[
+ return exec_lua(
+ [[
local fname = ...
return vim.uri_from_fname('/dir/' .. fname)
- ]], fname)
+ ]],
+ fname
+ )
end
eq(3, #result)
@@ -4391,7 +4860,8 @@ describe('LSP', function()
it('prunes duplicate events', function()
local root_dir = 'some_dir'
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir = ...
local server = _create_server()
@@ -4449,12 +4919,17 @@ describe('LSP', function()
wait_for_messages()
return server.messages
- ]], root_dir)
+ ]],
+ root_dir
+ )
local function watched_uri(fname)
- return exec_lua([[
+ return exec_lua(
+ [[
return vim.uri_from_fname(...)
- ]], fname)
+ ]],
+ fname
+ )
end
eq(3, #result)
@@ -4489,7 +4964,8 @@ describe('LSP', function()
]])
local function check_registered(capabilities)
- return exec_lua([[
+ return exec_lua(
+ [[
watching = false
local client_id = vim.lsp.start({
name = 'watchfiles-test',
@@ -4528,31 +5004,41 @@ describe('LSP', function()
vim.lsp.stop_client(client_id, true)
return watching
- ]], capabilities)
+ ]],
+ capabilities
+ )
end
- eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
+ eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
eq(false, check_registered(vim.empty_dict()))
- eq(false, check_registered({
+ eq(
+ false,
+ check_registered({
workspace = {
ignoreMe = true,
},
- }))
- eq(false, check_registered({
+ })
+ )
+ eq(
+ false,
+ check_registered({
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = false,
},
},
- }))
- eq(true, check_registered({
+ })
+ )
+ eq(
+ true,
+ check_registered({
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = true,
},
},
- }))
+ })
+ )
end)
end)
end)
-