diff options
author | Lewis Russell <lewis6991@gmail.com> | 2024-09-03 17:14:25 +0100 |
---|---|---|
committer | Lewis Russell <me@lewisr.dev> | 2024-09-04 11:34:19 +0100 |
commit | b6e350a6b4df40fcc99931c460668c36fadc9989 (patch) | |
tree | 37a22c94c5d38e9a3bdf57b08ae7b5a7ea747d7b /runtime/lua/vim/shared.lua | |
parent | 7b7c95dac97d6ea4f10855cc198dce650a796c20 (diff) | |
download | rneovim-b6e350a6b4df40fcc99931c460668c36fadc9989.tar.gz rneovim-b6e350a6b4df40fcc99931c460668c36fadc9989.tar.bz2 rneovim-b6e350a6b4df40fcc99931c460668c36fadc9989.zip |
fix(lua): allows tables with integer keys to be merged in tbl_deep_extend
- The exclusion of lists was never justified in the commit history and is
the wrong thing to do for a function that deals with tables.
- Move the error checks out of the recursive path.
Fixes #23654
Diffstat (limited to 'runtime/lua/vim/shared.lua')
-rw-r--r-- | runtime/lua/vim/shared.lua | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 99530bf72e..2f10380bad 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -354,37 +354,22 @@ function vim.tbl_isempty(t) return next(t) == nil end ---- We only merge empty tables or tables that are not an array (indexed by integers) -local function can_merge(v) - return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.isarray(v)) -end - -local function tbl_extend(behavior, deep_extend, ...) - if behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force' then - error('invalid "behavior": ' .. tostring(behavior)) - end - - if select('#', ...) < 2 then - error( - 'wrong number of arguments (given ' - .. tostring(1 + select('#', ...)) - .. ', expected at least 3)' - ) - end - +--- Recursive worker for tbl_extend +--- @param behavior 'error'|'keep'|'force' +--- @param deep_extend boolean +--- @param ... table<any,any> +local function tbl_extend_rec(behavior, deep_extend, ...) local ret = {} --- @type table<any,any> if vim._empty_dict_mt ~= nil and getmetatable(select(1, ...)) == vim._empty_dict_mt then ret = vim.empty_dict() end for i = 1, select('#', ...) do - local tbl = select(i, ...) - vim.validate('after the second argument', tbl, 'table') - --- @cast tbl table<any,any> + local tbl = select(i, ...) --[[@as table<any,any>]] if tbl then for k, v in pairs(tbl) do - if deep_extend and can_merge(v) and can_merge(ret[k]) then - ret[k] = tbl_extend(behavior, true, ret[k], v) + if deep_extend and type(v) == 'table' and type(ret[k]) == 'table' then + ret[k] = tbl_extend_rec(behavior, true, ret[k], v) elseif behavior ~= 'force' and ret[k] ~= nil then if behavior == 'error' then error('key found in more than one map: ' .. k) @@ -395,9 +380,31 @@ local function tbl_extend(behavior, deep_extend, ...) end end end + return ret end +--- @param behavior 'error'|'keep'|'force' +--- @param deep_extend boolean +--- @param ... table<any,any> +local function tbl_extend(behavior, deep_extend, ...) + if behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force' then + error('invalid "behavior": ' .. tostring(behavior)) + end + + local nargs = select('#', ...) + + if nargs < 2 then + error(('wrong number of arguments (given %d, expected at least 3)'):format(1 + nargs)) + end + + for i = 1, nargs do + vim.validate('after the second argument', select(i, ...), 'table') + end + + return tbl_extend_rec(behavior, deep_extend, ...) +end + --- Merges two or more tables. --- ---@see |extend()| |