diff options
author | Lewis Russell <lewis6991@gmail.com> | 2024-01-15 19:49:08 +0000 |
---|---|---|
committer | Lewis Russell <lewis6991@gmail.com> | 2024-01-17 10:10:17 +0000 |
commit | 26835d8d9cf1312d2851b191fe859c6f62d9d9d4 (patch) | |
tree | f2dd9bf5c2283a62a91c67372f2cebd454c6c0a2 | |
parent | 5a16d08a6389596c89691b45b06121b4814a089f (diff) | |
download | rneovim-26835d8d9cf1312d2851b191fe859c6f62d9d9d4.tar.gz rneovim-26835d8d9cf1312d2851b191fe859c6f62d9d9d4.tar.bz2 rneovim-26835d8d9cf1312d2851b191fe859c6f62d9d9d4.zip |
test: add type annotations
-rw-r--r-- | test/client/msgpack_rpc_stream.lua | 3 | ||||
-rw-r--r-- | test/client/session.lua | 14 | ||||
-rw-r--r-- | test/client/uv_stream.lua | 36 | ||||
-rw-r--r-- | test/functional/helpers.lua | 204 | ||||
-rw-r--r-- | test/helpers.lua | 102 |
5 files changed, 268 insertions, 91 deletions
diff --git a/test/client/msgpack_rpc_stream.lua b/test/client/msgpack_rpc_stream.lua index 4b4f30e0ec..7131940a58 100644 --- a/test/client/msgpack_rpc_stream.lua +++ b/test/client/msgpack_rpc_stream.lua @@ -22,6 +22,9 @@ function Response:send(value, is_error) self._msgpack_rpc_stream._stream:write(data) end +--- @class test.MsgpackRpcStream +--- @field private _stream test.Stream +--- @field private __pack table local MsgpackRpcStream = {} MsgpackRpcStream.__index = MsgpackRpcStream diff --git a/test/client/session.lua b/test/client/session.lua index 86b4ee7103..cf3d8c4f25 100644 --- a/test/client/session.lua +++ b/test/client/session.lua @@ -1,6 +1,12 @@ local uv = vim.uv local MsgpackRpcStream = require('test.client.msgpack_rpc_stream') +--- @class test.Session +--- @field private _pending_messages string[] +--- @field private _msgpack_rpc_stream test.MsgpackRpcStream +--- @field private _prepare uv.uv_prepare_t +--- @field private _timer uv.uv_timer_t +--- @field private _is_running boolean local Session = {} Session.__index = Session if package.loaded['jit'] then @@ -26,7 +32,7 @@ end local function coroutine_exec(func, ...) local args = { ... } - local on_complete + local on_complete --- @type function? if #args > 0 and type(args[#args]) == 'function' then -- completion callback @@ -54,6 +60,8 @@ function Session.new(stream) }, Session) end +--- @param timeout integer? +--- @return string? function Session:next_message(timeout) local function on_request(method, args, response) table.insert(self._pending_messages, { 'request', method, args, response }) @@ -86,6 +94,10 @@ function Session:notify(method, ...) self._msgpack_rpc_stream:write(method, { ... }) end +--- @param method string +--- @param ... any +--- @return boolean +--- @return table function Session:request(method, ...) local args = { ... } local err, result diff --git a/test/client/uv_stream.lua b/test/client/uv_stream.lua index 9e9a69e0a1..0540c44eb2 100644 --- a/test/client/uv_stream.lua +++ b/test/client/uv_stream.lua @@ -1,18 +1,28 @@ local uv = vim.uv +--- @class test.Stream +--- @field write fun(self, data: string|string[]) +--- @field read_start fun(self, cb: fun(chunk: string)) +--- @field read_stop fun(self) +--- @field close fun(self, signal?: string) + +--- @class vim.StdioStream : test.Stream +--- @field private _in uv.uv_pipe_t +--- @field private _out uv.uv_pipe_t local StdioStream = {} StdioStream.__index = StdioStream function StdioStream.open() local self = setmetatable({ - _in = uv.new_pipe(false), - _out = uv.new_pipe(false), + _in = assert(uv.new_pipe(false)), + _out = assert(uv.new_pipe(false)), }, StdioStream) self._in:open(0) self._out:open(1) return self end +--- @param data string|string[] function StdioStream:write(data) self._out:write(data) end @@ -35,11 +45,14 @@ function StdioStream:close() self._out:close() end +--- @class test.SocketStream : test.Stream +--- @field package _stream_error? string +--- @field package _socket uv.uv_pipe_t local SocketStream = {} SocketStream.__index = SocketStream function SocketStream.open(file) - local socket = uv.new_pipe(false) + local socket = assert(uv.new_pipe(false)) local self = setmetatable({ _socket = socket, _stream_error = nil, @@ -51,7 +64,7 @@ function SocketStream.open(file) end function SocketStream.connect(host, port) - local socket = uv.new_tcp() + local socket = assert(uv.new_tcp()) local self = setmetatable({ _socket = socket, _stream_error = nil, @@ -96,9 +109,20 @@ function SocketStream:close() uv.close(self._socket) end +--- @class test.ChildProcessStream : test.Stream +--- @field private _proc uv.uv_process_t +--- @field private _pid integer +--- @field private _child_stdin uv.uv_pipe_t +--- @field private _child_stdout uv.uv_pipe_t +--- @field status integer +--- @field signal integer local ChildProcessStream = {} ChildProcessStream.__index = ChildProcessStream +--- @param argv string[] +--- @param env string[]? +--- @param io_extra uv.uv_pipe_t? +--- @return test.ChildProcessStream function ChildProcessStream.spawn(argv, env, io_extra) local self = setmetatable({ _child_stdin = uv.new_pipe(false), @@ -106,13 +130,15 @@ function ChildProcessStream.spawn(argv, env, io_extra) _exiting = false, }, ChildProcessStream) local prog = argv[1] - local args = {} + local args = {} --- @type string[] for i = 2, #argv do args[#args + 1] = argv[i] end + --- @diagnostic disable-next-line:missing-fields self._proc, self._pid = uv.spawn(prog, { stdio = { self._child_stdin, self._child_stdout, 2, io_extra }, args = args, + --- @diagnostic disable-next-line:assign-type-mismatch env = env, }, function(status, signal) self.status = status diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index e1fbfe6ff3..eddf336b6f 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -55,7 +55,7 @@ if module.nvim_dir == module.nvim_prog then module.nvim_dir = '.' end -local prepend_argv +local prepend_argv --- @type string[]? if os.getenv('VALGRIND') then local log_file = os.getenv('VALGRIND_LOG') or 'valgrind-%p.log' @@ -79,7 +79,7 @@ elseif os.getenv('GDB') then end if prepend_argv then - local new_nvim_argv = {} + local new_nvim_argv = {} --- @type string[] local len = #prepend_argv for i = 1, len do new_nvim_argv[i] = prepend_argv[i] @@ -91,10 +91,13 @@ if prepend_argv then module.prepend_argv = prepend_argv end -local session, loop_running, last_error, method_error +local session --- @type test.Session? +local loop_running --- @type boolean? +local last_error --- @type string? +local method_error --- @type string? if not is_os('win') then - local sigpipe_handler = uv.new_signal() + local sigpipe_handler = assert(uv.new_signal()) uv.signal_start(sigpipe_handler, 'sigpipe', function() print('warning: got SIGPIPE signal. Likely related to a crash in nvim') end) @@ -108,10 +111,15 @@ function module.set_session(s) session = s end +--- @param method string +--- @param ... any +--- @return any function module.request(method, ...) + assert(session) local status, rv = session:request(method, ...) if not status then if loop_running then + --- @type string last_error = rv[2] session:stop() else @@ -121,12 +129,18 @@ function module.request(method, ...) return rv end +--- @param method string +--- @param ... any +--- @return any function module.request_lua(method, ...) return module.exec_lua([[return vim.api[...](select(2, ...))]], method, ...) end +--- @param timeout? integer +--- @return string? function module.next_msg(timeout) - return session:next_message(timeout and timeout or 10000) + assert(session) + return session:next_message(timeout or 10000) end function module.expect_twostreams(msgs1, msgs2) @@ -164,6 +178,7 @@ function module.expect_msg_seq(...) error('invalid args') end local ignore = arg1['ignore'] and arg1['ignore'] or {} + --- @type string[] local seqs = arg1['seqs'] and arg1['seqs'] or { ... } if type(ignore) ~= 'table' then error("'ignore' arg must be a list of strings") @@ -213,6 +228,7 @@ function module.expect_msg_seq(...) local message = result if type(result) == 'table' then -- 'eq' returns several things + --- @type string message = result.message end final_error = cat_err(final_error, message) @@ -234,8 +250,16 @@ function module.set_method_error(err) method_error = err end +--- @param lsession test.Session +--- @param request_cb function +--- @param notification_cb function +--- @param setup_cb function +--- @param timeout integer +--- @return {[1]: integer, [2]: string} function module.run_session(lsession, request_cb, notification_cb, setup_cb, timeout) - local on_request, on_notification, on_setup + local on_request --- @type function? + local on_notification --- @type function? + local on_setup --- @type function? if request_cb then function on_request(method, args) @@ -273,11 +297,12 @@ function module.run_session(lsession, request_cb, notification_cb, setup_cb, tim end function module.run(request_cb, notification_cb, setup_cb, timeout) + assert(session) return module.run_session(session, request_cb, notification_cb, setup_cb, timeout) end function module.stop() - session:stop() + assert(session):stop() end function module.nvim_prog_abs() @@ -301,6 +326,7 @@ function module.expect_exit(fn_or_timeout, ...) eof_err_msg, module.pcall_err(function(timeout, fn, ...) fn(...) + assert(session) while session:next_message(timeout) do end if session.eof_err then @@ -311,14 +337,18 @@ function module.expect_exit(fn_or_timeout, ...) end end --- Executes a Vimscript function via Lua. --- Fails on Vimscript error, but does not update v:errmsg. +--- Executes a Vimscript function via Lua. +--- Fails on Vimscript error, but does not update v:errmsg. +--- @param name string +--- @param ... any +--- @return any function module.call_lua(name, ...) return module.exec_lua([[return vim.call(...)]], name, ...) end --- Sends user input to Nvim. --- Does not fail on Vimscript error, but v:errmsg will be updated. +--- Sends user input to Nvim. +--- Does not fail on Vimscript error, but v:errmsg will be updated. +--- @param input string local function nvim_feed(input) while #input > 0 do local written = module.request('nvim_input', input) @@ -330,22 +360,27 @@ local function nvim_feed(input) end end +--- @param ... string function module.feed(...) for _, v in ipairs({ ... }) do nvim_feed(dedent(v)) end end +--- @param ... string function module.rawfeed(...) for _, v in ipairs({ ... }) do nvim_feed(dedent(v)) end end +---@param ... string[]? +---@return string[] function module.merge_args(...) local i = 1 - local argv = {} + local argv = {} --- @type string[] for anum = 1, select('#', ...) do + --- @type string[]? local args = select(anum, ...) if args then for _, arg in ipairs(args) do @@ -357,26 +392,29 @@ function module.merge_args(...) return argv end --- Removes Nvim startup args from `args` matching items in `args_rm`. --- --- - Special case: "-u", "-i", "--cmd" are treated specially: their "values" are also removed. --- - Special case: "runtimepath" will remove only { '--cmd', 'set runtimepath^=…', } --- --- Example: --- args={'--headless', '-u', 'NONE'} --- args_rm={'--cmd', '-u'} --- Result: --- {'--headless'} --- --- All matching cases are removed. --- --- Example: --- args={'--cmd', 'foo', '-N', '--cmd', 'bar'} --- args_rm={'--cmd', '-u'} --- Result: --- {'-N'} +--- Removes Nvim startup args from `args` matching items in `args_rm`. +--- +--- - Special case: "-u", "-i", "--cmd" are treated specially: their "values" are also removed. +--- - Special case: "runtimepath" will remove only { '--cmd', 'set runtimepath^=…', } +--- +--- Example: +--- args={'--headless', '-u', 'NONE'} +--- args_rm={'--cmd', '-u'} +--- Result: +--- {'--headless'} +--- +--- All matching cases are removed. +--- +--- Example: +--- args={'--cmd', 'foo', '-N', '--cmd', 'bar'} +--- args_rm={'--cmd', '-u'} +--- Result: +--- {'-N'} +--- @param args string[] +--- @param args_rm string[] +--- @return string[] local function remove_args(args, args_rm) - local new_args = {} + local new_args = {} --- @type string[] local skip_following = { '-u', '-i', '-c', '--cmd', '-s', '--listen' } if not args_rm or #args_rm == 0 then return { unpack(args) } @@ -421,7 +459,12 @@ function module.check_close() session = nil end ---- @param io_extra used for stdin_fd, see :help ui-option +--- @param argv string[] +--- @param merge boolean? +--- @param env string[]? +--- @param keep boolean +--- @param io_extra uv.uv_pipe_t? used for stdin_fd, see :help ui-option +--- @return test.Session function module.spawn(argv, merge, env, keep, io_extra) if not keep then module.check_close() @@ -457,16 +500,27 @@ function module.clear(...) return module.get_session() end --- same params as clear, but does returns the session instead --- of replacing the default session +--- same params as clear, but does returns the session instead +--- of replacing the default session +--- @return test.Session function module.spawn_argv(keep, ...) local argv, env, io_extra = module.new_argv(...) return module.spawn(argv, nil, env, keep, io_extra) end --- Builds an argument list for use in clear(). --- ----@see clear() for parameters. +--- @class test.new_argv.Opts +--- @field args? string[] +--- @field args_rm? string[] +--- @field env? table<string,string> +--- @field io_extra? uv.uv_pipe_t + +--- Builds an argument list for use in clear(). +--- +--- @see clear() for parameters. +--- @param ... string +--- @return string[] +--- @return string[]? +--- @return uv.uv_pipe_t? function module.new_argv(...) local args = { unpack(module.nvim_argv) } table.insert(args, '--headless') @@ -475,16 +529,17 @@ function module.new_argv(...) table.insert(args, '--listen') table.insert(args, _G._nvim_test_id) end - local new_args - local io_extra - local env = nil + local new_args --- @type string[] + local io_extra --- @type uv.uv_pipe_t? + local env --- @type string[]? + --- @type test.new_argv.Opts|string local opts = select(1, ...) if type(opts) ~= 'table' then new_args = { ... } else args = remove_args(args, opts.args_rm) if opts.env then - local env_opt = {} + local env_opt = {} --- @type table<string,string> for k, v in pairs(opts.env) do assert(type(k) == 'string') assert(type(v) == 'string') @@ -523,6 +578,7 @@ function module.new_argv(...) return args, env, io_extra end +--- @param ... string function module.insert(...) nvim_feed('i') for _, v in ipairs({ ... }) do @@ -532,8 +588,9 @@ function module.insert(...) nvim_feed('<ESC>') end --- Executes an ex-command by user input. Because nvim_input() is used, Vimscript --- errors will not manifest as client (lua) errors. Use command() for that. +--- Executes an ex-command by user input. Because nvim_input() is used, Vimscript +--- errors will not manifest as client (lua) errors. Use command() for that. +--- @param ... string function module.feed_command(...) for _, v in ipairs({ ... }) do if v:sub(1, 1) ~= '/' then @@ -587,6 +644,9 @@ end function module.create_callindex(func) return setmetatable({}, { + --- @param tbl table<any,function> + --- @param arg1 string + --- @return function __index = function(tbl, arg1) local ret = function(...) return func(arg1, ...) @@ -597,12 +657,17 @@ function module.create_callindex(func) }) end +--- @param method string +--- @param ... any function module.nvim_async(method, ...) - session:notify(method, ...) + assert(session):notify(method, ...) end --- Executes a Vimscript function via RPC. --- Fails on Vimscript error, but does not update v:errmsg. +--- Executes a Vimscript function via RPC. +--- Fails on Vimscript error, but does not update v:errmsg. +--- @param name string +--- @param ... any +--- @return any function module.call(name, ...) return module.request('nvim_call_function', name, { ... }) end @@ -637,6 +702,7 @@ module.api = vim.api module.fn = vim.fn for name, fns in pairs(module.rpc) do + --- @diagnostic disable-next-line:no-unknown module[name] = fns end @@ -673,6 +739,10 @@ function module.expect_any(contents) return ok(nil ~= string.find(module.curbuf_contents(), contents, 1, true)) end +--- @param expected any[] +--- @param received any[] +--- @param kind string +--- @return any function module.expect_events(expected, received, kind) if not pcall(eq, expected, received) then local msg = 'unexpected ' .. kind .. ' received.\n\n' @@ -712,6 +782,7 @@ function module.assert_visible(bufnr, visible) end end +--- @param path string local function do_rmdir(path) local stat = uv.fs_stat(path) if stat == nil then @@ -779,14 +850,17 @@ function module.exc_exec(cmd) return ret end +--- @param cond boolean +--- @param reason string +--- @return boolean function module.skip(cond, reason) if cond then + --- @type fun(reason: string) local pending = getfenv(2).pending pending(reason or 'FIXME') return true - else - return false end + return false end -- Calls pending() and returns `true` if the system is too slow to @@ -809,6 +883,8 @@ function module.exec(code) module.api.nvim_exec2(code, {}) end +--- @param code string +--- @return string function module.exec_capture(code) return module.api.nvim_exec2(code, { output = true }).output end @@ -855,19 +931,24 @@ function module.new_pipename() return pipename end +--- @param provider string +--- @return string|false? function module.missing_provider(provider) if provider == 'ruby' or provider == 'node' or provider == 'perl' then + --- @type string? local e = module.fn['provider#' .. provider .. '#Detect']()[2] return e ~= '' and e or false elseif provider == 'python' or provider == 'python3' then local py_major_version = (provider == 'python3' and 3 or 2) + --- @type string? local e = module.fn['provider#pythonx#Detect'](py_major_version)[2] return e ~= '' and e or false - else - assert(false, 'Unknown provider: ' .. provider) end + assert(false, 'Unknown provider: ' .. provider) end +--- @param obj string|table +--- @return any function module.alter_slashes(obj) if not is_os('win') then return obj @@ -876,14 +957,14 @@ function module.alter_slashes(obj) local ret = obj:gsub('/', '\\') return ret elseif type(obj) == 'table' then - local ret = {} + --- @cast obj table<any,any> + local ret = {} --- @type table<any,any> for k, v in pairs(obj) do ret[k] = module.alter_slashes(v) end return ret - else - assert(false, 'expected string or table of strings, got ' .. type(obj)) end + assert(false, 'expected string or table of strings, got ' .. type(obj)) end local load_factor = 1 @@ -893,18 +974,25 @@ if global_helpers.is_ci() then module.request('nvim_command', 'source test/old/testdir/load.vim') load_factor = module.request('nvim_eval', 'g:test_load_factor') end + +--- @param num number +--- @return number function module.load_adjust(num) return math.ceil(num * load_factor) end +--- @param ctx table<string,any> +--- @return table function module.parse_context(ctx) - local parsed = {} + local parsed = {} --- @type table<string,any> for _, item in ipairs({ 'regs', 'jumps', 'bufs', 'gvars' }) do + --- @param v any parsed[item] = vim.tbl_filter(function(v) return type(v) == 'table' end, module.call('msgpackparse', ctx[item])) end parsed['bufs'] = parsed['bufs'][1] + --- @param v any return vim.tbl_map(function(v) if #v == 0 then return nil @@ -918,7 +1006,9 @@ function module.add_builddir_to_rtp() module.command(string.format([[set rtp+=%s/runtime]], module.paths.test_build_dir)) end --- Kill (reap) a process by PID. +--- Kill (reap) a process by PID. +--- @param pid string +--- @return boolean? function module.os_kill(pid) return os.execute( ( @@ -928,7 +1018,9 @@ function module.os_kill(pid) ) end --- Create folder with non existing parents +--- Create folder with non existing parents +--- @param path string +--- @return boolean? function module.mkdir_p(path) return os.execute((is_os('win') and 'mkdir ' .. path or 'mkdir -p ' .. path)) end diff --git a/test/helpers.lua b/test/helpers.lua index fa09942bc9..f0cb395c89 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -63,8 +63,12 @@ function module.popen_r(...) return io.popen(module.argss_to_cmd(...), 'r') end --- Calls fn() until it succeeds, up to `max` times or until `max_ms` --- milliseconds have passed. +--- Calls fn() until it succeeds, up to `max` times or until `max_ms` +--- milliseconds have passed. +--- @param max integer? +--- @param max_ms integer? +--- @param fn function +--- @return any function module.retry(max, max_ms, fn) luaassert(max == nil or max > 0) luaassert(max_ms == nil or max_ms > 0) @@ -72,6 +76,7 @@ function module.retry(max, max_ms, fn) local timeout = (max_ms and max_ms or 10000) local start_time = uv.now() while true do + --- @type boolean, any local status, result = pcall(fn) if status then return result @@ -121,6 +126,9 @@ function module.fail(msg) return luaassert.epicfail(msg) end +--- @param pat string +--- @param actual string +--- @return boolean function module.matches(pat, actual) if nil ~= string.match(actual, pat) then return true @@ -170,10 +178,16 @@ end --- Asserts that `pat` does NOT match any line in the tail of `logfile`. --- --- @see assert_log +--- @param pat (string) Lua pattern to match lines in the log file +--- @param logfile? (string) Full path to log file (default=$NVIM_LOG_FILE) +--- @param nrlines? (number) Search up to this many log lines function module.assert_nolog(pat, logfile, nrlines) return module.assert_log(pat, logfile, nrlines, true) end +--- @param fn fun(...): any +--- @param ... any +--- @return boolean, any function module.pcall(fn, ...) luaassert(type(fn) == 'function') local status, rv = pcall(fn, ...) @@ -221,6 +235,8 @@ end -- -- Match Lua pattern. -- matches('e[or]+$', pcall_err(function(a, b) error('some error') end, 'arg1', 'arg2')) -- +--- @param fn function +--- @return string function module.pcall_err_withfile(fn, ...) luaassert(type(fn) == 'function') local status, rv = module.pcall(fn, ...) @@ -230,19 +246,29 @@ function module.pcall_err_withfile(fn, ...) return rv end +--- @param fn function +--- @param ... any +--- @return string function module.pcall_err_withtrace(fn, ...) local errmsg = module.pcall_err_withfile(fn, ...) - return errmsg - :gsub('^%.%.%./helpers%.lua:0: ', '') - :gsub('^Error executing lua:- ', '') - :gsub('^%[string "<nvim>"%]:0: ', '') + return ( + errmsg + :gsub('^%.%.%./helpers%.lua:0: ', '') + :gsub('^Error executing lua:- ', '') + :gsub('^%[string "<nvim>"%]:0: ', '') + ) end -function module.pcall_err(...) - return module.remove_trace(module.pcall_err_withtrace(...)) +--- @param fn function +--- @param ... any +--- @return string +function module.pcall_err(fn, ...) + return module.remove_trace(module.pcall_err_withtrace(fn, ...)) end +--- @param s string +--- @return string function module.remove_trace(s) return (s:gsub('\n%s*stack traceback:.*', '')) end @@ -252,9 +278,9 @@ end -- exc_re: exclude pattern(s) (string or table) function module.glob(initial_path, re, exc_re) exc_re = type(exc_re) == 'table' and exc_re or { exc_re } - local paths_to_check = { initial_path } - local ret = {} - local checked_files = {} + local paths_to_check = { initial_path } --- @type string[] + local ret = {} --- @type string[] + local checked_files = {} --- @type table<string,true> local function is_excluded(path) for _, pat in pairs(exc_re) do if path:match(pat) then @@ -301,7 +327,7 @@ function module.check_logs() local file = log_dir .. '/' .. tail local fd = assert(io.open(file)) local start_msg = ('='):rep(20) .. ' File ' .. file .. ' ' .. ('='):rep(20) - local lines = {} + local lines = {} --- @type string[] local warning_line = 0 for line in fd:lines() do local cur_warning_line = check_logs_useless_lines[line] @@ -313,6 +339,7 @@ function module.check_logs() end fd:close() if #lines > 0 then + --- @type boolean?, file*? local status, f local out = io.stdout if os.getenv('SYMBOLIZER') then @@ -320,6 +347,7 @@ function module.check_logs() end out:write(start_msg .. '\n') if status then + assert(f) for line in f:lines() do out:write('= ' .. line .. '\n') end @@ -364,9 +392,11 @@ local function tmpdir_get() return os.getenv('TMPDIR') and os.getenv('TMPDIR') or os.getenv('TEMP') end --- Is temp directory `dir` defined local to the project workspace? +--- Is temp directory `dir` defined local to the project workspace? +--- @param dir string? +--- @return boolean local function tmpdir_is_local(dir) - return not not (dir and string.find(dir, 'Xtest')) + return not not (dir and dir:find('Xtest')) end --- Creates a new temporary file for use by tests. @@ -410,6 +440,7 @@ function module.check_cores(app, force) -- luacheck: ignore return end app = app or 'build/bin/nvim' -- luacheck: ignore + --- @type string, string?, string[] local initial_path, re, exc_re local gdb_db_cmd = 'gdb -n -batch -ex "thread apply all bt full" "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"' @@ -422,14 +453,14 @@ function module.check_cores(app, force) -- luacheck: ignore and relpath(tmpdir_get()):gsub('^[ ./]+', ''):gsub('%/+$', ''):gsub('([^%w])', '%%%1') or nil ) - local db_cmd + local db_cmd --- @type string local test_glob_dir = os.getenv('NVIM_TEST_CORE_GLOB_DIRECTORY') if test_glob_dir and test_glob_dir ~= '' then initial_path = test_glob_dir re = os.getenv('NVIM_TEST_CORE_GLOB_RE') exc_re = { os.getenv('NVIM_TEST_CORE_EXC_RE'), local_tmpdir } db_cmd = os.getenv('NVIM_TEST_CORE_DB_CMD') or gdb_db_cmd - random_skip = os.getenv('NVIM_TEST_CORE_RANDOM_SKIP') + random_skip = os.getenv('NVIM_TEST_CORE_RANDOM_SKIP') ~= '' elseif module.is_os('mac') then initial_path = '/cores' re = nil @@ -487,17 +518,24 @@ function module.repeated_read_cmd(...) return nil end +--- @generic T +--- @param orig T +--- @return T function module.shallowcopy(orig) if type(orig) ~= 'table' then return orig end - local copy = {} + --- @cast orig table<any,any> + local copy = {} --- @type table<any,any> for orig_key, orig_value in pairs(orig) do copy[orig_key] = orig_value end return copy end +--- @param d1 table<any,any> +--- @param d2 table<any,any> +--- @return table<any,any> function module.mergedicts_copy(d1, d2) local ret = module.shallowcopy(d1) for k, v in pairs(d2) do @@ -512,11 +550,13 @@ function module.mergedicts_copy(d1, d2) return ret end --- dictdiff: find a diff so that mergedicts_copy(d1, diff) is equal to d2 --- --- Note: does not do copies of d2 values used. +--- dictdiff: find a diff so that mergedicts_copy(d1, diff) is equal to d2 +--- +--- Note: does not do copies of d2 values used. +--- @param d1 table<any,any> +--- @param d2 table<any,any> function module.dictdiff(d1, d2) - local ret = {} + local ret = {} --- @type table<any,any> local hasdiff = false for k, v in pairs(d1) do if d2[k] == nil then @@ -554,8 +594,9 @@ end -- Concat list-like tables. function module.concat_tables(...) - local ret = {} + local ret = {} --- @type table<any,any> for i = 1, select('#', ...) do + --- @type table<any,any> local tbl = select(i, ...) if tbl then for _, v in ipairs(tbl) do @@ -787,10 +828,10 @@ function module.hexdump(str) return dump .. hex .. string.rep(' ', 8 - len % 8) .. asc end --- Reads text lines from `filename` into a table. --- --- filename: path to file --- start: start line (1-indexed), negative means "lines before end" (tail) +--- Reads text lines from `filename` into a table. +--- @param filename string path to file +--- @param start? integer start line (1-indexed), negative means "lines before end" (tail) +--- @return string[]? function module.read_file_list(filename, start) local lnum = (start ~= nil and type(start) == 'number') and start or 1 local tail = (lnum < 0) @@ -826,9 +867,9 @@ function module.read_file_list(filename, start) return lines end --- Reads the entire contents of `filename` into a string. --- --- filename: path to file +--- Reads the entire contents of `filename` into a string. +--- @param filename string +--- @return string? function module.read_file(filename) local file = io.open(filename, 'r') if not file then @@ -844,6 +885,7 @@ function module.write_file(name, text, no_dedent, append) local file = assert(io.open(name, (append and 'a' or 'w'))) if type(text) == 'table' then -- Byte blob + --- @type string[] local bytes = text text = '' for _, char in ipairs(bytes) do @@ -857,6 +899,8 @@ function module.write_file(name, text, no_dedent, append) file:close() end +--- @param name? 'cirrus'|'github' +--- @return boolean function module.is_ci(name) local any = (name == nil) luaassert(any or name == 'github' or name == 'cirrus') |