support cpying self-referenced table (#2076)

This commit is contained in:
hrsh7th
2024-11-02 13:54:35 +09:00
committed by GitHub
parent 7d4051064c
commit f17d9b4394
2 changed files with 53 additions and 15 deletions

View File

@@ -156,28 +156,39 @@ misc.set = function(t, keys, v)
c[keys[#keys]] = v c[keys[#keys]] = v
end end
---Copy table do
---@generic T local function do_copy(tbl, seen)
---@param tbl T
---@return T
misc.copy = function(tbl)
if type(tbl) ~= 'table' then if type(tbl) ~= 'table' then
return tbl return tbl
end end
if seen[tbl] then
return seen[tbl]
end
if islist(tbl) then if islist(tbl) then
local copy = {} local copy = {}
seen[tbl] = copy
for i, value in ipairs(tbl) do for i, value in ipairs(tbl) do
copy[i] = misc.copy(value) copy[i] = do_copy(value, seen)
end end
return copy return copy
end end
local copy = {} local copy = {}
seen[tbl] = copy
for key, value in pairs(tbl) do for key, value in pairs(tbl) do
copy[key] = misc.copy(value) copy[key] = do_copy(value, seen)
end end
return copy return copy
end
---Copy table
---@generic T
---@param tbl T
---@return T
misc.copy = function(tbl)
return do_copy(tbl, {})
end
end end
---Safe version of vim.str_utfindex ---Safe version of vim.str_utfindex

View File

@@ -5,6 +5,33 @@ local misc = require('cmp.utils.misc')
describe('misc', function() describe('misc', function()
before_each(spec.before) before_each(spec.before)
it('copy', function()
-- basic.
local tbl, copy
tbl = {
a = {
b = 1,
},
}
copy = misc.copy(tbl)
assert.are_not.equal(tbl, copy)
assert.are_not.equal(tbl.a, copy.a)
assert.are.same(tbl, copy)
-- self reference.
tbl = {
a = {
b = 1,
},
}
tbl.a.c = tbl.a
copy = misc.copy(tbl)
assert.are_not.equal(tbl, copy)
assert.are_not.equal(tbl.a, copy.a)
assert.are_not.equal(tbl.a.c, copy.a.c)
assert.are.same(tbl, copy)
end)
it('merge', function() it('merge', function()
local merged local merged
merged = misc.merge({ merged = misc.merge({