aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/buffer_spec.lua18
-rw-r--r--test/functional/api/server_requests_spec.lua9
-rw-r--r--test/functional/api/vim_spec.lua86
-rw-r--r--test/functional/core/channels_spec.lua10
-rw-r--r--test/functional/core/startup_spec.lua5
-rw-r--r--test/functional/editor/meta_key_spec.lua28
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua63
-rw-r--r--test/functional/helpers.lua11
-rw-r--r--test/functional/lua/api_spec.lua33
-rw-r--r--test/functional/lua/commands_spec.lua27
-rw-r--r--test/functional/lua/diagnostic_spec.lua436
-rw-r--r--test/functional/lua/loop_spec.lua8
-rw-r--r--test/functional/lua/luaeval_spec.lua13
-rw-r--r--test/functional/lua/mpack_spec.lua8
-rw-r--r--test/functional/lua/overrides_spec.lua12
-rw-r--r--test/functional/lua/ui_spec.lua25
-rw-r--r--test/functional/lua/vim_spec.lua203
-rw-r--r--test/functional/plugin/health_spec.lua6
-rw-r--r--test/functional/plugin/lsp/codelens_spec.lua27
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua807
-rw-r--r--test/functional/plugin/lsp/incremental_sync_spec.lua266
-rw-r--r--test/functional/plugin/lsp_spec.lua212
-rw-r--r--test/functional/terminal/channel_spec.lua49
-rw-r--r--test/functional/terminal/tui_spec.lua14
-rw-r--r--test/functional/ui/decorations_spec.lua11
-rw-r--r--test/functional/ui/diff_spec.lua23
-rw-r--r--test/functional/ui/float_spec.lua165
-rw-r--r--test/functional/ui/messages_spec.lua43
-rw-r--r--test/functional/vimscript/executable_spec.lua6
-rw-r--r--test/functional/vimscript/exepath_spec.lua3
-rw-r--r--test/functional/vimscript/has_spec.lua7
-rw-r--r--test/functional/vimscript/null_spec.lua2
-rw-r--r--test/helpers.lua10
-rw-r--r--test/unit/api/private_helpers_spec.lua2
-rw-r--r--test/unit/marktree_spec.lua4
35 files changed, 1577 insertions, 1075 deletions
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 01fcfab543..a0c97804b7 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -711,46 +711,46 @@ describe('api/buf', function()
describe('nvim_buf_set_mark', function()
it('works with buffer local marks', function()
curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- eq(true, curbufmeths.set_mark('z', 1, 1))
+ eq(true, curbufmeths.set_mark('z', 1, 1, {}))
eq({1, 1}, curbufmeths.get_mark('z'))
end)
it('works with file/uppercase marks', function()
curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- eq(true, curbufmeths.set_mark('Z', 3, 1))
+ eq(true, curbufmeths.set_mark('Z', 3, 1, {}))
eq({3, 1}, curbufmeths.get_mark('Z'))
end)
it('fails when invalid marks names are used', function()
- eq(false, pcall(curbufmeths.set_mark, '!', 1, 0))
- eq(false, pcall(curbufmeths.set_mark, 'fail', 1, 0))
+ eq(false, pcall(curbufmeths.set_mark, '!', 1, 0, {}))
+ eq(false, pcall(curbufmeths.set_mark, 'fail', 1, 0, {}))
end)
it('fails when invalid buffer number is used', function()
- eq(false, pcall(meths.buf_set_mark, 99, 'a', 1, 1))
+ eq(false, pcall(meths.buf_set_mark, 99, 'a', 1, 1, {}))
end)
end)
describe('nvim_buf_del_mark', function()
it('works with buffer local marks', function()
curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- curbufmeths.set_mark('z', 3, 1)
+ curbufmeths.set_mark('z', 3, 1, {})
eq(true, curbufmeths.del_mark('z'))
eq({0, 0}, curbufmeths.get_mark('z'))
end)
it('works with file/uppercase marks', function()
curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- curbufmeths.set_mark('Z', 3, 3)
+ curbufmeths.set_mark('Z', 3, 3, {})
eq(true, curbufmeths.del_mark('Z'))
eq({0, 0}, curbufmeths.get_mark('Z'))
end)
it('returns false in marks not set in this buffer', function()
local abuf = meths.create_buf(false,true)
bufmeths.set_lines(abuf, -1, -1, true, {'a', 'bit of', 'text'})
- bufmeths.set_mark(abuf, 'A', 2, 2)
+ bufmeths.set_mark(abuf, 'A', 2, 2, {})
eq(false, curbufmeths.del_mark('A'))
eq({2, 2}, bufmeths.get_mark(abuf, 'A'))
end)
it('returns false if mark was not deleted', function()
curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- curbufmeths.set_mark('z', 3, 1)
+ curbufmeths.set_mark('z', 3, 1, {})
eq(true, curbufmeths.del_mark('z'))
eq(false, curbufmeths.del_mark('z')) -- Mark was already deleted
end)
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index e408890906..309d9084c8 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -278,8 +278,9 @@ describe('server -> client', function()
local nvim_argv = merge_args(helpers.nvim_argv, {'--headless'})
local function connect_test(server, mode, address)
local serverpid = funcs.getpid()
- local client = spawn(nvim_argv)
- set_session(client, true)
+ local client = spawn(nvim_argv, false, nil, true)
+ set_session(client)
+
local clientpid = funcs.getpid()
neq(serverpid, clientpid)
local id = funcs.sockconnect(mode, address, {rpc=true})
@@ -288,7 +289,7 @@ describe('server -> client', function()
funcs.rpcrequest(id, 'nvim_set_current_line', 'hello')
local client_id = funcs.rpcrequest(id, 'nvim_get_api_info')[1]
- set_session(server, true)
+ set_session(server)
eq(serverpid, funcs.getpid())
eq('hello', meths.get_current_line())
@@ -296,7 +297,7 @@ describe('server -> client', function()
funcs.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!')
eq(id, funcs.rpcrequest(client_id, 'nvim_get_api_info')[1])
- set_session(client, true)
+ set_session(client)
eq(clientpid, funcs.getpid())
eq('howdy!', meths.get_current_line())
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index f030cfe00e..21de4925b5 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -22,6 +22,7 @@ local source = helpers.source
local next_msg = helpers.next_msg
local tmpname = helpers.tmpname
local write_file = helpers.write_file
+local exec_lua = helpers.exec_lua
local pcall_err = helpers.pcall_err
local format_string = helpers.format_string
@@ -1689,7 +1690,7 @@ describe('API', function()
end)
local it_maybe_pending = it
- if (helpers.isCI('appveyor') and os.getenv('CONFIGURATION') == 'MSVC_32') then
+ if helpers.isCI() and os.getenv('CONFIGURATION') == 'MSVC_32' then
-- For "works with &opt" (flaky on MSVC_32), but not easy to skip alone. #10241
it_maybe_pending = pending
end
@@ -2264,6 +2265,9 @@ describe('API', function()
[2] = {background = tonumber('0xffff40'), bg_indexed = true};
[3] = {background = Screen.colors.Plum1, fg_indexed = true, foreground = tonumber('0x00e000')};
[4] = {bold = true, reverse = true, background = Screen.colors.Plum1};
+ [5] = {foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta, bold = true};
+ [6] = {bold = true};
+ [7] = {reverse = true, background = Screen.colors.LightMagenta};
})
end)
@@ -2311,13 +2315,81 @@ describe('API', function()
|
]]}
end)
+
+ it('can handle input', function()
+ screen:try_resize(50, 10)
+ eq({3, 2}, exec_lua [[
+ buf = vim.api.nvim_create_buf(1,1)
+
+ stream = ''
+ do_the_echo = false
+ function input(_,t1,b1,data)
+ stream = stream .. data
+ _G.vals = {t1, b1}
+ if do_the_echo then
+ vim.api.nvim_chan_send(t1, data)
+ end
+ end
+
+ term = vim.api.nvim_open_term(buf, {on_input=input})
+ vim.api.nvim_open_win(buf, true, {width=40, height=5, row=1, col=1, relative='editor'})
+ return {term, buf}
+ ]])
+
+ screen:expect{grid=[[
+ |
+ {0:~}{1:^ }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+
+ feed 'iba<c-x>bla'
+ screen:expect{grid=[[
+ |
+ {0:~}{7: }{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {6:-- TERMINAL --} |
+ ]]}
+
+ eq('ba\024bla', exec_lua [[ return stream ]])
+ eq({3,2}, exec_lua [[ return vals ]])
+
+ exec_lua [[ do_the_echo = true ]]
+ feed 'herrejösses!'
+
+ screen:expect{grid=[[
+ |
+ {0:~}{1:herrejösses!}{7: }{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~}{1: }{0: }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {6:-- TERMINAL --} |
+ ]]}
+ eq('ba\024blaherrejösses!', exec_lua [[ return stream ]])
+ end)
end)
describe('nvim_del_mark', function()
it('works', function()
local buf = meths.create_buf(false,true)
meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'})
- eq(true, meths.buf_set_mark(buf, 'F', 2, 2))
+ eq(true, meths.buf_set_mark(buf, 'F', 2, 2, {}))
eq(true, meths.del_mark('F'))
eq({0, 0}, meths.buf_get_mark(buf, 'F'))
end)
@@ -2331,9 +2403,9 @@ describe('API', function()
it('works', function()
local buf = meths.create_buf(false,true)
meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'})
- meths.buf_set_mark(buf, 'F', 2, 2)
+ meths.buf_set_mark(buf, 'F', 2, 2, {})
meths.buf_set_name(buf, "mybuf")
- local mark = meths.get_mark('F')
+ local mark = meths.get_mark('F', {})
-- Compare the path tail ony
assert(string.find(mark[4], "mybuf$"))
eq({2, 2, buf.id, mark[4]}, mark)
@@ -2345,7 +2417,7 @@ describe('API', function()
end)
it('returns the expected when mark is not set', function()
eq(true, meths.del_mark('A'))
- eq({0, 0, 0, ''}, meths.get_mark('A'))
+ eq({0, 0, 0, ''}, meths.get_mark('A', {}))
end)
it('works with deleted buffers', function()
local fname = tmpname()
@@ -2353,12 +2425,12 @@ describe('API', function()
nvim("command", "edit " .. fname)
local buf = meths.get_current_buf()
- meths.buf_set_mark(buf, 'F', 2, 2)
+ meths.buf_set_mark(buf, 'F', 2, 2, {})
nvim("command", "new") -- Create new buf to avoid :bd failing
nvim("command", "bd! " .. buf.id)
os.remove(fname)
- local mark = meths.get_mark('F')
+ local mark = meths.get_mark('F', {})
-- To avoid comparing relative vs absolute path
local mfname = mark[4]
local tail_patt = [[[\/][^\/]*$]]
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index 6efa4f9b80..93dec9fb35 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -29,11 +29,11 @@ describe('channels', function()
end)
pending('can connect to socket', function()
- local server = spawn(nvim_argv)
+ local server = spawn(nvim_argv, nil, nil, true)
set_session(server)
local address = funcs.serverlist()[1]
- local client = spawn(nvim_argv)
- set_session(client, true)
+ local client = spawn(nvim_argv, nil, nil, true)
+ set_session(client)
source(init)
meths.set_var('address', address)
@@ -42,11 +42,11 @@ describe('channels', function()
ok(id > 0)
command("call chansend(g:id, msgpackdump([[2,'nvim_set_var',['code',23]]]))")
- set_session(server, true)
+ set_session(server)
retry(nil, 1000, function()
eq(23, meths.get_var('code'))
end)
- set_session(client, true)
+ set_session(client)
command("call chansend(g:id, msgpackdump([[0,0,'nvim_eval',['2+3']]]))")
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index cc6e2c8067..d1dce0f8da 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -414,6 +414,11 @@ describe('startup', function()
eq({'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
eq({'ordinary', 'funky!', 'mittel', 'ordinary after'}, exec_lua [[ return _G.nested_order ]])
end)
+
+ it("handles the correct order when prepending packpath", function()
+ clear{args={'--cmd', 'set packpath^=test/functional/fixtures', '--cmd', [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]]}, env={XDG_CONFIG_HOME='test/functional/fixtures/'}}
+ eq({'ordinary', 'FANCY', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ end)
end)
describe('sysinit', function()
diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua
index c219204409..2280f5bb24 100644
--- a/test/functional/editor/meta_key_spec.lua
+++ b/test/functional/editor/meta_key_spec.lua
@@ -1,6 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command = helpers.command
+local exec_lua = helpers.exec_lua
+local eval = helpers.eval
local expect = helpers.expect
local funcs = helpers.funcs
local eq = helpers.eq
@@ -61,4 +63,30 @@ describe('meta-keys #8226 #13042', function()
feed('u')
expect('hello')
end)
+
+ it('ALT/META terminal-mode', function()
+ exec_lua([[
+ _G.input_data = ''
+ vim.api.nvim_open_term(0, { on_input = function(_, _, _, data)
+ _G.input_data = _G.input_data .. vim.fn.strtrans(data)
+ end })
+ ]])
+ -- Mapped ALT-chord behaves as mapped.
+ command('tnoremap <M-l> meta-l')
+ command('tnoremap <A-j> alt-j')
+ feed('i<M-l> xxx <A-j>')
+ eq('meta-l xxx alt-j', exec_lua([[return _G.input_data]]))
+ -- Unmapped ALT-chord is sent to terminal as-is. #16220
+ exec_lua([[_G.input_data = '']])
+ command('tunmap <M-l>')
+ feed('<M-l>')
+ local meta_l_seq = exec_lua([[return _G.input_data]])
+ command('tnoremap <Esc> <C-\\><C-N>')
+ feed('yyy<M-l><A-j>')
+ eq(meta_l_seq .. 'yyy' .. meta_l_seq .. 'alt-j', exec_lua([[return _G.input_data]]))
+ eq('t', eval('mode(1)'))
+ feed('<Esc>j')
+ eq({ 0, 2, 1, 0, }, funcs.getpos('.'))
+ eq('nt', eval('mode(1)'))
+ end)
end)
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index 9abf478070..5c0de50731 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -275,6 +275,55 @@ function tests.check_forward_content_modified()
}
end
+function tests.check_pending_request_tracked()
+ skeleton {
+ on_init = function(_)
+ return { capabilities = {} }
+ end;
+ body = function()
+ local msg = read_message()
+ assert_eq('slow_request', msg.method)
+ expect_notification('release')
+ respond(msg.id, nil, {})
+ expect_notification('finish')
+ notify('finish')
+ end;
+ }
+end
+
+function tests.check_cancel_request_tracked()
+ skeleton {
+ on_init = function(_)
+ return { capabilities = {} }
+ end;
+ body = function()
+ local msg = read_message()
+ assert_eq('slow_request', msg.method)
+ expect_notification('$/cancelRequest', {id=msg.id})
+ expect_notification('release')
+ respond(msg.id, {code = -32800}, nil)
+ notify('finish')
+ end;
+ }
+end
+
+function tests.check_tracked_requests_cleared()
+ skeleton {
+ on_init = function(_)
+ return { capabilities = {} }
+ end;
+ body = function()
+ local msg = read_message()
+ assert_eq('slow_request', msg.method)
+ expect_notification('$/cancelRequest', {id=msg.id})
+ expect_notification('release')
+ respond(msg.id, nil, {})
+ expect_notification('finish')
+ notify('finish')
+ end;
+ }
+end
+
function tests.basic_finish()
skeleton {
on_init = function(params)
@@ -622,6 +671,20 @@ function tests.code_action_with_resolve()
}
end
+function tests.clientside_commands()
+ skeleton {
+ on_init = function()
+ return {
+ capabilities = {}
+ }
+ end;
+ body = function()
+ notify('start')
+ notify('shutdown')
+ end;
+ }
+end
+
-- Tests will be indexed by TEST_NAME
local kill_timer = vim.loop.new_timer()
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index a26e883370..f152a487af 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -96,10 +96,7 @@ function module.get_session()
return session
end
-function module.set_session(s, keep)
- if session and not keep then
- session:close()
- end
+function module.set_session(s)
session = s
end
@@ -366,7 +363,11 @@ local function remove_args(args, args_rm)
return new_args
end
-function module.spawn(argv, merge, env)
+function module.spawn(argv, merge, env, keep)
+ if session and not keep then
+ session:close()
+ end
+
local child_stream = ChildProcessStream.spawn(
merge and module.merge_args(prepend_argv, argv) or argv,
env)
diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua
index 8551c3d2a0..81e00bba6d 100644
--- a/test/functional/lua/api_spec.lua
+++ b/test/functional/lua/api_spec.lua
@@ -2,6 +2,7 @@
local helpers = require('test.functional.helpers')(after_each)
local exc_exec = helpers.exc_exec
+local remove_trace = helpers.remove_trace
local funcs = helpers.funcs
local clear = helpers.clear
local eval = helpers.eval
@@ -159,44 +160,44 @@ describe('luaeval(vim.api.…)', function()
it('errors out correctly when working with API', function()
-- Conversion errors
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type',
- exc_exec([[call luaeval("vim.api.nvim__id(vim.api.nvim__id)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id(vim.api.nvim__id)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua table',
- exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Cannot convert given lua type',
- exc_exec([[call luaeval("vim.api.nvim__id({42, vim.api.nvim__id})")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({42, vim.api.nvim__id})")]])))
-- Errors in number of arguments
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
- exc_exec([[call luaeval("vim.api.nvim__id()")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id()")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
- exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 2 arguments',
- exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]])))
-- Error in argument types
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua string',
- exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua number',
- exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Number is not integral',
- exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
- exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
- exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
- exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
- exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
- exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Unexpected type',
- exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected lua table',
- exc_exec([[call luaeval("vim.api.nvim_set_keymap('', '', '', '')")]]))
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_keymap('', '', '', '')")]])))
-- TODO: check for errors with Tabpage argument
-- TODO: check for errors with Window argument
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index 2e0d0ea899..9b9ba531b0 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -17,6 +17,7 @@ local pcall_err = helpers.pcall_err
local write_file = helpers.write_file
local exec_capture = helpers.exec_capture
local curbufmeths = helpers.curbufmeths
+local remove_trace = helpers.remove_trace
before_each(clear)
@@ -46,9 +47,9 @@ describe(':lua command', function()
eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']],
pcall_err(command, 'lua ()'))
eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: TEST]],
- exc_exec('lua error("TEST")'))
+ remove_trace(exc_exec('lua error("TEST")')))
eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: Invalid buffer id: -10]],
- exc_exec('lua vim.api.nvim_buf_set_lines(-10, 1, 1, false, {"TEST"})'))
+ remove_trace(exc_exec('lua vim.api.nvim_buf_set_lines(-10, 1, 1, false, {"TEST"})')))
eq({''}, curbufmeths.get_lines(0, 100, false))
end)
it('works with NULL errors', function()
@@ -95,15 +96,15 @@ describe(':lua command', function()
feed(':lua error("fail\\nmuch error\\nsuch details")<cr>')
screen:expect{grid=[[
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
{2: }|
{3:E5108: Error executing lua [string ":lua}|
{3:"]:1: fail} |
{3:much error} |
{3:such details} |
+ {3:stack traceback:} |
+ {3: [C]: in function 'error'} |
+ {3: [string ":lua"]:1: in main chunk}|
+ |
{4:Press ENTER or type command to continue}^ |
]]}
feed('<cr>')
@@ -119,24 +120,24 @@ describe(':lua command', function()
{1:~ }|
|
]]}
- eq('E5108: Error executing lua [string ":lua"]:1: fail\nmuch error\nsuch details', eval('v:errmsg'))
+ eq('E5108: Error executing lua [string ":lua"]:1: fail\nmuch error\nsuch details', remove_trace(eval('v:errmsg')))
local status, err = pcall(command,'lua error("some error\\nin a\\nAPI command")')
local expected = 'Vim(lua):E5108: Error executing lua [string ":lua"]:1: some error\nin a\nAPI command'
eq(false, status)
- eq(expected, string.sub(err, -string.len(expected)))
+ eq(expected, string.sub(remove_trace(err), -string.len(expected)))
feed(':messages<cr>')
screen:expect{grid=[[
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
{2: }|
{3:E5108: Error executing lua [string ":lua}|
{3:"]:1: fail} |
{3:much error} |
{3:such details} |
+ {3:stack traceback:} |
+ {3: [C]: in function 'error'} |
+ {3: [string ":lua"]:1: in main chunk}|
+ |
{4:Press ENTER or type command to continue}^ |
]]}
end)
@@ -219,7 +220,7 @@ describe(':luafile', function()
exc_exec('luafile ' .. fname))
write_file(fname, 'vimm.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})')
eq(("Vim(luafile):E5113: Error while calling lua chunk: %s:1: attempt to index global 'vimm' (a nil value)"):format(fname),
- exc_exec('luafile ' .. fname))
+ remove_trace(exc_exec('luafile ' .. fname)))
end)
it('works with NULL errors', function()
write_file(fname, 'error(nil)')
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index 33469597a1..ec53916024 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -6,6 +6,8 @@ local clear = helpers.clear
local exec_lua = helpers.exec_lua
local eq = helpers.eq
local nvim = helpers.nvim
+local matches = helpers.matches
+local pcall_err = helpers.pcall_err
describe('vim.diagnostic', function()
before_each(function()
@@ -47,7 +49,21 @@ describe('vim.diagnostic', function()
end
function count_extmarks(bufnr, namespace)
- return #vim.api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, {})
+ local ns = vim.diagnostic.get_namespace(namespace)
+ local extmarks = 0
+ if ns.user_data.virt_text_ns then
+ extmarks = extmarks + #vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.virt_text_ns, 0, -1, {})
+ end
+ if ns.user_data.underline_ns then
+ extmarks = extmarks + #vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.underline_ns, 0, -1, {})
+ end
+ return extmarks
+ end
+
+ function get_virt_text_extmarks(ns)
+ local ns = vim.diagnostic.get_namespace(ns)
+ local virt_text_ns = ns.user_data.virt_text_ns
+ return vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, virt_text_ns, 0, -1, {details = true})
end
]]
@@ -252,6 +268,56 @@ describe('vim.diagnostic', function()
]])
end)
+ describe('show() and hide()', function()
+ it('works', function()
+ local result = exec_lua [[
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+
+ local result = {}
+
+ vim.diagnostic.config({ underline = false, virtual_text = true })
+
+ local ns_1_diags = {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 2, 1, 2, 5),
+ }
+ local ns_2_diags = {
+ make_warning("Warning 1", 2, 1, 2, 5),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
+ vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
+
+ -- Both
+ table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns))
+
+ -- Hide one namespace
+ vim.diagnostic.hide(diagnostic_ns)
+ table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns))
+
+ -- Show one namespace
+ vim.diagnostic.show(diagnostic_ns)
+ table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns))
+
+ -- Hide all namespaces
+ vim.diagnostic.hide()
+ table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns))
+
+ -- Show all namespaces
+ vim.diagnostic.show()
+ table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) + count_extmarks(diagnostic_bufnr, other_ns))
+
+ return result
+ ]]
+
+ eq(3, result[1])
+ eq(0, result[2])
+ eq(2, result[3])
+ eq(0, result[4])
+ eq(3, result[5])
+ end)
+ end)
+
describe('reset()', function()
it('diagnostic count is 0 and displayed diagnostics are 0 after call', function()
-- 1 Error (1)
@@ -567,7 +633,7 @@ describe('vim.diagnostic', function()
]]
eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
- eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ -- eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
end)
it('allows filtering by severity', function()
@@ -615,7 +681,7 @@ describe('vim.diagnostic', function()
severity_sort = severity_sort,
})
- local virt_text = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})[1][4].virt_text
+ local virt_text = get_virt_text_extmarks(diagnostic_ns)[1][4].virt_text
local virt_texts = {}
for i = 2, #virt_text do
@@ -661,7 +727,7 @@ describe('vim.diagnostic', function()
}
})
- local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local extmarks = get_virt_text_extmarks(diagnostic_ns)
local virt_text = extmarks[1][4].virt_text[2][1]
return virt_text
]]
@@ -676,7 +742,7 @@ describe('vim.diagnostic', function()
}
}, diagnostic_ns)
- local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local extmarks = get_virt_text_extmarks(diagnostic_ns)
local virt_text = extmarks[1][4].virt_text[2][1]
return virt_text
]]
@@ -696,7 +762,7 @@ describe('vim.diagnostic', function()
}
})
- local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local extmarks = get_virt_text_extmarks(diagnostic_ns)
local virt_text = {extmarks[1][4].virt_text[2][1], extmarks[2][4].virt_text[2][1]}
return virt_text
]]
@@ -724,7 +790,7 @@ describe('vim.diagnostic', function()
make_error('Error', 1, 0, 1, 0),
})
- local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local extmarks = get_virt_text_extmarks(diagnostic_ns)
return {extmarks[1][4].virt_text, extmarks[2][4].virt_text}
]]
eq(" 👀 Warning", result[1][2][1])
@@ -752,7 +818,7 @@ describe('vim.diagnostic', function()
make_error('Error', 1, 0, 1, 0, 'another_linter'),
})
- local extmarks = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, diagnostic_ns, 0, -1, {details = true})
+ local extmarks = get_virt_text_extmarks(diagnostic_ns)
return {extmarks[1][4].virt_text, extmarks[2][4].virt_text}
]]
eq(" some_linter: 👀 Warning", result[1][2][1])
@@ -800,13 +866,11 @@ describe('vim.diagnostic', function()
virtual_text = true,
})
- -- Count how many times we call display.
- SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
-
DisplayCount = 0
- vim.diagnostic._set_virtual_text = function(...)
+ local set_virtual_text = vim.diagnostic.handlers.virtual_text.show
+ vim.diagnostic.handlers.virtual_text.show = function(...)
DisplayCount = DisplayCount + 1
- return SetVirtualTextOriginal(...)
+ return set_virtual_text(...)
end
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
@@ -850,13 +914,12 @@ describe('vim.diagnostic', function()
virtual_text = false,
})
- -- Count how many times we call display.
- SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
DisplayCount = 0
- vim.diagnostic._set_virtual_text = function(...)
+ local set_virtual_text = vim.diagnostic.handlers.virtual_text.show
+ vim.diagnostic.handlers.virtual_text.show = function(...)
DisplayCount = DisplayCount + 1
- return SetVirtualTextOriginal(...)
+ return set_virtual_text(...)
end
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
@@ -968,8 +1031,102 @@ describe('vim.diagnostic', function()
end)
end)
- describe('show_line_diagnostics()', function()
- it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function()
+ describe('open_float()', function()
+ it('can show diagnostics from the whole buffer', function()
+ eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ make_warning("Some warning", 1, 1, 1, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header = false})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+ end)
+
+ it('can show diagnostics from a single line', function()
+ -- Using cursor position
+ eq({'1. Some warning'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ make_warning("Some warning", 1, 1, 1, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ vim.api.nvim_win_set_cursor(0, {2, 1})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="line"})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ -- With specified position
+ eq({'1. Some warning'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ make_warning("Some warning", 1, 1, 1, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ vim.api.nvim_win_set_cursor(0, {1, 1})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="line", pos=1})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+ end)
+
+ it('can show diagnostics from a specific position', function()
+ -- Using cursor position
+ eq({'Syntax error'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 1, 1, 1, 2),
+ make_warning("Some warning", 1, 3, 1, 4),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ vim.api.nvim_win_set_cursor(0, {2, 2})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="cursor"})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ -- With specified position
+ eq({'Some warning'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 1, 1, 1, 2),
+ make_warning("Some warning", 1, 3, 1, 4),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ vim.api.nvim_win_set_cursor(0, {1, 1})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="cursor", pos={1,3}})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ -- With column position past the end of the line. #16062
+ eq({'Syntax error'}, exec_lua [[
+ local first_line_len = #vim.api.nvim_buf_get_lines(diagnostic_bufnr, 0, 1, true)[1]
+ local diagnostics = {
+ make_error("Syntax error", 0, first_line_len + 1, 1, 0),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ vim.api.nvim_win_set_cursor(0, {1, 1})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header=false, scope="cursor", pos={0,first_line_len}})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+ end)
+
+ it('creates floating window and returns float bufnr and winnr if current line contains diagnostics', function()
-- Two lines:
-- Diagnostic:
-- 1. <msg>
@@ -979,8 +1136,10 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics()
- return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {scope="line"})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return #lines
]])
end)
@@ -996,8 +1155,10 @@ describe('vim.diagnostic', function()
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, buf_1_diagnostics)
vim.diagnostic.set(other_ns, other_bufnr, buf_2_diagnostics)
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics()
- return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float()
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return #lines
]])
end)
@@ -1012,12 +1173,14 @@ describe('vim.diagnostic', function()
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diagnostics)
vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diagnostics)
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics({namespace = diagnostic_ns})
- return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {namespace = diagnostic_ns})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return #lines
]])
end)
- it('creates floating window and returns popup bufnr and winnr without header, if requested', function()
+ it('creates floating window and returns float bufnr and winnr without header, if requested', function()
-- One line (since no header):
-- 1. <msg>
eq(1, exec_lua [[
@@ -1026,8 +1189,10 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {show_header = false}
- return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {show_header = false})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return #lines
]])
end)
@@ -1038,8 +1203,10 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics({show_header = false}, diagnostic_bufnr, 5)
- return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {show_header = false, scope = "line", pos = 5})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return #lines
]])
end)
@@ -1051,21 +1218,21 @@ describe('vim.diagnostic', function()
make_error("Syntax error", 0, 1, 0, 3, "source x"),
}
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {
show_header = false,
source = "if_many",
- }
- local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
]])
eq({"1. source x: Syntax error"}, exec_lua [[
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {
show_header = false,
source = "always",
- }
- local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
]])
@@ -1076,11 +1243,11 @@ describe('vim.diagnostic', function()
make_error("Another error", 0, 1, 0, 3, "source y"),
}
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics {
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {
show_header = false,
source = "if_many",
- }
- local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
]])
@@ -1101,28 +1268,138 @@ describe('vim.diagnostic', function()
vim.diagnostic.config({severity_sort = false})
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { show_header = false }
- local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
]])
eq({"1. Syntax error", "2. Error", "3. Warning", "4. Info"}, exec_lua [[
vim.diagnostic.config({severity_sort = true})
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { show_header = false }
- local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
]])
eq({"1. Info", "2. Warning", "3. Error", "4. Syntax error"}, exec_lua [[
vim.diagnostic.config({severity_sort = { reverse = true } })
- local popup_bufnr, winnr = vim.diagnostic.show_line_diagnostics { show_header = false }
- local lines = vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
]])
end)
+
+ it('can filter by severity', function()
+ local count_diagnostics_with_severity = function(min_severity, max_severity)
+ return exec_lua([[
+ local min_severity, max_severity = ...
+ vim.diagnostic.config({
+ float = {
+ severity = {min=min_severity, max=max_severity},
+ },
+ })
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Syntax error", 0, 1, 0, 3),
+ make_info('Info', 0, 3, 0, 4),
+ make_error('Error', 0, 2, 0, 2),
+ make_warning('Warning', 0, 0, 0, 1),
+ })
+
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { show_header = false })
+ if not float_bufnr then
+ return 0
+ end
+
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return #lines
+ ]], min_severity, max_severity)
+ end
+
+ eq(2, count_diagnostics_with_severity("ERROR"))
+ eq(3, count_diagnostics_with_severity("WARN"))
+ eq(1, count_diagnostics_with_severity("WARN", "WARN"))
+ eq(4, count_diagnostics_with_severity("HINT"))
+ eq(0, count_diagnostics_with_severity("HINT", "HINT"))
+ end)
+
+ it('can add a prefix to diagnostics', function()
+ -- Default is to add a number
+ eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ make_warning("Some warning", 1, 1, 1, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header = false, number = "always"})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ eq({'Syntax error', 'Some warning'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ make_warning("Some warning", 1, 1, 1, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {show_header = false, prefix = ""})
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ make_warning("Some warning", 1, 1, 1, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {
+ show_header = false,
+ prefix = function(_, i, total)
+ -- Only show a number if there is more than one diagnostic
+ if total > 1 then
+ return string.format("%d. ", i)
+ end
+ return ""
+ end,
+ })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ eq({'Syntax error'}, exec_lua [[
+ local diagnostics = {
+ make_error("Syntax error", 0, 1, 0, 3),
+ }
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {
+ show_header = false,
+ prefix = function(_, i, total)
+ -- Only show a number if there is more than one diagnostic
+ if total > 1 then
+ return string.format("%d. ", i)
+ end
+ return ""
+ end,
+ })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]])
+
+ eq("Error executing lua: .../diagnostic.lua:0: prefix: expected 'string' or 'function', got 42",
+ pcall_err(exec_lua, [[ vim.diagnostic.open_float(0, { prefix = 42 }) ]]))
+ end)
end)
describe('setloclist()', function()
@@ -1243,4 +1520,73 @@ describe('vim.diagnostic', function()
eq(result[1], result[2])
end)
end)
+
+ describe('handlers', function()
+ it('checks that a new handler is a table', function()
+ matches([[.*handler: expected table, got string.*]], pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = "bar" ]]))
+ matches([[.*handler: expected table, got function.*]], pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = function() end ]]))
+ end)
+
+ it('can add new handlers', function()
+ eq(true, exec_lua [[
+ local handler_called = false
+ vim.diagnostic.handlers.test = {
+ show = function(namespace, bufnr, diagnostics, opts)
+ assert(namespace == diagnostic_ns)
+ assert(bufnr == diagnostic_bufnr)
+ assert(#diagnostics == 1)
+ assert(opts.test.some_opt == 42)
+ handler_called = true
+ end,
+ }
+
+ vim.diagnostic.config({test = {some_opt = 42}})
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning("Warning", 0, 0, 0, 0),
+ })
+ return handler_called
+ ]])
+ end)
+
+ it('can disable handlers by setting the corresponding option to false', function()
+ eq(false, exec_lua [[
+ local handler_called = false
+ vim.diagnostic.handlers.test = {
+ show = function(namespace, bufnr, diagnostics, opts)
+ handler_called = true
+ end,
+ }
+
+ vim.diagnostic.config({test = false})
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning("Warning", 0, 0, 0, 0),
+ })
+ return handler_called
+ ]])
+ end)
+
+ it('always calls a handler\'s hide function if defined', function()
+ eq({false, true}, exec_lua [[
+ local hide_called = false
+ local show_called = false
+ vim.diagnostic.handlers.test = {
+ show = function(namespace, bufnr, diagnostics, opts)
+ show_called = true
+ end,
+ hide = function(namespace, bufnr)
+ assert(namespace == diagnostic_ns)
+ assert(bufnr == diagnostic_bufnr)
+ hide_called = true
+ end,
+ }
+
+ vim.diagnostic.config({test = false})
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_warning("Warning", 0, 0, 0, 0),
+ })
+ vim.diagnostic.hide(diagnostic_ns, diagnostic_bufnr)
+ return {show_called, hide_called}
+ ]])
+ end)
+ end)
end)
diff --git a/test/functional/lua/loop_spec.lua b/test/functional/lua/loop_spec.lua
index 992d1666f6..7f3787d7bf 100644
--- a/test/functional/lua/loop_spec.lua
+++ b/test/functional/lua/loop_spec.lua
@@ -84,14 +84,14 @@ describe('vim.loop', function()
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
{2: }|
{3:Error executing luv callback:} |
{3:[string "<nvim>"]:5: E5560: nvim_set_var must not }|
{3:be called in a lua loop callback} |
+ {3:stack traceback:} |
+ {3: [C]: in function 'nvim_set_var'} |
+ {3: [string "<nvim>"]:5: in function <[string }|
+ {3:"<nvim>"]:2>} |
{4:Press ENTER or type command to continue}^ |
]])
feed('<cr>')
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index 0675ec9abd..c543dd1995 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -4,6 +4,7 @@ local Screen = require('test.functional.ui.screen')
local pcall_err = helpers.pcall_err
local exc_exec = helpers.exc_exec
+local remove_trace = helpers.remove_trace
local exec_lua = helpers.exec_lua
local command = helpers.command
local meths = helpers.meths
@@ -424,11 +425,11 @@ describe('luaeval()', function()
it('errors out correctly when doing incorrect things in lua', function()
-- Conversion errors
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: attempt to call field \'xxx_nonexistent_key_xxx\' (a nil value)',
- exc_exec([[call luaeval("vim.xxx_nonexistent_key_xxx()")]]))
+ remove_trace(exc_exec([[call luaeval("vim.xxx_nonexistent_key_xxx()")]])))
eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: ERROR',
- exc_exec([[call luaeval("error('ERROR')")]]))
+ remove_trace(exc_exec([[call luaeval("error('ERROR')")]])))
eq('Vim(call):E5108: Error executing lua [NULL]',
- exc_exec([[call luaeval("error(nil)")]]))
+ remove_trace(exc_exec([[call luaeval("error(nil)")]])))
end)
it('does not leak memory when called with too long line',
@@ -527,6 +528,12 @@ describe('v:lua', function()
]]}
end)
+ it('supports packages', function()
+ command('set pp+=test/functional/fixtures')
+ eq('\tbadval', eval("v:lua.require'leftpad'('badval')"))
+ eq(9003, eval("v:lua.require'bar'.doit()"))
+ end)
+
it('throw errors for invalid use', function()
eq('Vim(let):E15: Invalid expression: v:lua.func', pcall_err(command, "let g:Func = v:lua.func"))
eq('Vim(let):E15: Invalid expression: v:lua', pcall_err(command, "let g:Func = v:lua"))
diff --git a/test/functional/lua/mpack_spec.lua b/test/functional/lua/mpack_spec.lua
index ef693f01f3..cc788ed8bb 100644
--- a/test/functional/lua/mpack_spec.lua
+++ b/test/functional/lua/mpack_spec.lua
@@ -7,16 +7,16 @@ local exec_lua = helpers.exec_lua
describe('lua vim.mpack', function()
before_each(clear)
- it('can pack vim.NIL', function()
+ it('encodes vim.NIL', function()
eq({true, true, true, true}, exec_lua [[
- local var = vim.mpack.unpack(vim.mpack.pack({33, vim.NIL, 77}))
+ local var = vim.mpack.decode(vim.mpack.encode({33, vim.NIL, 77}))
return {var[1]==33, var[2]==vim.NIL, var[3]==77, var[4]==nil}
]])
end)
- it('can pack vim.empty_dict()', function()
+ it('encodes vim.empty_dict()', function()
eq({{{}, "foo", {}}, true, false}, exec_lua [[
- local var = vim.mpack.unpack(vim.mpack.pack({{}, "foo", vim.empty_dict()}))
+ local var = vim.mpack.decode(vim.mpack.encode({{}, "foo", vim.empty_dict()}))
return {var, vim.tbl_islist(var[1]), vim.tbl_islist(var[3])}
]])
end)
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua
index 636479b81f..b0712ff366 100644
--- a/test/functional/lua/overrides_spec.lua
+++ b/test/functional/lua/overrides_spec.lua
@@ -161,15 +161,15 @@ describe('debug.debug', function()
{0:~ }|
{0:~ }|
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
nil |
lua_debug> print("TEST") |
TEST |
|
{E:E5108: Error executing lua [string ":lua"]:5: attempt}|
{E: to perform arithmetic on local 'a' (a nil value)} |
+ {E:stack traceback:} |
+ {E: [string ":lua"]:5: in function 'Test'} |
+ {E: [string ":lua"]:1: in main chunk} |
Interrupt: {cr:Press ENTER or type command to continue}^ |
]]}
feed('<C-l>:lua Test()\n')
@@ -197,13 +197,13 @@ describe('debug.debug', function()
{0:~ }|
{0:~ }|
{0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
nil |
lua_debug> |
{E:E5108: Error executing lua [string ":lua"]:5: attempt}|
{E: to perform arithmetic on local 'a' (a nil value)} |
+ {E:stack traceback:} |
+ {E: [string ":lua"]:5: in function 'Test'} |
+ {E: [string ":lua"]:1: in main chunk} |
{cr:Press ENTER or type command to continue}^ |
]]}
end)
diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua
index 94f1b5840b..2371939204 100644
--- a/test/functional/lua/ui_spec.lua
+++ b/test/functional/lua/ui_spec.lua
@@ -43,4 +43,29 @@ describe('vim.ui', function()
}, result[2])
end)
end)
+
+ describe('input', function()
+ it('can input text', function()
+ local result = exec_lua[[
+ local opts = {
+ prompt = 'Input: ',
+ }
+ local input
+ local cb = function(item)
+ input = item
+ end
+ -- input would require input and block the test;
+ local prompt
+ vim.fn.input = function(opts)
+ prompt = opts.prompt
+ return "Inputted text"
+ end
+ vim.ui.input(opts, cb)
+ vim.wait(100, function() return input ~= nil end)
+ return {input, prompt}
+ ]]
+ eq('Inputted text', result[1])
+ eq('Input: ', result[2])
+ end)
+ end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index a739992611..3832d27a22 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -4,7 +4,6 @@ local Screen = require('test.functional.ui.screen')
local funcs = helpers.funcs
local meths = helpers.meths
-local dedent = helpers.dedent
local command = helpers.command
local insert = helpers.insert
local clear = helpers.clear
@@ -19,6 +18,7 @@ local source = helpers.source
local NIL = helpers.NIL
local retry = helpers.retry
local next_msg = helpers.next_msg
+local remove_trace = helpers.remove_trace
before_each(clear)
@@ -121,11 +121,6 @@ describe('lua stdlib', function()
eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
end)
- -- for brevity, match only the error header (not the traceback)
- local function pcall_header(...)
- return string.gsub(string.gsub(pcall_err(exec_lua, ...), '[\r\n].*', ''), '^Error executing lua: ', '')
- end
-
it('vim.startswith', function()
eq(true, funcs.luaeval('vim.startswith("123", "1")'))
eq(true, funcs.luaeval('vim.startswith("123", "")'))
@@ -136,8 +131,10 @@ describe('lua stdlib', function()
eq(false, funcs.luaeval('vim.startswith("123", "2")'))
eq(false, funcs.luaeval('vim.startswith("123", "1234")'))
- eq("vim/shared.lua:0: prefix: expected string, got nil", pcall_header 'return vim.startswith("123", nil)')
- eq("vim/shared.lua:0: s: expected string, got nil", pcall_header 'return vim.startswith(nil, "123")')
+ eq("Error executing lua: vim/shared.lua:0: prefix: expected string, got nil",
+ pcall_err(exec_lua, 'return vim.startswith("123", nil)'))
+ eq("Error executing lua: vim/shared.lua:0: s: expected string, got nil",
+ pcall_err(exec_lua, 'return vim.startswith(nil, "123")'))
end)
it('vim.endswith', function()
@@ -150,8 +147,10 @@ describe('lua stdlib', function()
eq(false, funcs.luaeval('vim.endswith("123", "2")'))
eq(false, funcs.luaeval('vim.endswith("123", "1234")'))
- eq("vim/shared.lua:0: suffix: expected string, got nil", pcall_header 'return vim.endswith("123", nil)')
- eq("vim/shared.lua:0: s: expected string, got nil", pcall_header 'return vim.endswith(nil, "123")')
+ eq("Error executing lua: vim/shared.lua:0: suffix: expected string, got nil",
+ pcall_err(exec_lua, 'return vim.endswith("123", nil)'))
+ eq("Error executing lua: vim/shared.lua:0: s: expected string, got nil",
+ pcall_err(exec_lua, 'return vim.endswith(nil, "123")'))
end)
it("vim.str_utfindex/str_byteindex", function()
@@ -179,6 +178,37 @@ describe('lua stdlib', function()
end
end)
+ it("vim.str_utf_start", function()
+ exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
+ local expected_positions = {0,0,0,0,-1,0,-1,0,-1,0,0,-1,0,0,-1,-2,0,-1,-2,0,0,-1,-2,0,0,-1,-2,-3,0,0,-1,-2,-3,0,0,0,-1,0,0,-1,0,-1,0,-1,0,-1,0,-1}
+ eq(expected_positions, exec_lua([[
+ local start_codepoint_positions = {}
+ for idx = 1, #_G.test_text do
+ table.insert(start_codepoint_positions, vim.str_utf_start(_G.test_text, idx))
+ end
+ return start_codepoint_positions
+ ]]))
+ end)
+
+ it("vim.str_utf_end", function()
+ exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
+ local expected_positions = {0,0,0,1,0,1,0,1,0,0,1,0,0,2,1,0,2,1,0,0,2,1,0,0,3,2,1,0,0,3,2,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0 }
+ eq(expected_positions, exec_lua([[
+ local end_codepoint_positions = {}
+ for idx = 1, #_G.test_text do
+ table.insert(end_codepoint_positions, vim.str_utf_end(_G.test_text, idx))
+ end
+ return end_codepoint_positions
+ ]]))
+ end)
+
+
+ it("vim.str_utf_pos", function()
+ exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 å بِيَّ"]])
+ local expected_positions = { 1,2,3,4,6,8,10,11,13,14,17,20,21,24,25,29,30,34,35,36,38,39,41,43,45,47 }
+ eq(expected_positions, exec_lua("return vim.str_utf_pos(_G.test_text)"))
+ end)
+
it("vim.schedule", function()
exec_lua([[
test_table = {}
@@ -202,7 +232,7 @@ describe('lua stdlib', function()
]])
feed("<cr>")
- eq('Error executing vim.schedule lua callback: [string "<nvim>"]:2: big failure\nvery async', eval("v:errmsg"))
+ eq('Error executing vim.schedule lua callback: [string "<nvim>"]:2: big failure\nvery async', remove_trace(eval("v:errmsg")))
local screen = Screen.new(60,5)
screen:set_default_attr_ids({
@@ -228,10 +258,10 @@ describe('lua stdlib', function()
end)
]])
screen:expect{grid=[[
- |
- {2: }|
- {3:Error executing vim.schedule lua callback: [string "<nvim>"]}|
- {3::2: Vim(echo):E115: Missing quote: 'err} |
+ {3:stack traceback:} |
+ {3: [C]: in function 'nvim_command'} |
+ {3: [string "<nvim>"]:2: in function <[string "<nvim>"]:}|
+ {3:1>} |
{4:Press ENTER or type command to continue}^ |
]]}
end)
@@ -275,22 +305,11 @@ describe('lua stdlib', function()
-- Validates args.
eq(true, pcall(split, 'string', 'string'))
- eq(dedent([[
- Error executing lua: vim/shared.lua:0: s: expected string, got number
- stack traceback:
- vim/shared.lua:0: in function 'gsplit'
- vim/shared.lua:0: in function <vim/shared.lua:0>]]),
+ eq('Error executing lua: vim/shared.lua:0: s: expected string, got number',
pcall_err(split, 1, 'string'))
- eq(dedent([[
- Error executing lua: vim/shared.lua:0: sep: expected string, got number
- stack traceback:
- vim/shared.lua:0: in function 'gsplit'
- vim/shared.lua:0: in function <vim/shared.lua:0>]]),
+ eq('Error executing lua: vim/shared.lua:0: sep: expected string, got number',
pcall_err(split, 'string', 1))
- eq(dedent([[
- Error executing lua: vim/shared.lua:0: kwargs: expected table, got number
- stack traceback:
- vim/shared.lua:0: in function <vim/shared.lua:0>]]),
+ eq('Error executing lua: vim/shared.lua:0: kwargs: expected table, got number',
pcall_err(split, 'string', 'string', 1))
end)
@@ -311,10 +330,7 @@ describe('lua stdlib', function()
end
-- Validates args.
- eq(dedent([[
- Error executing lua: vim/shared.lua:0: s: expected string, got number
- stack traceback:
- vim/shared.lua:0: in function <vim/shared.lua:0>]]),
+ eq('Error executing lua: vim/shared.lua:0: s: expected string, got number',
pcall_err(trim, 2))
end)
@@ -393,10 +409,7 @@ describe('lua stdlib', function()
eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]]))
-- Validates args.
- eq(dedent([[
- Error executing lua: vim/shared.lua:0: s: expected string, got number
- stack traceback:
- vim/shared.lua:0: in function <vim/shared.lua:0>]]),
+ eq('Error executing lua: vim/shared.lua:0: s: expected string, got number',
pcall_err(exec_lua, [[return vim.pesc(2)]]))
end)
@@ -679,10 +692,7 @@ describe('lua stdlib', function()
it('vim.list_extend', function()
eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]])
- eq(dedent([[
- Error executing lua: vim/shared.lua:0: src: expected table, got nil
- stack traceback:
- vim/shared.lua:0: in function <vim/shared.lua:0>]]),
+ eq('Error executing lua: vim/shared.lua:0: src: expected table, got nil',
pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]]))
eq({1,2}, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]])
eq(true, exec_lua [[ local a = {1} return vim.list_extend(a, {2;a=1}) == a ]])
@@ -814,12 +824,12 @@ describe('lua stdlib', function()
end)
]])
screen:expect{grid=[[
- foo |
- {1:~ }|
- {2: }|
- {3:Error executing luv callback:} |
{3:[string "<nvim>"]:6: E5560: rpcrequest must not be}|
{3: called in a lua loop callback} |
+ {3:stack traceback:} |
+ {3: [C]: in function 'rpcrequest'} |
+ {3: [string "<nvim>"]:6: in function <[string }|
+ {3:"<nvim>"]:2>} |
{4:Press ENTER or type command to continue}^ |
]]}
feed('<cr>')
@@ -883,76 +893,37 @@ describe('lua stdlib', function()
exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}")
exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}")
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number',
pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: invalid type name: x
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: invalid type name: x',
pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: invalid type name: 1
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: invalid type name: 1',
pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: invalid type name: nil
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: invalid type name: nil',
pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}"))
-- Validated parameters are required by default.
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil',
pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
-- Explicitly required.
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil',
pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number',
pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number',
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil',
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil',
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3',
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3',
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
-- Pass an additional message back.
- eq(dedent([[
- Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG
- stack traceback:
- [string "<nvim>"]:0: in main chunk]]),
+ eq('Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG',
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}"))
end)
@@ -996,6 +967,9 @@ describe('lua stdlib', function()
vim.g.to_delete = nil
]]
eq(NIL, funcs.luaeval "vim.g.to_delete")
+
+ matches([[^Error executing lua: .*: attempt to index .* nil value]],
+ pcall_err(exec_lua, 'return vim.g[0].testing'))
end)
it('vim.b', function()
@@ -1005,18 +979,25 @@ describe('lua stdlib', function()
vim.api.nvim_buf_set_var(0, "floaty", 5120.1)
vim.api.nvim_buf_set_var(0, "nullvar", vim.NIL)
vim.api.nvim_buf_set_var(0, "to_delete", {hello="world"})
+ BUF = vim.api.nvim_create_buf(false, true)
+ vim.api.nvim_buf_set_var(BUF, "testing", "bye")
]]
eq('hi', funcs.luaeval "vim.b.testing")
+ eq('bye', funcs.luaeval "vim.b[BUF].testing")
eq(123, funcs.luaeval "vim.b.other")
eq(5120.1, funcs.luaeval "vim.b.floaty")
eq(NIL, funcs.luaeval "vim.b.nonexistant")
+ eq(NIL, funcs.luaeval "vim.b[BUF].nonexistant")
eq(NIL, funcs.luaeval "vim.b.nullvar")
-- lost over RPC, so test locally:
eq({false, true}, exec_lua [[
return {vim.b.nonexistant == vim.NIL, vim.b.nullvar == vim.NIL}
]])
+ matches([[^Error executing lua: .*: attempt to index .* nil value]],
+ pcall_err(exec_lua, 'return vim.b[BUF][0].testing'))
+
eq({hello="world"}, funcs.luaeval "vim.b.to_delete")
exec_lua [[
vim.b.to_delete = nil
@@ -1037,11 +1018,22 @@ describe('lua stdlib', function()
vim.api.nvim_win_set_var(0, "testing", "hi")
vim.api.nvim_win_set_var(0, "other", 123)
vim.api.nvim_win_set_var(0, "to_delete", {hello="world"})
+ BUF = vim.api.nvim_create_buf(false, true)
+ WIN = vim.api.nvim_open_win(BUF, false, {
+ width=10, height=10,
+ relative='win', row=0, col=0
+ })
+ vim.api.nvim_win_set_var(WIN, "testing", "bye")
]]
eq('hi', funcs.luaeval "vim.w.testing")
+ eq('bye', funcs.luaeval "vim.w[WIN].testing")
eq(123, funcs.luaeval "vim.w.other")
eq(NIL, funcs.luaeval "vim.w.nonexistant")
+ eq(NIL, funcs.luaeval "vim.w[WIN].nonexistant")
+
+ matches([[^Error executing lua: .*: attempt to index .* nil value]],
+ pcall_err(exec_lua, 'return vim.w[WIN][0].testing'))
eq({hello="world"}, funcs.luaeval "vim.w.to_delete")
exec_lua [[
@@ -1068,6 +1060,12 @@ describe('lua stdlib', function()
eq('hi', funcs.luaeval "vim.t.testing")
eq(123, funcs.luaeval "vim.t.other")
eq(NIL, funcs.luaeval "vim.t.nonexistant")
+ eq('hi', funcs.luaeval "vim.t[0].testing")
+ eq(123, funcs.luaeval "vim.t[0].other")
+ eq(NIL, funcs.luaeval "vim.t[0].nonexistant")
+
+ matches([[^Error executing lua: .*: attempt to index .* nil value]],
+ pcall_err(exec_lua, 'return vim.t[0][0].testing'))
eq({hello="world"}, funcs.luaeval "vim.t.to_delete")
exec_lua [[
@@ -1096,6 +1094,8 @@ describe('lua stdlib', function()
eq(funcs.luaeval "vim.api.nvim_get_vvar('progpath')", funcs.luaeval "vim.v.progpath")
eq(false, funcs.luaeval "vim.v['false']")
eq(NIL, funcs.luaeval "vim.v.null")
+ matches([[^Error executing lua: .*: attempt to index .* nil value]],
+ pcall_err(exec_lua, 'return vim.v[0].progpath'))
end)
it('vim.bo', function()
@@ -2030,6 +2030,8 @@ describe('lua stdlib', function()
-- Would wait ten seconds if results blocked.
wait_result = vim.wait(10000, function() return vim.g.timer_result end)
+ timer:close()
+
return {
time = (start_time + 5) > get_time(),
wait_result = wait_result,
@@ -2049,6 +2051,8 @@ describe('lua stdlib', function()
wait_result = vim.wait(300, function() return vim.g.timer_result end, nil, true)
+ timer:close()
+
return {
wait_result = wait_result,
}
@@ -2069,9 +2073,10 @@ describe('lua stdlib', function()
end)
it('should not crash when callback errors', function()
- eq({false, '[string "<nvim>"]:1: As Expected'}, exec_lua [[
+ local result = exec_lua [[
return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)}
- ]])
+ ]]
+ eq({false, '[string "<nvim>"]:1: As Expected'}, {result[1], remove_trace(result[2])})
end)
it('if callback is passed, it must be a function', function()
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index b84e9d1533..b567b3e20c 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -134,7 +134,7 @@ describe('health.vim', function()
command("checkhealth test_plug*")
local buf_lines = helpers.curbuf('get_lines', 0, -1, true)
-- avoid dealing with path separators
- local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2)
+ local received = table.concat(buf_lines, '\n', 1, #buf_lines - 5)
local expected = helpers.dedent([[
test_plug: require("test_plug.health").check()
@@ -175,10 +175,10 @@ describe('health.vim', function()
it("gracefully handles broken lua healthcheck", function()
command("checkhealth test_plug.submodule_failed")
local buf_lines = helpers.curbuf('get_lines', 0, -1, true)
- local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2)
+ local received = table.concat(buf_lines, '\n', 1, #buf_lines - 5)
-- avoid dealing with path separators
local lua_err = "attempt to perform arithmetic on a nil value"
- local last_line = buf_lines[#buf_lines - 1]
+ local last_line = buf_lines[#buf_lines - 4]
assert(string.find(last_line, lua_err) ~= nil, "Lua error not present")
local expected = global_helpers.dedent([[
diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua
index c8b75e65fc..ecc2f579b8 100644
--- a/test/functional/plugin/lsp/codelens_spec.lua
+++ b/test/functional/plugin/lsp/codelens_spec.lua
@@ -60,31 +60,4 @@ describe('vim.lsp.codelens', function()
eq({[1] = {'Lens1', 'LspCodeLens'}}, virtual_text_chunks)
end)
- it('codelens uses client commands', function()
- local fake_uri = "file:///fake/uri"
- local cmd = exec_lua([[
- fake_uri = ...
- local bufnr = vim.uri_to_bufnr(fake_uri)
- vim.fn.bufload(bufnr)
- vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'One line'})
- local lenses = {
- {
- range = {
- start = { line = 0, character = 0, },
- ['end'] = { line = 0, character = 8 }
- },
- command = { title = 'Lens1', command = 'Dummy' }
- },
- }
- vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr})
- local cmd_called = nil
- vim.lsp.commands['Dummy'] = function(command)
- cmd_called = command
- end
- vim.api.nvim_set_current_buf(bufnr)
- vim.lsp.codelens.run()
- return cmd_called
- ]], fake_uri)
- eq({ command = 'Dummy', title = 'Lens1' }, cmd)
- end)
end)
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 243ad6bdb8..1269a2350c 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -3,7 +3,6 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local exec_lua = helpers.exec_lua
local eq = helpers.eq
-local nvim = helpers.nvim
describe('vim.lsp.diagnostic', function()
local fake_uri
@@ -45,11 +44,32 @@ describe('vim.lsp.diagnostic', function()
}
end
- count_of_extmarks_for_client = function(bufnr, client_id)
- return #vim.api.nvim_buf_get_extmarks(
- bufnr, vim.lsp.diagnostic.get_namespace(client_id), 0, -1, {}
- )
+ function get_extmarks(bufnr, client_id)
+ local namespace = vim.lsp.diagnostic.get_namespace(client_id)
+ local ns = vim.diagnostic.get_namespace(namespace)
+ local extmarks = {}
+ if ns.user_data.virt_text_ns then
+ for _, e in pairs(vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.virt_text_ns, 0, -1, {details=true})) do
+ table.insert(extmarks, e)
+ end
+ end
+ if ns.user_data.underline_ns then
+ for _, e in pairs(vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.underline_ns, 0, -1, {details=true})) do
+ table.insert(extmarks, e)
+ end
+ end
+ return extmarks
end
+
+ client_id = vim.lsp.start_client {
+ cmd_env = {
+ NVIM_LUA_NOTRACK = "1";
+ };
+ cmd = {
+ vim.v.progpath, '-es', '-u', 'NONE', '--headless'
+ };
+ offset_encoding = "utf-16";
+ }
]]
fake_uri = "file:///fake/uri"
@@ -69,366 +89,6 @@ describe('vim.lsp.diagnostic', function()
end)
describe('vim.lsp.diagnostic', function()
- describe('handle_publish_diagnostics', function()
- it('should be able to retrieve diagnostics from all buffers and clients', function()
- local result = exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 2, 1, 2, 1),
- }, 1, 1
- )
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #3', 3, 1, 3, 1),
- }, 2, 2
- )
- return vim.lsp.diagnostic.get_all()
- ]]
- eq(2, #result)
- eq(2, #result[1])
- eq('Diagnostic #1', result[1][1].message)
- end)
- it('should be able to save and count a single client error', function()
- eq(1, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- }, 0, 1
- )
- return vim.lsp.diagnostic.get_count(0, "Error", 1)
- ]])
- end)
-
- it('should be able to save and count from two clients', function()
- eq(2, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 2, 1, 2, 1),
- }, 0, 1
- )
- return vim.lsp.diagnostic.get_count(0, "Error", 1)
- ]])
- end)
-
- it('should be able to save and count from multiple clients', function()
- eq({1, 1, 2}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic From Server 1', 1, 1, 1, 1),
- }, 0, 1
- )
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic From Server 2', 1, 1, 1, 1),
- }, 0, 2
- )
- return {
- -- Server 1
- vim.lsp.diagnostic.get_count(0, "Error", 1),
- -- Server 2
- vim.lsp.diagnostic.get_count(0, "Error", 2),
- -- All servers
- vim.lsp.diagnostic.get_count(0, "Error", nil),
- }
- ]])
- end)
-
- it('should be able to save and count from multiple clients with respect to severity', function()
- eq({3, 0, 3}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
- make_error('Diagnostic From Server 1:2', 2, 2, 2, 2),
- make_error('Diagnostic From Server 1:3', 2, 3, 3, 2),
- }, 0, 1
- )
- vim.lsp.diagnostic.save(
- {
- make_warning('Warning From Server 2', 3, 3, 3, 3),
- }, 0, 2
- )
- return {
- -- Server 1
- vim.lsp.diagnostic.get_count(0, "Error", 1),
- -- Server 2
- vim.lsp.diagnostic.get_count(0, "Error", 2),
- -- All servers
- vim.lsp.diagnostic.get_count(0, "Error", nil),
- }
- ]])
- end)
- it('should handle one server clearing highlights while the other still has highlights', function()
- -- 1 Error (1)
- -- 1 Warning (2)
- -- 1 Warning (2) + 1 Warning (1)
- -- 2 highlights and 2 underlines (since error)
- -- 1 highlight + 1 underline
- local all_highlights = {1, 1, 2, 4, 2}
- eq(all_highlights, exec_lua [[
- local server_1_diags = {
- make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 2, 1, 2, 5),
- }
- local server_2_diags = {
- make_warning("Warning 1", 2, 1, 2, 5),
- }
-
- vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1})
- vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2})
- return {
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- }
- ]])
-
- -- Clear diagnostics from server 1, and make sure we have the right amount of stuff for client 2
- eq({1, 1, 2, 0, 2}, exec_lua [[
- vim.lsp.diagnostic.disable(diagnostic_bufnr, 1)
- return {
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- }
- ]])
-
- -- Show diagnostics from server 1 again
- eq(all_highlights, exec_lua([[
- vim.lsp.diagnostic.enable(diagnostic_bufnr, 1)
- return {
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- }
- ]]))
- end)
-
- it('should not display diagnostics when disabled', function()
- eq({0, 2}, exec_lua [[
- local server_1_diags = {
- make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 2, 1, 2, 5),
- }
- local server_2_diags = {
- make_warning("Warning 1", 2, 1, 2, 5),
- }
-
- vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1})
- vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2})
-
- vim.lsp.diagnostic.disable(diagnostic_bufnr, 1)
-
- return {
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- }
- ]])
-
- eq({4, 0}, exec_lua [[
- vim.lsp.diagnostic.enable(diagnostic_bufnr, 1)
- vim.lsp.diagnostic.disable(diagnostic_bufnr, 2)
-
- return {
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- }
- ]])
- end)
-
- describe('reset', function()
- it('diagnostic count is 0 and displayed diagnostics are 0 after call', function()
- -- 1 Error (1)
- -- 1 Warning (2)
- -- 1 Warning (2) + 1 Warning (1)
- -- 2 highlights and 2 underlines (since error)
- -- 1 highlight + 1 underline
- local all_highlights = {1, 1, 2, 4, 2}
- eq(all_highlights, exec_lua [[
- local server_1_diags = {
- make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 2, 1, 2, 5),
- }
- local server_2_diags = {
- make_warning("Warning 1", 2, 1, 2, 5),
- }
-
- vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_1_diags }, {client_id=1})
- vim.lsp.diagnostic.on_publish_diagnostics(nil, { uri = fake_uri, diagnostics = server_2_diags }, {client_id=2})
- return {
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- }
- ]])
-
- -- Reset diagnostics from server 1
- exec_lua([[ vim.lsp.diagnostic.reset(1, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]])
-
- -- Make sure we have the right diagnostic count
- eq({0, 1, 1, 0, 2} , exec_lua [[
- local diagnostic_count = {}
- vim.wait(100, function () diagnostic_count = {
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- } end )
- return diagnostic_count
- ]])
-
- -- Reset diagnostics from server 2
- exec_lua([[ vim.lsp.diagnostic.reset(2, { [ diagnostic_bufnr ] = { [ 1 ] = true ; [ 2 ] = true } } )]])
-
- -- Make sure we have the right diagnostic count
- eq({0, 0, 0, 0, 0}, exec_lua [[
- local diagnostic_count = {}
- vim.wait(100, function () diagnostic_count = {
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", 2),
- vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Warning", nil),
- count_of_extmarks_for_client(diagnostic_bufnr, 1),
- count_of_extmarks_for_client(diagnostic_bufnr, 2),
- } end )
- return diagnostic_count
- ]])
-
- end)
- end)
-
- describe('get_next_diagnostic_pos', function()
- it('can find the next pos with only one client', function()
- eq({1, 1}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- return vim.lsp.diagnostic.get_next_pos()
- ]])
- end)
-
- it('can find next pos with two errors', function()
- eq({4, 4}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 4, 4, 4, 4),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.lsp.diagnostic.get_next_pos { client_id = 1 }
- ]])
- end)
-
- it('can cycle when position is past error', function()
- eq({1, 1}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.lsp.diagnostic.get_next_pos { client_id = 1 }
- ]])
- end)
-
- it('will not cycle when wrap is off', function()
- eq(false, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.lsp.diagnostic.get_next_pos { client_id = 1, wrap = false }
- ]])
- end)
-
- it('can cycle even from the last line', function()
- eq({4, 4}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #2', 4, 4, 4, 4),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1})
- return vim.lsp.diagnostic.get_prev_pos { client_id = 1 }
- ]])
- end)
- end)
-
- describe('get_prev_diagnostic_pos', function()
- it('can find the prev pos with only one client', function()
- eq({1, 1}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.lsp.diagnostic.get_prev_pos()
- ]])
- end)
-
- it('can find prev pos with two errors', function()
- eq({1, 1}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #1', 1, 1, 1, 1),
- make_error('Diagnostic #2', 4, 4, 4, 4),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.lsp.diagnostic.get_prev_pos { client_id = 1 }
- ]])
- end)
-
- it('can cycle when position is past error', function()
- eq({4, 4}, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #2', 4, 4, 4, 4),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.lsp.diagnostic.get_prev_pos { client_id = 1 }
- ]])
- end)
-
- it('respects wrap parameter', function()
- eq(false, exec_lua [[
- vim.lsp.diagnostic.save(
- {
- make_error('Diagnostic #2', 4, 4, 4, 4),
- }, diagnostic_bufnr, 1
- )
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {3, 1})
- return vim.lsp.diagnostic.get_prev_pos { client_id = 1, wrap = false}
- ]])
- end)
- end)
- end)
-
it('maintains LSP information when translating diagnostics', function()
local result = exec_lua [[
local diagnostics = {
@@ -442,7 +102,7 @@ describe('vim.lsp.diagnostic', function()
vim.lsp.diagnostic.on_publish_diagnostics(nil, {
uri = fake_uri,
diagnostics = diagnostics,
- }, {client_id=1})
+ }, {client_id=client_id})
return {
vim.diagnostic.get(diagnostic_bufnr, {lnum=1})[1],
@@ -456,246 +116,7 @@ describe('vim.lsp.diagnostic', function()
end)
end)
- describe("vim.lsp.diagnostic.get_line_diagnostics", function()
- it('should return an empty table when no diagnostics are present', function()
- eq({}, exec_lua [[return vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)]])
- end)
-
- it('should return all diagnostics when no severity is supplied', function()
- eq(2, exec_lua [[
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 1, 1, 2, 5),
- make_error("Error On Other Line", 2, 1, 1, 5),
- }
- }, {client_id=1})
-
- return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)
- ]])
- end)
-
- it('should return only requested diagnostics when severity_limit is supplied', function()
- eq(2, exec_lua [[
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error("Error 1", 1, 1, 1, 5),
- make_warning("Warning on Server 1", 1, 1, 2, 5),
- make_information("Ignored information", 1, 1, 2, 5),
- make_error("Error On Other Line", 2, 1, 1, 5),
- }
- }, {client_id=1})
-
- return #vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1, { severity_limit = "Warning" })
- ]])
- end)
- end)
-
describe("vim.lsp.diagnostic.on_publish_diagnostics", function()
- it('can use functions for config values', function()
- exec_lua [[
- vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- virtual_text = function() return true end,
- })(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Delayed Diagnostic', 4, 4, 4, 4),
- }
- }, {client_id=1}
- )
- ]]
-
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
-
- -- Now, don't enable virtual text.
- -- We should have one less extmark displayed.
- exec_lua [[
- vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- virtual_text = function() return false end,
- })(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Delayed Diagnostic', 4, 4, 4, 4),
- }
- }, {client_id=1}
- )
- ]]
-
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(1, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
- end)
-
- it('can perform updates after insert_leave', function()
- exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
-
- -- Save the diagnostics
- exec_lua [[
- vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- update_in_insert = false,
- })(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Delayed Diagnostic', 4, 4, 4, 4),
- }
- }, {client_id=1}
- )
- ]]
-
- -- No diagnostics displayed yet.
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
-
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
-
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
- end)
-
- it('does not perform updates when not needed', function()
- exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
-
- -- Save the diagnostics
- exec_lua [[
- PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- update_in_insert = false,
- virtual_text = true,
- })
-
- -- Count how many times we call display.
- SetVirtualTextOriginal = vim.diagnostic._set_virtual_text
-
- DisplayCount = 0
- vim.diagnostic._set_virtual_text = function(...)
- DisplayCount = DisplayCount + 1
- return SetVirtualTextOriginal(...)
- end
-
- PublishDiagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Delayed Diagnostic', 4, 4, 4, 4),
- }
- }, {client_id=1}
- )
- ]]
-
- -- No diagnostics displayed yet.
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
- eq(0, exec_lua [[return DisplayCount]])
-
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
-
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
- eq(1, exec_lua [[return DisplayCount]])
-
- -- Go in and out of insert mode one more time.
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
-
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
-
- -- Should not have set the virtual text again.
- eq(1, exec_lua [[return DisplayCount]])
- end)
-
- it('never sets virtual text, in combination with insert leave', function()
- exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
-
- -- Save the diagnostics
- exec_lua [[
- PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- update_in_insert = false,
- virtual_text = false,
- })
-
- -- Count how many times we call display.
- SetVirtualTextOriginal = vim.lsp.diagnostic.set_virtual_text
-
- DisplayCount = 0
- vim.lsp.diagnostic.set_virtual_text = function(...)
- DisplayCount = DisplayCount + 1
- return SetVirtualTextOriginal(...)
- end
-
- PublishDiagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Delayed Diagnostic', 4, 4, 4, 4),
- }
- }, {client_id=1}
- )
- ]]
-
- -- No diagnostics displayed yet.
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(0, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
- eq(0, exec_lua [[return DisplayCount]])
-
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
-
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(1, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
- eq(0, exec_lua [[return DisplayCount]])
-
- -- Go in and out of insert mode one more time.
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
-
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
-
- -- Should not have set the virtual text still.
- eq(0, exec_lua [[return DisplayCount]])
- end)
-
- it('can perform updates while in insert mode, if desired', function()
- exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
-
- -- Save the diagnostics
- exec_lua [[
- vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- update_in_insert = true,
- })(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Delayed Diagnostic', 4, 4, 4, 4),
- }
- }, {client_id=1}
- )
- ]]
-
- -- Diagnostics are displayed, because the user wanted them that way!
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
-
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
-
- eq(1, exec_lua [[return vim.lsp.diagnostic.get_count(diagnostic_bufnr, "Error", 1)]])
- eq(2, exec_lua [[return count_of_extmarks_for_client(diagnostic_bufnr, 1)]])
- end)
-
it('allows configuring the virtual text via vim.lsp.with', function()
local expected_spacing = 10
local extmarks = exec_lua([[
@@ -710,16 +131,10 @@ describe('vim.lsp.diagnostic', function()
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, {client_id=1}
+ }, {client_id=client_id}
)
- return vim.api.nvim_buf_get_extmarks(
- diagnostic_bufnr,
- vim.lsp.diagnostic.get_namespace(1),
- 0,
- -1,
- { details = true }
- )
+ return get_extmarks(diagnostic_bufnr, client_id)
]], expected_spacing)
local virt_text = extmarks[1][4].virt_text
@@ -728,7 +143,6 @@ describe('vim.lsp.diagnostic', function()
eq(expected_spacing, #spacing)
end)
-
it('allows configuring the virtual text via vim.lsp.with using a function', function()
local expected_spacing = 10
local extmarks = exec_lua([[
@@ -747,16 +161,10 @@ describe('vim.lsp.diagnostic', function()
diagnostics = {
make_error('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, {client_id=1}
+ }, {client_id=client_id}
)
- return vim.api.nvim_buf_get_extmarks(
- diagnostic_bufnr,
- vim.lsp.diagnostic.get_namespace(1),
- 0,
- -1,
- { details = true }
- )
+ return get_extmarks(diagnostic_bufnr, client_id)
]], expected_spacing)
local virt_text = extmarks[1][4].virt_text
@@ -780,10 +188,10 @@ describe('vim.lsp.diagnostic', function()
diagnostics = {
make_warning('Delayed Diagnostic', 4, 4, 4, 4),
}
- }, {client_id=1}
+ }, {client_id=client_id}
)
- return count_of_extmarks_for_client(diagnostic_bufnr, 1)
+ return #get_extmarks(diagnostic_bufnr, client_id)
]], severity_limit)
end
@@ -799,16 +207,6 @@ describe('vim.lsp.diagnostic', function()
local line = "All 💼 and no 🎉 makes Jack a dull 👦"
local result = exec_lua([[
local line = ...
- local client_id = vim.lsp.start_client {
- cmd_env = {
- NVIM_LUA_NOTRACK = "1";
- };
- cmd = {
- vim.v.progpath, '-es', '-u', 'NONE', '--headless'
- };
- offset_encoding = "utf-16";
- }
-
vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, {line})
vim.lsp.diagnostic.on_publish_diagnostics(nil, {
@@ -829,145 +227,4 @@ describe('vim.lsp.diagnostic', function()
eq(exec_lua([[return vim.str_byteindex(..., 8, true)]], line), result[1].end_col)
end)
end)
-
- describe('lsp.util.show_line_diagnostics', function()
- it('creates floating window and returns popup bufnr and winnr if current line contains diagnostics', function()
- -- Two lines:
- -- Diagnostic:
- -- 1. <msg>
- eq(2, exec_lua [[
- local buffer = vim.api.nvim_create_buf(false, true)
- vim.api.nvim_buf_set_lines(buffer, 0, -1, false, {
- "testing";
- "123";
- })
- local diagnostics = {
- {
- range = {
- start = { line = 0; character = 1; };
- ["end"] = { line = 0; character = 3; };
- };
- severity = vim.lsp.protocol.DiagnosticSeverity.Error;
- message = "Syntax error";
- },
- }
- vim.api.nvim_win_set_buf(0, buffer)
- vim.lsp.diagnostic.save(diagnostics, buffer, 1)
- local popup_bufnr, winnr = vim.lsp.diagnostic.show_line_diagnostics()
- return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
- ]])
- end)
-
- it('creates floating window and returns popup bufnr and winnr without header, if requested', function()
- -- One line (since no header):
- -- 1. <msg>
- eq(1, exec_lua [[
- local buffer = vim.api.nvim_create_buf(false, true)
- vim.api.nvim_buf_set_lines(buffer, 0, -1, false, {
- "testing";
- "123";
- })
- local diagnostics = {
- {
- range = {
- start = { line = 0; character = 1; };
- ["end"] = { line = 0; character = 3; };
- };
- severity = vim.lsp.protocol.DiagnosticSeverity.Error;
- message = "Syntax error";
- },
- }
- vim.api.nvim_win_set_buf(0, buffer)
- vim.lsp.diagnostic.save(diagnostics, buffer, 1)
- local popup_bufnr, winnr = vim.lsp.diagnostic.show_line_diagnostics { show_header = false }
- return #vim.api.nvim_buf_get_lines(popup_bufnr, 0, -1, false)
- ]])
- end)
- end)
-
- describe('set_signs', function()
- -- TODO(tjdevries): Find out why signs are not displayed when set from Lua...??
- pending('sets signs by default', function()
- exec_lua [[
- PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
- update_in_insert = true,
- signs = true,
- })
-
- local diagnostics = {
- make_error('Delayed Diagnostic', 1, 1, 1, 2),
- make_error('Delayed Diagnostic', 3, 3, 3, 3),
- }
-
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = fake_uri,
- diagnostics = diagnostics
- }, {client_id=1}
- )
-
- vim.lsp.diagnostic.set_signs(diagnostics, diagnostic_bufnr, 1)
- -- return vim.fn.sign_getplaced()
- ]]
-
- nvim("input", "o")
- nvim("input", "<esc>")
-
- -- TODO(tjdevries): Find a way to get the signs to display in the test...
- eq(nil, exec_lua [[
- return im.fn.sign_getplaced()[1].signs
- ]])
- end)
- end)
-
- describe('set_loclist()', function()
- it('sets diagnostics in lnum order', function()
- local loc_list = exec_lua [[
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
-
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Farther Diagnostic', 4, 4, 4, 4),
- make_error('Lower Diagnostic', 1, 1, 1, 1),
- }
- }, {client_id=1}
- )
-
- vim.lsp.diagnostic.set_loclist()
-
- return vim.fn.getloclist(0)
- ]]
-
- assert(loc_list[1].lnum < loc_list[2].lnum)
- end)
-
- it('sets diagnostics in lnum order, regardless of client', function()
- local loc_list = exec_lua [[
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
-
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- make_error('Lower Diagnostic', 1, 1, 1, 1),
- }
- }, {client_id=1}
- )
-
- vim.lsp.diagnostic.on_publish_diagnostics(nil, {
- uri = fake_uri,
- diagnostics = {
- make_warning('Farther Diagnostic', 4, 4, 4, 4),
- }
- }, {client_id=2}
- )
-
- vim.lsp.diagnostic.set_loclist()
-
- return vim.fn.getloclist(0)
- ]]
-
- assert(loc_list[1].lnum < loc_list[2].lnum)
- end)
- end)
end)
diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua
new file mode 100644
index 0000000000..fe4f8f3593
--- /dev/null
+++ b/test/functional/plugin/lsp/incremental_sync_spec.lua
@@ -0,0 +1,266 @@
+-- Test suite for testing interactions with the incremental sync algorithms powering the LSP client
+local helpers = require('test.functional.helpers')(after_each)
+
+local meths = helpers.meths
+local clear = helpers.clear
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local feed = helpers.feed
+
+before_each(function ()
+ clear()
+ exec_lua [[
+ local evname = ...
+ local sync = require('vim.lsp.sync')
+ local events = {}
+ local buffer_cache = {}
+
+ -- local format_line_ending = {
+ -- ["unix"] = '\n',
+ -- ["dos"] = '\r\n',
+ -- ["mac"] = '\r',
+ -- }
+
+ -- local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')]
+
+
+ function test_register(bufnr, id, offset_encoding, line_ending)
+ local curr_lines
+ local prev_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
+
+ local function callback(_, bufnr, changedtick, firstline, lastline, new_lastline)
+ if test_unreg == id then
+ return true
+ end
+
+ local curr_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
+ local incremental_change = sync.compute_diff(
+ prev_lines, curr_lines, firstline, lastline, new_lastline, offset_encoding, line_ending)
+
+ table.insert(events, incremental_change)
+ prev_lines = curr_lines
+ end
+ local opts = {on_lines=callback, on_detach=callback, on_reload=callback}
+ vim.api.nvim_buf_attach(bufnr, false, opts)
+ end
+
+ function get_events()
+ local ret_events = events
+ events = {}
+ return ret_events
+ end
+ ]]
+end)
+
+local function test_edit(prev_buffer, edit_operations, expected_text_changes, offset_encoding, line_ending)
+ offset_encoding = offset_encoding or 'utf-16'
+ line_ending = line_ending or '\n'
+
+ meths.buf_set_lines(0, 0, -1, true, prev_buffer)
+ exec_lua("return test_register(...)", 0, "test1", offset_encoding, line_ending)
+
+ for _, edit in ipairs(edit_operations) do
+ feed(edit)
+ end
+ eq(expected_text_changes, exec_lua("return get_events(...)" ))
+ exec_lua("test_unreg = 'test1'")
+
+end
+describe('incremental synchronization', function()
+ describe('single line edit', function()
+ it('inserting a character in an empty buffer', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 0,
+ line = 0
+ },
+ ['end'] = {
+ character = 0,
+ line = 0
+ }
+ },
+ rangeLength = 0,
+ text = 'a'
+ }
+ }
+ test_edit({""}, {"ia"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ it('inserting a character in the middle of a the first line', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 1,
+ line = 0
+ },
+ ['end'] = {
+ character = 1,
+ line = 0
+ }
+ },
+ rangeLength = 0,
+ text = 'a'
+ }
+ }
+ test_edit({"ab"}, {"lia"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ it('deleting the only character in a buffer', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 0,
+ line = 0
+ },
+ ['end'] = {
+ character = 1,
+ line = 0
+ }
+ },
+ rangeLength = 1,
+ text = ''
+ }
+ }
+ test_edit({"a"}, {"x"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ it('deleting a character in the middle of the line', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 1,
+ line = 0
+ },
+ ['end'] = {
+ character = 2,
+ line = 0
+ }
+ },
+ rangeLength = 1,
+ text = ''
+ }
+ }
+ test_edit({"abc"}, {"lx"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ it('replacing a character', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 0,
+ line = 0
+ },
+ ['end'] = {
+ character = 1,
+ line = 0
+ }
+ },
+ rangeLength = 1,
+ text = 'b'
+ }
+ }
+ test_edit({"a"}, {"rb"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ describe('multi-byte edits', function()
+ it('join and undo', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 11,
+ line = 0
+ },
+ ['end'] = {
+ character = 11,
+ line = 0
+ }
+ },
+ rangeLength = 0,
+ text = ' test3'
+ },{
+ range = {
+ ['start'] = {
+ character = 0,
+ line = 1
+ },
+ ['end'] = {
+ character = 0,
+ line = 2
+ }
+ },
+ rangeLength = 6,
+ text = ''
+ },{
+ range = {
+ ['start'] = {
+ character = 11,
+ line = 0
+ },
+ ['end'] = {
+ character = 17,
+ line = 0
+ }
+ },
+ rangeLength = 6,
+ text = '\ntest3'
+ },
+ }
+ test_edit({"test1 test2", "test3"}, {"J", "u"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ end)
+ end)
+ describe('multi-byte edits', function()
+ it('deleting a multibyte character', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 0,
+ line = 0
+ },
+ ['end'] = {
+ character = 2,
+ line = 0
+ }
+ },
+ rangeLength = 2,
+ text = ''
+ }
+ }
+ test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ it('deleting a multiple lines containing multibyte characters', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 0,
+ line = 1
+ },
+ ['end'] = {
+ character = 0,
+ line = 3
+ }
+ },
+ --utf 16 len of 🔥 is 2
+ rangeLength = 8,
+ text = ''
+ }
+ }
+ test_edit({"a🔥", "b🔥", "c🔥", "d🔥"}, {"j2dd"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ end)
+end)
+
+-- TODO(mjlbach): Add additional tests
+-- deleting single lone line
+-- 2 lines -> 2 line delete -> undo -> redo
+-- describe('future tests', function()
+-- -- This test is currently wrong, ask bjorn why dd on an empty line triggers on_lines
+-- it('deleting an empty line', function()
+-- local expected_text_changes = {{ }}
+-- test_edit({""}, {"ggdd"}, expected_text_changes, 'utf-16', '\n')
+-- end)
+-- end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index ce50abb50d..228fc06e9b 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -3,9 +3,11 @@ local helpers = require('test.functional.helpers')(after_each)
local assert_log = helpers.assert_log
local clear = helpers.clear
local buf_lines = helpers.buf_lines
+local command = helpers.command
local dedent = helpers.dedent
local exec_lua = helpers.exec_lua
local eq = helpers.eq
+local eval = helpers.eval
local matches = helpers.matches
local pcall_err = helpers.pcall_err
local pesc = helpers.pesc
@@ -272,7 +274,7 @@ describe('LSP', function()
return
end
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="shutdown", bufnr=1, client_id=1}};
{NIL, {}, {method="test", client_id=1}};
}
test_rpc_server {
@@ -486,7 +488,7 @@ describe('LSP', function()
it('should forward ContentModified to callback', function()
local expected_handlers = {
{NIL, {}, {method="finish", client_id=1}};
- {{code = -32801}, NIL, {method = "error_code_test", client_id=1}};
+ {{code = -32801}, NIL, {method = "error_code_test", bufnr=1, client_id=1}};
}
local client
test_rpc_server {
@@ -509,6 +511,140 @@ describe('LSP', function()
}
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}};
+ }
+ local client
+ test_rpc_server {
+ test_name = "check_pending_request_tracked";
+ on_init = function(_client)
+ client = _client
+ 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;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ eq(0, #expected_handlers, "did not call expected handler")
+ end;
+ on_handler = function(err, _, ctx)
+ eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ if ctx.method == 'slow_request' then
+ local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
+ eq(NIL, request)
+ client.notify("finish")
+ end
+ if ctx.method == 'finish' then client.stop() end
+ end;
+ }
+ end)
+
+ it('should track cancel requests to the language server', function()
+ local expected_handlers = {
+ {NIL, {}, {method="finish", client_id=1}};
+ }
+ local client
+ test_rpc_server {
+ test_name = "check_cancel_request_tracked";
+ on_init = function(_client)
+ client = _client
+ 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;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ eq(0, #expected_handlers, "did not call expected handler")
+ end;
+ on_handler = function(err, _, ctx)
+ 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;
+ }
+ 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}};
+ }
+ local client
+ test_rpc_server {
+ test_name = "check_tracked_requests_cleared";
+ on_init = function(_client)
+ client = _client
+ client.request("slow_request")
+ local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
+ 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;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ eq(0, #expected_handlers, "did not call expected handler")
+ end;
+ on_handler = function(err, _, ctx)
+ eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ if ctx.method == 'slow_request' then
+ local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
+ eq(NIL, request)
+ client.notify("finish")
+ 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}};
+ }
+ local client
+ test_rpc_server {
+ test_name = "check_tracked_requests_cleared";
+ on_init = function(_client)
+ command('let g:requests = 0')
+ command('autocmd User LspRequest let g:requests+=1')
+ client = _client
+ client.request("slow_request")
+ eq(1, eval('g:requests'))
+ client.cancel_request(2)
+ eq(2, eval('g:requests'))
+ client.notify("release")
+ end;
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ eq(0, #expected_handlers, "did not call expected handler")
+ eq(3, eval('g:requests'))
+ end;
+ on_handler = function(err, _, ctx)
+ eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ if ctx.method == 'slow_request' then
+ client.notify("finish")
+ end
+ if ctx.method == 'finish' then client.stop() end
+ end;
+ }
+ end)
+
it('should not send didOpen if the buffer closes before init', function()
local expected_handlers = {
{NIL, {}, {method="shutdown", client_id=1}};
@@ -790,7 +926,7 @@ describe('LSP', function()
-- 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", client_id=1}};
+ {NIL, {}, {method="shutdown", bufnr=1, client_id=1}};
{NIL, {}, {method="finish", client_id=1}};
{NIL, {}, {method="start", client_id=1}};
}
@@ -1017,15 +1153,9 @@ describe('LSP', function()
end)
it('should invalid cmd argument', function()
- eq(dedent([[
- Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim
- stack traceback:
- .../lsp.lua:0: in function <.../lsp.lua:0>]]),
+ eq('Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim',
pcall_err(_cmd_parts, 'nvim'))
- eq(dedent([[
- Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number
- stack traceback:
- .../lsp.lua:0: in function <.../lsp.lua:0>]]),
+ eq('Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number',
pcall_err(_cmd_parts, {'nvim', 1}))
end)
end)
@@ -1605,6 +1735,7 @@ describe('LSP', function()
-- 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)
@@ -2305,9 +2436,9 @@ describe('LSP', function()
local bufnr = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
vim.lsp._stubs = {}
- vim.fn.input = function(prompt, text)
- vim.lsp._stubs.input_prompt = prompt
- vim.lsp._stubs.input_text = text
+ vim.fn.input = function(opts, on_confirm)
+ vim.lsp._stubs.input_prompt = opts.prompt
+ vim.lsp._stubs.input_text = opts.default
return 'renameto' -- expect this value in fake lsp
end
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'', 'this is line two'})
@@ -2395,4 +2526,57 @@ describe('LSP', function()
)
end)
end)
+ describe('vim.lsp.codelens', function()
+ it('uses client commands', function()
+ local client
+ local expected_handlers = {
+ {NIL, {}, {method="shutdown", client_id=1}};
+ {NIL, {}, {method="start", client_id=1}};
+ }
+ test_rpc_server {
+ test_name = 'clientside_commands',
+ on_init = function(client_)
+ client = client_
+ end,
+ on_setup = function()
+ end,
+ on_exit = function(code, signal)
+ eq(0, code, "exit code", fake_lsp_logfile)
+ eq(0, signal, "exit signal", fake_lsp_logfile)
+ end,
+ on_handler = function(err, result, ctx)
+ eq(table.remove(expected_handlers), {err, result, ctx})
+ if ctx.method == 'start' then
+ local fake_uri = "file:///fake/uri"
+ local cmd = exec_lua([[
+ fake_uri = ...
+ local bufnr = vim.uri_to_bufnr(fake_uri)
+ vim.fn.bufload(bufnr)
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'One line'})
+ local lenses = {
+ {
+ range = {
+ start = { line = 0, character = 0, },
+ ['end'] = { line = 0, character = 8 }
+ },
+ command = { title = 'Lens1', command = 'Dummy' }
+ },
+ }
+ vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr})
+ local cmd_called = nil
+ vim.lsp.commands['Dummy'] = function(command)
+ cmd_called = command
+ end
+ 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()
+ end
+ end
+ }
+ end)
+ end)
end)
diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua
new file mode 100644
index 0000000000..7d37dcccc8
--- /dev/null
+++ b/test/functional/terminal/channel_spec.lua
@@ -0,0 +1,49 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local eq = helpers.eq
+local command = helpers.command
+local exc_exec = helpers.exc_exec
+local feed = helpers.feed
+local sleep = helpers.sleep
+local poke_eventloop = helpers.poke_eventloop
+
+describe('associated channel is closed and later freed for terminal', function()
+ before_each(clear)
+
+ it('opened by nvim_open_term() and deleted by :bdelete!', function()
+ command([[let id = nvim_open_term(0, {})]])
+ -- channel hasn't been freed yet
+ eq("Vim(call):Can't send data to closed stream", exc_exec([[bdelete! | call chansend(id, 'test')]]))
+ -- process free_channel_event
+ poke_eventloop()
+ -- channel has been freed
+ eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]]))
+ end)
+
+ it('opened by termopen(), exited, and deleted by pressing a key', function()
+ command([[let id = termopen('echo')]])
+ sleep(500)
+ -- process has exited
+ eq("Vim(call):Can't send data to closed stream", exc_exec([[call chansend(id, 'test')]]))
+ -- delete terminal
+ feed('i<CR>')
+ -- process term_delayed_free and free_channel_event
+ poke_eventloop()
+ -- channel has been freed
+ eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]]))
+ end)
+
+ -- This indirectly covers #16264
+ it('opened by termopen(), exited, and deleted by :bdelete', function()
+ command([[let id = termopen('echo')]])
+ sleep(500)
+ -- process has exited
+ eq("Vim(call):Can't send data to closed stream", exc_exec([[call chansend(id, 'test')]]))
+ -- channel hasn't been freed yet
+ eq("Vim(call):Can't send data to closed stream", exc_exec([[bdelete | call chansend(id, 'test')]]))
+ -- process term_delayed_free and free_channel_event
+ poke_eventloop()
+ -- channel has been freed
+ eq("Vim(call):E900: Invalid channel id", exc_exec([[call chansend(id, 'test')]]))
+ end)
+end)
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index f7520b14d4..6b9586b4de 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -494,6 +494,8 @@ describe('TUI', function()
it('paste: recovers from vim.paste() failure', function()
child_session:request('nvim_exec_lua', [[
_G.save_paste_fn = vim.paste
+ -- Stack traces for this test are non-deterministic, so disable them
+ _G.debug.traceback = function(msg) return msg end
vim.paste = function(lines, phase) error("fake fail") end
]], {})
-- Prepare something for dot-repeat/redo.
@@ -514,7 +516,7 @@ describe('TUI', function()
foo |
|
{5: }|
- {8:paste: Error executing lua: [string "<nvim>"]:2: f}|
+ {8:paste: Error executing lua: [string "<nvim>"]:4: f}|
{8:ake fail} |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
@@ -579,12 +581,16 @@ describe('TUI', function()
it("paste: 'nomodifiable' buffer", function()
child_session:request('nvim_command', 'set nomodifiable')
+ child_session:request('nvim_exec_lua', [[
+ -- Stack traces for this test are non-deterministic, so disable them
+ _G.debug.traceback = function(msg) return msg end
+ ]], {})
feed_data('\027[200~fail 1\nfail 2\n\027[201~')
screen:expect{grid=[[
|
{4:~ }|
{5: }|
- {MATCH:paste: Error executing lua: vim.lua:%d+: Vim:E21: }|
+ {8:paste: Error executing lua: vim.lua:243: Vim:E21: }|
{8:Cannot make changes, 'modifiable' is off} |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
@@ -671,8 +677,8 @@ describe('TUI', function()
item 2997 |
item 2998 |
item 2999 |
- item 3000 en{1:d}d |
- {5:[No Name] [+] 5999,13 Bot}|
+ item 3000 en{1:d} |
+ {5:[No Name] [+] 3000,13 Bot}|
|
{3:-- TERMINAL --} |
]])
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 8074f91215..dce6384b9b 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -901,15 +901,15 @@ if (h->n_buckets < new_n_buckets) { // expand
screen:expect{grid=[[
if (h->n_buckets < new_n_buckets) { // expand |
khkey_t *new_keys = (khkey_t *) |
+ {1:>> }{2:krealloc}: change the size of an allocation |
{3:krealloc}((void *)h->keys, new_n_buckets * sizeof(k|
hkey_t)); |
h->keys = new_keys; |
if (kh_is_map && val_size) { |
- char *new_vals = {3:krealloc}( h->vals_buf, new_n_|
- buck^ets * val_size); |
+ ^char *new_vals = {3:krealloc}( h->vals_buf, new_n_|
+ buckets * val_size); |
{5:^^ REVIEW:}{6: new_vals variable seems unneccesary?} |
h->vals_buf = new_vals; |
- } |
|
]]}
@@ -992,7 +992,7 @@ if (h->n_buckets < new_n_buckets) { // expand
]]}
end)
- it('works with text et the end of the buffer', function()
+ it('works with text at the end of the buffer', function()
insert(example_text)
feed 'G'
@@ -1213,7 +1213,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- meths.buf_set_extmark(0, ns, 2, 0, {
+ local markid = meths.buf_set_extmark(0, ns, 2, 0, {
virt_lines={
{{"Some special", "Special"}};
{{"remark about codes", "Comment"}};
@@ -1241,6 +1241,7 @@ if (h->n_buckets < new_n_buckets) { // expand
{{"remark about codes", "Comment"}};
};
virt_lines_leftcol=true;
+ id=markid;
})
screen:expect{grid=[[
{8: }{9: 1 }^if (h->n_buckets < new_n_buckets) { // expan|
diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua
index df750a1a68..13949b0756 100644
--- a/test/functional/ui/diff_spec.lua
+++ b/test/functional/ui/diff_spec.lua
@@ -1196,4 +1196,27 @@ it('Align the filler lines when changing text in diff mode', function()
{8:[No Name] [+] }{3:[No Name] [+] }|
|
]]}
+ feed('<C-W>lay<Esc>')
+ screen:expect{grid=[[
+ {1: }{2:-----------------}{3:│}{1: }{4:6 }|
+ {1: }{2:-----------------}{3:│}{1: }{4:7 }|
+ {1: }{2:-----------------}{3:│}{1: }{4:8 }|
+ {1: }9 {3:│}{1: }9 |
+ {1: }10 {3:│}{1: }10 |
+ {1: }11 {3:│}{1: }11 |
+ {1: }12 {3:│}{1: }12 |
+ {1: }13 {3:│}{1: }13 |
+ {1: }14 {3:│}{1: }14 |
+ {1: }{5:15}{6:x}{5: }{3:│}{1: }{5:15}{6:^y}{5: }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {7:~ }{3:│}{7:~ }|
+ {3:[No Name] [+] }{8:[No Name] [+] }|
+ |
+ ]]}
end)
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 6c2c4b398a..5f29261b17 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -1,11 +1,13 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local global_helpers = require('test.helpers')
local os = require('os')
local clear, feed = helpers.clear, helpers.feed
local assert_alive = helpers.assert_alive
local command, feed_command = helpers.command, helpers.feed_command
local eval = helpers.eval
local eq = helpers.eq
+local neq = helpers.neq
local exec_lua = helpers.exec_lua
local insert = helpers.insert
local meths = helpers.meths
@@ -13,6 +15,7 @@ local curbufmeths = helpers.curbufmeths
local funcs = helpers.funcs
local run = helpers.run
local pcall_err = helpers.pcall_err
+local tbl_contains = global_helpers.tbl_contains
describe('float window', function()
before_each(function()
@@ -294,6 +297,125 @@ describe('float window', function()
eq(12, pos[2])
end)
+ it('is not operated on by windo when non-focusable #15374', function()
+ command([[
+ let winids = []
+ windo call add(winids, win_getid())
+ ]])
+ local windo_count_before = eval('len(winids)')
+ local winid = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local opts = {
+ relative = 'editor',
+ focusable = false,
+ height = 5,
+ width = 5,
+ col = 5,
+ row = 5,
+ }
+ return vim.api.nvim_open_win(bufnr, false, opts)
+ ]])
+ command([[
+ let winids = []
+ windo call add(winids, win_getid())
+ ]])
+ local windo_count_after = eval('len(winids)')
+ eq(windo_count_before, windo_count_after)
+ eq(false, tbl_contains(eval('winids'), winid))
+ end)
+
+ it('is operated on by windo when focusable', function()
+ command([[
+ let winids = []
+ windo call add(winids, win_getid())
+ ]])
+ local windo_count_before = eval('len(winids)')
+ local winid = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local opts = {
+ relative = 'editor',
+ focusable = true,
+ height = 5,
+ width = 5,
+ col = 5,
+ row = 5,
+ }
+ return vim.api.nvim_open_win(bufnr, false, opts)
+ ]])
+ command([[
+ let winids = []
+ windo call add(winids, win_getid())
+ ]])
+ local windo_count_after = eval('len(winids)')
+ eq(windo_count_before + 1, windo_count_after)
+ eq(true, tbl_contains(eval('winids'), winid))
+ end)
+
+ it('is not active after windo when non-focusable #15374', function()
+ local winid = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local opts = {
+ relative = 'editor',
+ focusable = false,
+ height = 5,
+ width = 5,
+ col = 5,
+ row = 5,
+ }
+ return vim.api.nvim_open_win(bufnr, false, opts)
+ ]])
+ command('windo echo')
+ neq(eval('win_getid()'), winid)
+ end)
+
+ it('is active after windo when focusable', function()
+ local winid = exec_lua([[
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local opts = {
+ relative = 'editor',
+ focusable = true,
+ height = 5,
+ width = 5,
+ col = 5,
+ row = 5,
+ }
+ return vim.api.nvim_open_win(bufnr, false, opts)
+ ]])
+ command('windo echo')
+ eq(eval('win_getid()'), winid)
+ end)
+
+ it('supports windo with focusable and non-focusable floats', function()
+ local winids = exec_lua([[
+ local result = {vim.api.nvim_get_current_win()}
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local opts = {
+ relative = 'editor',
+ focusable = false,
+ height = 5,
+ width = 5,
+ col = 5,
+ row = 5,
+ }
+ vim.api.nvim_open_win(bufnr, false, opts)
+ opts.focusable = true
+ table.insert(result, vim.api.nvim_open_win(bufnr, false, opts))
+ opts.focusable = false
+ vim.api.nvim_open_win(bufnr, false, opts)
+ opts.focusable = true
+ table.insert(result, vim.api.nvim_open_win(bufnr, false, opts))
+ opts.focusable = false
+ vim.api.nvim_open_win(bufnr, false, opts)
+ return result
+ ]])
+ table.sort(winids)
+ command([[
+ let winids = []
+ windo call add(winids, win_getid())
+ call sort(winids)
+ ]])
+ eq(winids, eval('winids'))
+ end)
local function with_ext_multigrid(multigrid)
local screen
@@ -1194,6 +1316,49 @@ describe('float window', function()
]]}
end
+ meths.win_set_config(win, {border={"", "_", "", "", "", "-", "", ""}})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [2:----------------------------------------]|
+ [3:----------------------------------------]|
+ ## grid 2
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ ## grid 3
+ |
+ ## grid 5
+ {5:_________}|
+ {1: halloj! }|
+ {1: BORDAA }|
+ {5:---------}|
+ ]], float_pos={
+ [5] = { { id = 1002 }, "NW", 1, 2, 5, true }
+ }, win_viewport={
+ [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1};
+ [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2};
+ }}
+ else
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }{5:_________}{0: }|
+ {0:~ }{1: halloj! }{0: }|
+ {0:~ }{1: BORDAA }{0: }|
+ {0:~ }{5:---------}{0: }|
+ |
+ ]]}
+ end
+
insert [[
neeed some dummy
background text
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index c238898244..f038348253 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -750,8 +750,13 @@ describe('ui/ext_messages', function()
{1:~ }|
{1:~ }|
]], messages={{
- content = {{'E5108: Error executing lua [string ":lua"]:1: such\nmultiline\nerror', 2}},
- kind = "lua_error"
+ content = {{[[E5108: Error executing lua [string ":lua"]:1: such
+multiline
+error
+stack traceback:
+ [C]: in function 'error'
+ [string ":lua"]:1: in main chunk]], 2}},
+ kind = "lua_error",
}}}
end)
@@ -1048,12 +1053,12 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
-- edge case: just covers statusline
feed(':set colorcolumn=5 | lua error("x\\n\\nx")<cr>')
screen:expect{grid=[[
- |
- {1:~ }|
- {3: }|
{2:E5108: Error executing lua [string ":lua"]:1: x} |
|
{2:x} |
+ {2:stack traceback:} |
+ {2: [C]: in function 'error'} |
+ {2: [string ":lua"]:1: in main chunk} |
{4:Press ENTER or type command to continue}^ |
]]}
@@ -1071,24 +1076,24 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
-- edge case: just covers lowest window line
feed(':set colorcolumn=5 | lua error("x\\n\\n\\nx")<cr>')
screen:expect{grid=[[
- |
- {3: }|
{2:E5108: Error executing lua [string ":lua"]:1: x} |
|
|
{2:x} |
- {4:Press ENTER or type command to continue}^ |
+ {2:stack traceback:} |
+ {2: [C]: in function 'error'} |
+ {4:-- More --}^ |
]]}
feed('<cr>')
screen:expect{grid=[[
|
- {1:~ }|
- {8:[No Name] }|
- ^ {9: } |
- {1:~ }|
- {3:[No Name] }|
|
+ {2:x} |
+ {2:stack traceback:} |
+ {2: [C]: in function 'error'} |
+ {2: [string ":lua"]:1: in main chunk} |
+ {4:Press ENTER or type command to continue}^ |
]]}
end)
end)
@@ -1360,14 +1365,14 @@ aliquip ex ea commodo consequat.]])
]]}
feed('d')
screen:expect{grid=[[
+ {2:mpor} |
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
{2:Ut enim ad minim veniam, quis nostr}|
{2:ud xercitation} |
{2:ullamco laboris nisi ut} |
{2:aliquip ex ea commodo consequat.} |
- {4:Press ENTER or type command to cont}|
- {4:inue}^ |
+ {4:-- More --}^ |
]]}
feed('u')
screen:expect{grid=[[
@@ -1460,14 +1465,14 @@ aliquip ex ea commodo consequat.]])
]]}
feed('d')
screen:expect{grid=[[
+ {3:mpor}{5: }|
{3:incididunt ut labore et dolore magn}|
{3:a aliqua.}{5: }|
{3:Ut enim ad minim veniam, quis nostr}|
{3:ud xercitation}{5: }|
{3:ullamco laboris nisi ut}{5: }|
{3:aliquip ex ea commodo consequat.}{5: }|
- {6:Press ENTER or type command to cont}|
- {6:inue}{5:^ }|
+ {6:-- More --}{5:^ }|
]]}
feed('u')
screen:expect{grid=[[
@@ -1667,6 +1672,7 @@ aliquip ex ea commodo consequat.]])
-- wrapped at the new screen size.
feed('<cr>')
screen:expect{grid=[[
+ {2:":lua"]:1: Lorem ipsum dolor s}|
{2:et, consectetur} |
{2:adipisicing elit, sed do eiusm}|
{2:mpore} |
@@ -1677,8 +1683,7 @@ aliquip ex ea commodo consequat.]])
{2:ullamco laboris nisi ut} |
{2:aliquip ex ea commodo consequa}|
{2:t.} |
- {4:Press ENTER or type command to}|
- {4: continue}^ |
+ {4:-- More --}^ |
]]}
feed('q')
diff --git a/test/functional/vimscript/executable_spec.lua b/test/functional/vimscript/executable_spec.lua
index 28aefb72e5..048a65188d 100644
--- a/test/functional/vimscript/executable_spec.lua
+++ b/test/functional/vimscript/executable_spec.lua
@@ -18,7 +18,7 @@ describe('executable()', function()
end)
it('fails for invalid values', function()
- for _, input in ipairs({'""', 'v:null', 'v:true', 'v:false', '{}', '[]'}) do
+ for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
eq('Vim(call):E928: String required', exc_exec('call executable('..input..')'))
end
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
@@ -27,6 +27,10 @@ describe('executable()', function()
end
end)
+ it('returns 0 for empty strings', function()
+ eq(0, call('executable', '""'))
+ end)
+
it('returns 0 for non-existent files', function()
eq(0, call('executable', 'no_such_file_exists_209ufq23f'))
end)
diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua
index 08d2c59af8..bbca954511 100644
--- a/test/functional/vimscript/exepath_spec.lua
+++ b/test/functional/vimscript/exepath_spec.lua
@@ -20,9 +20,10 @@ describe('exepath()', function()
end)
it('fails for invalid values', function()
- for _, input in ipairs({'""', 'v:null', 'v:true', 'v:false', '{}', '[]'}) do
+ for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')'))
end
+ eq('Vim(call):E1142: Non-empty string required', exc_exec('call exepath("")'))
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')'))
diff --git a/test/functional/vimscript/has_spec.lua b/test/functional/vimscript/has_spec.lua
index a3af2d1a20..c03fd13e0c 100644
--- a/test/functional/vimscript/has_spec.lua
+++ b/test/functional/vimscript/has_spec.lua
@@ -59,7 +59,12 @@ describe('has()', function()
end)
it('"wsl"', function()
- if 1 == funcs.has('win32') or 1 == funcs.has('mac') then
+ local luv = require('luv')
+ local is_wsl =
+ luv.os_uname()['release']:lower():match('microsoft') and true or false
+ if is_wsl then
+ eq(1, funcs.has('wsl'))
+ else
eq(0, funcs.has('wsl'))
end
end)
diff --git a/test/functional/vimscript/null_spec.lua b/test/functional/vimscript/null_spec.lua
index 7ecbcd2fd6..f23f00bcc5 100644
--- a/test/functional/vimscript/null_spec.lua
+++ b/test/functional/vimscript/null_spec.lua
@@ -161,7 +161,7 @@ describe('NULL', function()
null_test('does not crash :echomsg', 'echomsg S', 0)
null_test('does not crash :execute', 'execute S', 0)
null_expr_test('does not crash execute()', 'execute(S)', 0, '')
- null_expr_test('makes executable() error out', 'executable(S)', 'E928: String required', 0)
+ null_expr_test('does not crash executable()', 'executable(S)', 0, 0)
null_expr_test('makes timer_start() error out', 'timer_start(0, S)', 'E921: Invalid callback argument', -1)
null_expr_test('does not crash filereadable()', 'filereadable(S)', 0, 0)
null_expr_test('does not crash filewritable()', 'filewritable(S)', 0, 0)
diff --git a/test/helpers.lua b/test/helpers.lua
index 9ac3904776..09b113c01d 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -155,12 +155,20 @@ function module.pcall_err_withfile(fn, ...)
return errmsg
end
-function module.pcall_err(fn, ...)
+function module.pcall_err_withtrace(fn, ...)
local errmsg = module.pcall_err_withfile(fn, ...)
return errmsg:gsub('.../helpers.lua:0: ', '')
end
+function module.pcall_err(...)
+ return module.remove_trace(module.pcall_err_withtrace(...))
+end
+
+function module.remove_trace(s)
+ return (s:gsub("\n%s*stack traceback:.*", ""))
+end
+
-- initial_path: directory to recurse into
-- re: include pattern (string)
-- exc_re: exclude pattern(s) (string or table)
diff --git a/test/unit/api/private_helpers_spec.lua b/test/unit/api/private_helpers_spec.lua
index a534d83165..dbb4b3ae5a 100644
--- a/test/unit/api/private_helpers_spec.lua
+++ b/test/unit/api/private_helpers_spec.lua
@@ -18,7 +18,7 @@ local type_key = api_helpers.type_key
local obj2lua = api_helpers.obj2lua
local func_type = api_helpers.func_type
-local api = cimport('./src/nvim/api/private/helpers.h')
+local api = cimport('./src/nvim/api/private/helpers.h', './src/nvim/api/private/converter.h')
describe('vim_to_object', function()
local vim_to_object = function(l)
diff --git a/test/unit/marktree_spec.lua b/test/unit/marktree_spec.lua
index cd9c7bef13..10d02d2eb4 100644
--- a/test/unit/marktree_spec.lua
+++ b/test/unit/marktree_spec.lua
@@ -97,7 +97,7 @@ describe('marktree', function()
for i = 1,100 do
for j = 1,100 do
local gravitate = (i%2) > 0
- local id = tonumber(lib.marktree_put(tree, j, i, gravitate))
+ local id = tonumber(lib.marktree_put(tree, j, i, gravitate, 0))
ok(id > 0)
eq(nil, shadow[id])
shadow[id] = {j,i,gravitate}
@@ -191,7 +191,7 @@ describe('marktree', function()
-- https://github.com/neovim/neovim/pull/14719
lib.marktree_clear(tree)
for i = 1,20 do
- lib.marktree_put(tree, i, i, false)
+ lib.marktree_put(tree, i, i, false, 0)
end
lib.marktree_itr_get(tree, 10, 10, iter)