mirror of
https://github.com/neovim/neovim.git
synced 2025-12-10 00:22:41 +00:00
Merge pull request #12053 from tjdevries/tjdevries/nicer_validate
vim.validate(): include stacktrace in message
This commit is contained in:
@@ -477,48 +477,77 @@ end
|
||||
--- 2. (arg_value, fn, msg)
|
||||
--- - arg_value: argument value
|
||||
--- - fn: any function accepting one argument, returns true if and
|
||||
--- only if the argument is valid
|
||||
--- only if the argument is valid. Can optionally return an additional
|
||||
--- informative error message as the second returned value.
|
||||
--- - msg: (optional) error string if validation fails
|
||||
function vim.validate(opt) end -- luacheck: no unused
|
||||
vim.validate = (function()
|
||||
|
||||
do
|
||||
local type_names = {
|
||||
t='table', s='string', n='number', b='boolean', f='function', c='callable',
|
||||
['table']='table', ['string']='string', ['number']='number',
|
||||
['boolean']='boolean', ['function']='function', ['callable']='callable',
|
||||
['nil']='nil', ['thread']='thread', ['userdata']='userdata',
|
||||
['table'] = 'table', t = 'table',
|
||||
['string'] = 'string', s = 'string',
|
||||
['number'] = 'number', n = 'number',
|
||||
['boolean'] = 'boolean', b = 'boolean',
|
||||
['function'] = 'function', f = 'function',
|
||||
['callable'] = 'callable', c = 'callable',
|
||||
['nil'] = 'nil',
|
||||
['thread'] = 'thread',
|
||||
['userdata'] = 'userdata',
|
||||
}
|
||||
local function _type_name(t)
|
||||
local tname = type_names[t]
|
||||
if tname == nil then
|
||||
error(string.format('invalid type name: %s', tostring(t)))
|
||||
end
|
||||
return tname
|
||||
end
|
||||
|
||||
local function _is_type(val, t)
|
||||
return t == 'callable' and vim.is_callable(val) or type(val) == t
|
||||
end
|
||||
|
||||
return function(opt)
|
||||
assert(type(opt) == 'table', string.format('opt: expected table, got %s', type(opt)))
|
||||
local function is_valid(opt)
|
||||
if type(opt) ~= 'table' then
|
||||
return false, string.format('opt: expected table, got %s', type(opt))
|
||||
end
|
||||
|
||||
for param_name, spec in pairs(opt) do
|
||||
assert(type(spec) == 'table', string.format('%s: expected table, got %s', param_name, type(spec)))
|
||||
if type(spec) ~= 'table' then
|
||||
return false, string.format('opt[%s]: expected table, got %s', param_name, type(spec))
|
||||
end
|
||||
|
||||
local val = spec[1] -- Argument value.
|
||||
local t = spec[2] -- Type name, or callable.
|
||||
local optional = (true == spec[3])
|
||||
|
||||
if not vim.is_callable(t) then -- Check type name.
|
||||
if (not optional or val ~= nil) and not _is_type(val, _type_name(t)) then
|
||||
error(string.format("%s: expected %s, got %s", param_name, _type_name(t), type(val)))
|
||||
if type(t) == 'string' then
|
||||
local t_name = type_names[t]
|
||||
if not t_name then
|
||||
return false, string.format('invalid type name: %s', t)
|
||||
end
|
||||
elseif not t(val) then -- Check user-provided validation function.
|
||||
error(string.format("%s: expected %s, got %s", param_name, (spec[3] or '?'), val))
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end)()
|
||||
|
||||
if (not optional or val ~= nil) and not _is_type(val, t_name) then
|
||||
return false, string.format("%s: expected %s, got %s", param_name, t_name, type(val))
|
||||
end
|
||||
elseif vim.is_callable(t) then
|
||||
-- Check user-provided validation function.
|
||||
local valid, optional_message = t(val)
|
||||
if not valid then
|
||||
local error_message = string.format("%s: expected %s, got %s", param_name, (spec[3] or '?'), val)
|
||||
if optional_message ~= nil then
|
||||
error_message = error_message .. string.format(". Info: %s", optional_message)
|
||||
end
|
||||
|
||||
return false, error_message
|
||||
end
|
||||
else
|
||||
return false, string.format("invalid type name: %s", tostring(t))
|
||||
end
|
||||
end
|
||||
|
||||
return true, nil
|
||||
end
|
||||
|
||||
function vim.validate(opt)
|
||||
local ok, err_msg = is_valid(opt)
|
||||
if not ok then
|
||||
error(debug.traceback(err_msg, 2), 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
--- Returns true if object `f` can be called as a function.
|
||||
---
|
||||
--@param f Any object
|
||||
|
||||
@@ -449,19 +449,19 @@ describe('API', function()
|
||||
end)
|
||||
|
||||
it('reports errors', function()
|
||||
eq([[Error loading lua: [string "<nvim>"]:1: '=' expected near '+']],
|
||||
eq([[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']],
|
||||
pcall_err(meths.exec_lua, 'a+*b', {}))
|
||||
|
||||
eq([[Error loading lua: [string "<nvim>"]:1: unexpected symbol near '1']],
|
||||
eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']],
|
||||
pcall_err(meths.exec_lua, '1+2', {}))
|
||||
|
||||
eq([[Error loading lua: [string "<nvim>"]:1: unexpected symbol]],
|
||||
eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol]],
|
||||
pcall_err(meths.exec_lua, 'aa=bb\0', {}))
|
||||
|
||||
eq([[Error executing lua: [string "<nvim>"]:1: attempt to call global 'bork' (a nil value)]],
|
||||
eq([[Error executing lua: [string "<nvim>"]:0: attempt to call global 'bork' (a nil value)]],
|
||||
pcall_err(meths.exec_lua, 'bork()', {}))
|
||||
|
||||
eq('Error executing lua: [string "<nvim>"]:1: did\nthe\nfail',
|
||||
eq('Error executing lua: [string "<nvim>"]:0: did\nthe\nfail',
|
||||
pcall_err(meths.exec_lua, 'error("did\\nthe\\nfail")', {}))
|
||||
end)
|
||||
|
||||
@@ -605,7 +605,7 @@ describe('API', function()
|
||||
end)
|
||||
it('vim.paste() failure', function()
|
||||
nvim('exec_lua', 'vim.paste = (function(lines, phase) error("fake fail") end)', {})
|
||||
eq([[Error executing lua: [string "<nvim>"]:1: fake fail]],
|
||||
eq([[Error executing lua: [string "<nvim>"]:0: fake fail]],
|
||||
pcall_err(request, 'nvim_paste', 'line 1\nline 2\nline 3', false, 1))
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -43,7 +43,7 @@ describe(':lua command', function()
|
||||
eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
|
||||
end)
|
||||
it('throws catchable errors', function()
|
||||
eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:1: unexpected symbol near ')']],
|
||||
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")'))
|
||||
|
||||
@@ -477,14 +477,14 @@ describe('v:lua', function()
|
||||
eq(NIL, eval('v:lua.mymod.noisy("eval")'))
|
||||
eq("hey eval", meths.get_current_line())
|
||||
|
||||
eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)",
|
||||
eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
|
||||
pcall_err(eval, 'v:lua.mymod.crashy()'))
|
||||
end)
|
||||
|
||||
it('works in :call', function()
|
||||
command(":call v:lua.mymod.noisy('command')")
|
||||
eq("hey command", meths.get_current_line())
|
||||
eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)",
|
||||
eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
|
||||
pcall_err(command, 'call v:lua.mymod.crashy()'))
|
||||
end)
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@ before_each(clear)
|
||||
describe('treesitter API', function()
|
||||
-- error tests not requiring a parser library
|
||||
it('handles missing language', function()
|
||||
eq("Error executing lua: .../language.lua: no parser for 'borklang' language, see :help treesitter-parsers",
|
||||
eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
|
||||
pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')"))
|
||||
|
||||
-- actual message depends on platform
|
||||
matches("Error executing lua: Failed to load parser: uv_dlopen: .+",
|
||||
pcall_err(exec_lua, "parser = vim.treesitter.require_language('borklang', 'borkbork.so')"))
|
||||
|
||||
eq("Error executing lua: .../language.lua: no parser for 'borklang' language, see :help treesitter-parsers",
|
||||
eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
|
||||
pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')"))
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -4,13 +4,14 @@ local Screen = require('test.functional.ui.screen')
|
||||
|
||||
local funcs = helpers.funcs
|
||||
local meths = helpers.meths
|
||||
local dedent = helpers.dedent
|
||||
local command = helpers.command
|
||||
local clear = helpers.clear
|
||||
local eq = helpers.eq
|
||||
local ok = helpers.ok
|
||||
local eval = helpers.eval
|
||||
local feed = helpers.feed
|
||||
local pcall_err = helpers.pcall_err
|
||||
local pcall_err_withfile = helpers.pcall_err_withfile
|
||||
local exec_lua = helpers.exec_lua
|
||||
local matches = helpers.matches
|
||||
local source = helpers.source
|
||||
@@ -128,8 +129,8 @@ describe('lua stdlib', function()
|
||||
eq(false, funcs.luaeval('vim.startswith("123", "2")'))
|
||||
eq(false, funcs.luaeval('vim.startswith("123", "1234")'))
|
||||
|
||||
eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith("123", nil)')))
|
||||
eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith(nil, "123")')))
|
||||
eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.startswith("123", nil)')))
|
||||
eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.startswith(nil, "123")')))
|
||||
end)
|
||||
|
||||
it('vim.endswith', function()
|
||||
@@ -142,8 +143,8 @@ describe('lua stdlib', function()
|
||||
eq(false, funcs.luaeval('vim.endswith("123", "2")'))
|
||||
eq(false, funcs.luaeval('vim.endswith("123", "1234")'))
|
||||
|
||||
eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith("123", nil)')))
|
||||
eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith(nil, "123")')))
|
||||
eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.endswith("123", nil)')))
|
||||
eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.endswith(nil, "123")')))
|
||||
end)
|
||||
|
||||
it("vim.str_utfindex/str_byteindex", function()
|
||||
@@ -182,10 +183,10 @@ describe('lua stdlib', function()
|
||||
eq({"yy","xx"}, exec_lua("return test_table"))
|
||||
|
||||
-- Validates args.
|
||||
eq('Error executing lua: vim.schedule: expected function',
|
||||
pcall_err(exec_lua, "vim.schedule('stringly')"))
|
||||
eq('Error executing lua: vim.schedule: expected function',
|
||||
pcall_err(exec_lua, "vim.schedule()"))
|
||||
eq('.../helpers.lua:0: Error executing lua: vim.schedule: expected function',
|
||||
pcall_err_withfile(exec_lua, "vim.schedule('stringly')"))
|
||||
eq('.../helpers.lua:0: Error executing lua: vim.schedule: expected function',
|
||||
pcall_err_withfile(exec_lua, "vim.schedule()"))
|
||||
|
||||
exec_lua([[
|
||||
vim.schedule(function()
|
||||
@@ -257,17 +258,29 @@ describe('lua stdlib', function()
|
||||
}
|
||||
|
||||
for _, t in ipairs(loops) do
|
||||
matches(".*Infinite loop detected", pcall_err(split, t[1], t[2]))
|
||||
matches(".*Infinite loop detected", pcall_err_withfile(split, t[1], t[2]))
|
||||
end
|
||||
|
||||
-- Validates args.
|
||||
eq(true, pcall(split, 'string', 'string'))
|
||||
eq('Error executing lua: .../shared.lua: s: expected string, got number',
|
||||
pcall_err(split, 1, 'string'))
|
||||
eq('Error executing lua: .../shared.lua: sep: expected string, got number',
|
||||
pcall_err(split, 'string', 1))
|
||||
eq('Error executing lua: .../shared.lua: plain: expected boolean, got number',
|
||||
pcall_err(split, 'string', 'string', 1))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number
|
||||
stack traceback:
|
||||
shared.lua:0: in function 'gsplit'
|
||||
shared.lua:0: in function <shared.lua:0>]]),
|
||||
pcall_err_withfile(split, 1, 'string'))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: shared.lua:0: sep: expected string, got number
|
||||
stack traceback:
|
||||
shared.lua:0: in function 'gsplit'
|
||||
shared.lua:0: in function <shared.lua:0>]]),
|
||||
pcall_err_withfile(split, 'string', 1))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: shared.lua:0: plain: expected boolean, got number
|
||||
stack traceback:
|
||||
shared.lua:0: in function 'gsplit'
|
||||
shared.lua:0: in function <shared.lua:0>]]),
|
||||
pcall_err_withfile(split, 'string', 'string', 1))
|
||||
end)
|
||||
|
||||
it('vim.trim', function()
|
||||
@@ -287,8 +300,11 @@ describe('lua stdlib', function()
|
||||
end
|
||||
|
||||
-- Validates args.
|
||||
eq('Error executing lua: .../shared.lua: s: expected string, got number',
|
||||
pcall_err(trim, 2))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number
|
||||
stack traceback:
|
||||
shared.lua:0: in function <shared.lua:0>]]),
|
||||
pcall_err_withfile(trim, 2))
|
||||
end)
|
||||
|
||||
it('vim.inspect', function()
|
||||
@@ -353,8 +369,8 @@ describe('lua stdlib', function()
|
||||
return t1.f() ~= t2.f()
|
||||
]]))
|
||||
|
||||
eq('Error executing lua: .../shared.lua: Cannot deepcopy object of type thread',
|
||||
pcall_err(exec_lua, [[
|
||||
eq('.../helpers.lua:0: Error executing lua: shared.lua:0: Cannot deepcopy object of type thread',
|
||||
pcall_err_withfile(exec_lua, [[
|
||||
local thread = coroutine.create(function () return 0 end)
|
||||
local t = {thr = thread}
|
||||
vim.deepcopy(t)
|
||||
@@ -366,8 +382,11 @@ describe('lua stdlib', function()
|
||||
eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]]))
|
||||
|
||||
-- Validates args.
|
||||
eq('Error executing lua: .../shared.lua: s: expected string, got number',
|
||||
pcall_err(exec_lua, [[return vim.pesc(2)]]))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number
|
||||
stack traceback:
|
||||
shared.lua:0: in function <shared.lua:0>]]),
|
||||
pcall_err_withfile(exec_lua, [[return vim.pesc(2)]]))
|
||||
end)
|
||||
|
||||
it('vim.tbl_keys', function()
|
||||
@@ -491,20 +510,20 @@ describe('lua stdlib', function()
|
||||
return c.x.a == 1 and c.x.b == 2 and c.x.c == nil and count == 1
|
||||
]]))
|
||||
|
||||
eq('Error executing lua: .../shared.lua: invalid "behavior": nil',
|
||||
pcall_err(exec_lua, [[
|
||||
eq('.../helpers.lua:0: Error executing lua: shared.lua:0: invalid "behavior": nil',
|
||||
pcall_err_withfile(exec_lua, [[
|
||||
return vim.tbl_extend()
|
||||
]])
|
||||
)
|
||||
|
||||
eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)',
|
||||
pcall_err(exec_lua, [[
|
||||
eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 1, expected at least 3)',
|
||||
pcall_err_withfile(exec_lua, [[
|
||||
return vim.tbl_extend("keep")
|
||||
]])
|
||||
)
|
||||
|
||||
eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)',
|
||||
pcall_err(exec_lua, [[
|
||||
eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 2, expected at least 3)',
|
||||
pcall_err_withfile(exec_lua, [[
|
||||
return vim.tbl_extend("keep", {})
|
||||
]])
|
||||
)
|
||||
@@ -579,20 +598,20 @@ describe('lua stdlib', function()
|
||||
return vim.tbl_islist(c) and count == 0
|
||||
]]))
|
||||
|
||||
eq('Error executing lua: .../shared.lua: invalid "behavior": nil',
|
||||
pcall_err(exec_lua, [[
|
||||
eq('.../helpers.lua:0: Error executing lua: shared.lua:0: invalid "behavior": nil',
|
||||
pcall_err_withfile(exec_lua, [[
|
||||
return vim.tbl_deep_extend()
|
||||
]])
|
||||
)
|
||||
|
||||
eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)',
|
||||
pcall_err(exec_lua, [[
|
||||
eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 1, expected at least 3)',
|
||||
pcall_err_withfile(exec_lua, [[
|
||||
return vim.tbl_deep_extend("keep")
|
||||
]])
|
||||
)
|
||||
|
||||
eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)',
|
||||
pcall_err(exec_lua, [[
|
||||
eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 2, expected at least 3)',
|
||||
pcall_err_withfile(exec_lua, [[
|
||||
return vim.tbl_deep_extend("keep", {})
|
||||
]])
|
||||
)
|
||||
@@ -624,8 +643,11 @@ describe('lua stdlib', function()
|
||||
|
||||
it('vim.list_extend', function()
|
||||
eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]])
|
||||
eq('Error executing lua: .../shared.lua: src: expected table, got nil',
|
||||
pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]]))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: shared.lua:0: src: expected table, got nil
|
||||
stack traceback:
|
||||
shared.lua:0: in function <shared.lua:0>]]),
|
||||
pcall_err_withfile(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 ]])
|
||||
eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1) ]])
|
||||
@@ -648,8 +670,8 @@ describe('lua stdlib', function()
|
||||
assert(vim.deep_equal(a, { A = 1; [1] = 'A'; }))
|
||||
vim.tbl_add_reverse_lookup(a)
|
||||
]]
|
||||
matches('Error executing lua: .../shared.lua: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"',
|
||||
pcall_err(exec_lua, code))
|
||||
matches('.../helpers.lua:0: Error executing lua: shared.lua:0: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"',
|
||||
pcall_err_withfile(exec_lua, code))
|
||||
end)
|
||||
|
||||
it('vim.call, vim.fn', function()
|
||||
@@ -820,34 +842,77 @@ 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("Error executing lua: .../shared.lua: 1: expected table, got number",
|
||||
pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
|
||||
eq("Error executing lua: .../shared.lua: invalid type name: x",
|
||||
pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
|
||||
eq("Error executing lua: .../shared.lua: invalid type name: 1",
|
||||
pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
|
||||
eq("Error executing lua: .../shared.lua: invalid type name: nil",
|
||||
pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{ 1, 'x' }"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: x
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: 1
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: nil
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1 }}"))
|
||||
|
||||
-- Validated parameters are required by default.
|
||||
eq("Error executing lua: .../shared.lua: arg1: expected string, got nil",
|
||||
pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
|
||||
-- Explicitly required.
|
||||
eq("Error executing lua: .../shared.lua: arg1: expected string, got nil",
|
||||
pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
|
||||
|
||||
eq("Error executing lua: .../shared.lua: arg1: expected table, got number",
|
||||
pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}"))
|
||||
eq("Error executing lua: .../shared.lua: arg2: expected string, got number",
|
||||
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
|
||||
eq("Error executing lua: .../shared.lua: arg2: expected string, got nil",
|
||||
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
|
||||
eq("Error executing lua: .../shared.lua: arg2: expected string, got nil",
|
||||
pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
|
||||
eq("Error executing lua: .../shared.lua: arg1: expected even number, got 3",
|
||||
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
|
||||
eq("Error executing lua: .../shared.lua: arg1: expected ?, got 3",
|
||||
pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{arg1={1, 't'}}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
|
||||
|
||||
-- Pass an additional message back.
|
||||
eq(dedent([[
|
||||
.../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG
|
||||
stack traceback:
|
||||
[string "<nvim>"]:0: in main chunk]]),
|
||||
pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}"))
|
||||
end)
|
||||
|
||||
it('vim.is_callable', function()
|
||||
@@ -992,10 +1057,10 @@ describe('lua stdlib', function()
|
||||
]]
|
||||
eq('', funcs.luaeval "vim.bo.filetype")
|
||||
eq(true, funcs.luaeval "vim.bo[BUF].modifiable")
|
||||
matches("^Error executing lua: .*: Invalid option name: 'nosuchopt'$",
|
||||
pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
|
||||
matches("^Error executing lua: .*: Expected lua string$",
|
||||
pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
|
||||
matches("^.../helpers.lua:0: Error executing lua: .*: Invalid option name: 'nosuchopt'$",
|
||||
pcall_err_withfile(exec_lua, 'return vim.bo.nosuchopt'))
|
||||
matches("^.../helpers.lua:0: Error executing lua: .*: Expected lua string$",
|
||||
pcall_err_withfile(exec_lua, 'return vim.bo[0][0].autoread'))
|
||||
end)
|
||||
|
||||
it('vim.wo', function()
|
||||
@@ -1011,10 +1076,10 @@ describe('lua stdlib', function()
|
||||
eq(0, funcs.luaeval "vim.wo.cole")
|
||||
eq(0, funcs.luaeval "vim.wo[0].cole")
|
||||
eq(0, funcs.luaeval "vim.wo[1001].cole")
|
||||
matches("^Error executing lua: .*: Invalid option name: 'notanopt'$",
|
||||
pcall_err(exec_lua, 'return vim.wo.notanopt'))
|
||||
matches("^Error executing lua: .*: Expected lua string$",
|
||||
pcall_err(exec_lua, 'return vim.wo[0][0].list'))
|
||||
matches("^.../helpers.lua:0: Error executing lua: .*: Invalid option name: 'notanopt'$",
|
||||
pcall_err_withfile(exec_lua, 'return vim.wo.notanopt'))
|
||||
matches("^.../helpers.lua:0: Error executing lua: .*: Expected lua string$",
|
||||
pcall_err_withfile(exec_lua, 'return vim.wo[0][0].list'))
|
||||
eq(2, funcs.luaeval "vim.wo[1000].cole")
|
||||
exec_lua [[
|
||||
vim.wo[1000].cole = 0
|
||||
|
||||
@@ -747,8 +747,16 @@ describe('LSP', function()
|
||||
end)
|
||||
|
||||
it('should invalid cmd argument', function()
|
||||
eq('Error executing lua: .../shared.lua: cmd: expected list, got nvim', pcall_err(_cmd_parts, "nvim"))
|
||||
eq('Error executing lua: .../shared.lua: cmd argument: expected string, got number', pcall_err(_cmd_parts, {"nvim", 1}))
|
||||
eq(dedent([[
|
||||
Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim
|
||||
stack traceback:
|
||||
.../lsp.lua:0: in function .../lsp.lua:0>]]),
|
||||
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>]]),
|
||||
pcall_err(_cmd_parts, {'nvim', 1}))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('floatwin', function()
|
||||
end)
|
||||
|
||||
it('closed immediately by autocmd #11383', function()
|
||||
eq('Error executing lua: [string "<nvim>"]:4: Window was closed immediately',
|
||||
eq('Error executing lua: [string "<nvim>"]:0: Window was closed immediately',
|
||||
pcall_err(exec_lua, [[
|
||||
local a = vim.api
|
||||
local function crashes(contents)
|
||||
|
||||
@@ -116,8 +116,12 @@ function module.assert_log(pat, logfile)
|
||||
pat, nrlines, logfile, logtail))
|
||||
end
|
||||
|
||||
-- Invokes `fn` and returns the error string (may truncate full paths), or
|
||||
-- raises an error if `fn` succeeds.
|
||||
-- Invokes `fn` and returns the error string (with truncated paths), or raises
|
||||
-- an error if `fn` succeeds.
|
||||
--
|
||||
-- Replaces line/column numbers with zero:
|
||||
-- shared.lua:0: in function 'gsplit'
|
||||
-- shared.lua:0: in function <shared.lua:0>'
|
||||
--
|
||||
-- Usage:
|
||||
-- -- Match exact string.
|
||||
@@ -125,29 +129,36 @@ end
|
||||
-- -- Match Lua pattern.
|
||||
-- matches('e[or]+$', pcall_err(function(a, b) error('some error') end, 'arg1', 'arg2'))
|
||||
--
|
||||
function module.pcall_err(fn, ...)
|
||||
function module.pcall_err_withfile(fn, ...)
|
||||
assert(type(fn) == 'function')
|
||||
local status, rv = pcall(fn, ...)
|
||||
if status == true then
|
||||
error('expected failure, but got success')
|
||||
end
|
||||
-- From this:
|
||||
-- /home/foo/neovim/runtime/lua/vim/shared.lua:186: Expected string, got number
|
||||
-- to this:
|
||||
-- Expected string, got number
|
||||
local errmsg = tostring(rv):gsub('^[^:]+:%d+: ', '')
|
||||
-- From this:
|
||||
-- Error executing lua: /very/long/foo.lua:186: Expected string, got number
|
||||
-- to this:
|
||||
-- Error executing lua: .../foo.lua:186: Expected string, got number
|
||||
errmsg = errmsg:gsub([[lua: [a-zA-Z]?:?[^:]-[/\]([^:/\]+):%d+: ]], 'lua: .../%1: ')
|
||||
-- Compiled modules will not have a path and will just be a name like
|
||||
-- shared.lua:186, so strip the number.
|
||||
errmsg = errmsg:gsub([[lua: ([^:/\ ]+):%d+: ]], 'lua: .../%1: ')
|
||||
-- ^ Windows drive-letter (C:)
|
||||
-- From:
|
||||
-- C:/long/path/foo.lua:186: Expected string, got number
|
||||
-- to:
|
||||
-- .../foo.lua:0: Expected string, got number
|
||||
local errmsg = tostring(rv):gsub('[^%s]-[/\\]([^%s:/\\]+):%d+', '.../%1:0')
|
||||
-- Scrub numbers in paths/stacktraces:
|
||||
-- shared.lua:0: in function 'gsplit'
|
||||
-- shared.lua:0: in function <shared.lua:0>'
|
||||
errmsg = errmsg:gsub('([^%s]):%d+', '%1:0')
|
||||
-- Scrub tab chars:
|
||||
errmsg = errmsg:gsub('\t', ' ')
|
||||
-- In Lua 5.1, we sometimes get a "(tail call): ?" on the last line.
|
||||
-- We remove this so that the tests are not lua dependent.
|
||||
errmsg = errmsg:gsub('%s*%(tail call%): %?', '')
|
||||
|
||||
return errmsg
|
||||
end
|
||||
|
||||
function module.pcall_err(fn, ...)
|
||||
local errmsg = module.pcall_err_withfile(fn, ...)
|
||||
|
||||
return errmsg:gsub('.../helpers.lua:0: ', '')
|
||||
end
|
||||
|
||||
-- initial_path: directory to recurse into
|
||||
-- re: include pattern (string)
|
||||
-- exc_re: exclude pattern(s) (string or table)
|
||||
|
||||
Reference in New Issue
Block a user