mirror of
https://github.com/neovim/neovim
synced 2025-07-17 01:31:48 +00:00
fix(shared): do not treat empty tables as list in deep extend (#15094)
An empty table was previously always treated as a list, which means that while merging tables, whenever an empty table was encountered it would always truncate any table on the left. `vim.tbl_deep_extend("force", { b = { a = 1 } }, { b = {} })` Before: `{ b = {} }` After: `{ b = { a = 1 } }`
This commit is contained in:
@ -200,6 +200,10 @@ function vim.tbl_isempty(t)
|
|||||||
return next(t) == nil
|
return next(t) == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function can_merge(v)
|
||||||
|
return type(v) == "table" and (vim.tbl_isempty(v) or not vim.tbl_islist(v))
|
||||||
|
end
|
||||||
|
|
||||||
local function tbl_extend(behavior, deep_extend, ...)
|
local function tbl_extend(behavior, deep_extend, ...)
|
||||||
if (behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force') then
|
if (behavior ~= 'error' and behavior ~= 'keep' and behavior ~= 'force') then
|
||||||
error('invalid "behavior": '..tostring(behavior))
|
error('invalid "behavior": '..tostring(behavior))
|
||||||
@ -219,8 +223,8 @@ local function tbl_extend(behavior, deep_extend, ...)
|
|||||||
vim.validate{["after the second argument"] = {tbl,'t'}}
|
vim.validate{["after the second argument"] = {tbl,'t'}}
|
||||||
if tbl then
|
if tbl then
|
||||||
for k, v in pairs(tbl) do
|
for k, v in pairs(tbl) do
|
||||||
if type(v) == 'table' and deep_extend and not vim.tbl_islist(v) then
|
if deep_extend and can_merge(v) and can_merge(ret[k]) then
|
||||||
ret[k] = tbl_extend(behavior, true, ret[k] or vim.empty_dict(), v)
|
ret[k] = tbl_extend(behavior, true, ret[k], v)
|
||||||
elseif behavior ~= 'force' and ret[k] ~= nil then
|
elseif behavior ~= 'force' and ret[k] ~= nil then
|
||||||
if behavior == 'error' then
|
if behavior == 'error' then
|
||||||
error('key found in more than one map: '..k)
|
error('key found in more than one map: '..k)
|
||||||
|
@ -603,6 +603,31 @@ describe('lua stdlib', function()
|
|||||||
return vim.tbl_islist(c) and count == 0
|
return vim.tbl_islist(c) and count == 0
|
||||||
]]))
|
]]))
|
||||||
|
|
||||||
|
eq(exec_lua([[
|
||||||
|
local a = { a = { b = 1 } }
|
||||||
|
local b = { a = {} }
|
||||||
|
return vim.tbl_deep_extend("force", a, b)
|
||||||
|
]]), {a = {b = 1}})
|
||||||
|
|
||||||
|
eq(exec_lua([[
|
||||||
|
local a = { a = 123 }
|
||||||
|
local b = { a = { b = 1} }
|
||||||
|
return vim.tbl_deep_extend("force", a, b)
|
||||||
|
]]), {a = {b = 1}})
|
||||||
|
|
||||||
|
ok(exec_lua([[
|
||||||
|
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}})
|
||||||
|
]]))
|
||||||
|
|
||||||
|
eq(exec_lua([[
|
||||||
|
local a = { a = { b = 1} }
|
||||||
|
local b = { a = 123 }
|
||||||
|
return vim.tbl_deep_extend("force", a, b)
|
||||||
|
]]), {a = 123 })
|
||||||
|
|
||||||
eq('Error executing lua: vim/shared.lua:0: invalid "behavior": nil',
|
eq('Error executing lua: vim/shared.lua:0: invalid "behavior": nil',
|
||||||
pcall_err(exec_lua, [[
|
pcall_err(exec_lua, [[
|
||||||
return vim.tbl_deep_extend()
|
return vim.tbl_deep_extend()
|
||||||
|
Reference in New Issue
Block a user