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 | |
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
-rw-r--r-- | runtime/doc/news.txt | 3 | ||||
-rw-r--r-- | runtime/lua/vim/shared.lua | 53 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 10 |
3 files changed, 42 insertions, 24 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index dacb27e320..507559cac7 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -210,6 +210,9 @@ These existing features changed their behavior. more emoji characters than before, including those encoded with multiple emoji codepoints combined with ZWJ (zero width joiner) codepoints. +• |vim.tbl_deep_extend()| no longer ignores any values for which |vim.isarray()| + returns `true`. + ============================================================================== REMOVED FEATURES *news-removed* 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()| diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index df68020d8e..7bba24483e 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -1059,7 +1059,7 @@ describe('lua stdlib', function() local a = { a = {[2] = 3} } local b = { a = {[3] = 3} } local c = vim.tbl_deep_extend("force", a, b) - return vim.deep_equal(c, {a = {[3] = 3}}) + return vim.deep_equal(c, {a = {[2] = 3, [3] = 3}}) ]])) eq( @@ -1071,6 +1071,14 @@ describe('lua stdlib', function() ]]) ) + -- Fix github issue #23654 + ok(exec_lua([[ + local a = { sub = { [1] = 'a' } } + local b = { sub = { b = 'a' } } + local c = vim.tbl_deep_extend('force', a, b) + return vim.deep_equal(c, { sub = { [1] = 'a', b = 'a' } }) + ]])) + matches( 'invalid "behavior": nil', pcall_err( |