From 417fc6ccf78801aef79a8731c5a85db6b12cd407 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Thu, 13 Feb 2020 11:55:43 +0900 Subject: [PATCH 1/3] lua: vim.deepcopy uses empty_dict() instead of {} for empty_dict() fix: https://github.com/neovim/nvim-lsp/issues/94 --- runtime/lua/vim/shared.lua | 5 ++++ test/functional/lua/vim_spec.lua | 42 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index ea1117a906..36df24d0c1 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -20,6 +20,11 @@ vim.deepcopy = (function() local deepcopy_funcs = { table = function(orig) local copy = {} + + if getmetatable(orig) == vim._empty_dict_mt then + copy = vim.empty_dict() + end + for k, v in pairs(orig) do copy[vim.deepcopy(k)] = vim.deepcopy(v) end diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index e879f8b925..b8edd7b3e0 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -322,6 +322,48 @@ describe('lua stdlib', function() ]]) assert(is_dc) + + local is_empty_list = exec_lua([[ + local a = {} + local b = vim.deepcopy(a) + + local count = 0 + for _ in pairs(b) do count = count + 1 end + + return getmetatable(b) ~= vim._empty_dict_mt + and count == 0 + and tostring(a) ~= tostring(b) + ]]) + + assert(is_empty_list) + + local is_empty_dic = exec_lua([[ + local a = vim.empty_dict() + local b = vim.deepcopy(a) + + local count = 0 + for _ in pairs(b) do count = count + 1 end + + return getmetatable(b) == vim._empty_dict_mt + and count == 0 + ]]) + + assert(is_empty_dic) + + local include_empty_dic = exec_lua([[ + local a = {x = vim.empty_dict(), y = {}} + local b = vim.deepcopy(a) + + local count = 0 + for _ in pairs(b) do count = count + 1 end + + return getmetatable(b.x) == vim._empty_dict_mt + and getmetatable(b.y) ~= vim._empty_dict_mt + and count == 2 + and tostring(a) ~= tostring(b) + ]]) + + assert(include_empty_dic) end) it('vim.pesc', function() From c230c7d1a6b744efb673f516f0c6cc2a17c2305b Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Thu, 13 Feb 2020 15:02:30 +0900 Subject: [PATCH 2/3] lua: if second argument is vim.empty_dict(), vim.tbl_extend uses empty_dict() instead of {} --- runtime/lua/vim/shared.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 36df24d0c1..6eb7a970e4 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -21,7 +21,7 @@ vim.deepcopy = (function() table = function(orig) local copy = {} - if getmetatable(orig) == vim._empty_dict_mt then + if vim._empty_dict_mt ~= nil and getmetatable(orig) == vim._empty_dict_mt then copy = vim.empty_dict() end @@ -174,9 +174,19 @@ function vim.tbl_extend(behavior, ...) 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 + local ret = {} + 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,'t'}} if tbl then for k, v in pairs(tbl) do if behavior ~= 'force' and ret[k] ~= nil then From cdb729b7462cfef28a0264cb75bffe69182c5275 Mon Sep 17 00:00:00 2001 From: Hirokazu Hata Date: Fri, 14 Feb 2020 19:40:02 +0900 Subject: [PATCH 3/3] lua: add vim.tbl_extend and vim.deepcopy test --- test/functional/lua/vim_spec.lua | 122 +++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 23 deletions(-) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index b8edd7b3e0..f549ca2bd1 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -7,6 +7,7 @@ local meths = helpers.meths local command = helpers.command local clear = helpers.clear local eq = helpers.eq +local ok = helpers.ok local eval = helpers.eval local feed = helpers.feed local pcall_err = helpers.pcall_err @@ -310,7 +311,7 @@ describe('lua stdlib', function() end) it("vim.deepcopy", function() - local is_dc = exec_lua([[ + ok(exec_lua([[ local a = { x = { 1, 2 }, y = 5} local b = vim.deepcopy(a) @@ -319,51 +320,39 @@ describe('lua stdlib', function() return b.x[1] == 1 and b.x[2] == 2 and b.y == 5 and count == 2 and tostring(a) ~= tostring(b) - ]]) + ]])) - assert(is_dc) - - local is_empty_list = exec_lua([[ + ok(exec_lua([[ local a = {} local b = vim.deepcopy(a) local count = 0 for _ in pairs(b) do count = count + 1 end - return getmetatable(b) ~= vim._empty_dict_mt - and count == 0 - and tostring(a) ~= tostring(b) - ]]) + return vim.tbl_islist(b) and count == 0 and tostring(a) ~= tostring(b) + ]])) - assert(is_empty_list) - - local is_empty_dic = exec_lua([[ + ok(exec_lua([[ local a = vim.empty_dict() local b = vim.deepcopy(a) local count = 0 for _ in pairs(b) do count = count + 1 end - return getmetatable(b) == vim._empty_dict_mt - and count == 0 - ]]) + return not vim.tbl_islist(b) and count == 0 + ]])) - assert(is_empty_dic) - - local include_empty_dic = exec_lua([[ + ok(exec_lua([[ local a = {x = vim.empty_dict(), y = {}} local b = vim.deepcopy(a) local count = 0 for _ in pairs(b) do count = count + 1 end - return getmetatable(b.x) == vim._empty_dict_mt - and getmetatable(b.y) ~= vim._empty_dict_mt + return not vim.tbl_islist(b.x) and vim.tbl_islist(b.y) and count == 2 and tostring(a) ~= tostring(b) - ]]) - - assert(include_empty_dic) + ]])) end) it('vim.pesc', function() @@ -411,6 +400,93 @@ describe('lua stdlib', function() eq(false, exec_lua("return vim.tbl_isempty({a=1, b=2, c=3})")) end) + it('vim.tbl_extend', function() + ok(exec_lua([[ + local a = {x = 1} + local b = {y = 2} + local c = vim.tbl_extend("keep", a, b) + + local count = 0 + for _ in pairs(c) do count = count + 1 end + + return c.x == 1 and b.y == 2 and count == 2 + ]])) + + ok(exec_lua([[ + local a = {x = 1} + local b = {y = 2} + local c = {z = 3} + local d = vim.tbl_extend("keep", a, b, c) + + local count = 0 + for _ in pairs(d) do count = count + 1 end + + return d.x == 1 and d.y == 2 and d.z == 3 and count == 3 + ]])) + + ok(exec_lua([[ + local a = {x = 1} + local b = {x = 3} + local c = vim.tbl_extend("keep", a, b) + + local count = 0 + for _ in pairs(c) do count = count + 1 end + + return c.x == 1 and count == 1 + ]])) + + ok(exec_lua([[ + local a = {x = 1} + local b = {x = 3} + local c = vim.tbl_extend("force", a, b) + + local count = 0 + for _ in pairs(c) do count = count + 1 end + + return c.x == 3 and count == 1 + ]])) + + ok(exec_lua([[ + local a = vim.empty_dict() + local b = {} + local c = vim.tbl_extend("keep", a, b) + + local count = 0 + for _ in pairs(c) do count = count + 1 end + + return not vim.tbl_islist(c) and count == 0 + ]])) + + ok(exec_lua([[ + local a = {} + local b = vim.empty_dict() + local c = vim.tbl_extend("keep", a, b) + + local count = 0 + for _ in pairs(c) do count = count + 1 end + + return vim.tbl_islist(c) and count == 0 + ]])) + + eq('Error executing lua: .../shared.lua: invalid "behavior": nil', + pcall_err(exec_lua, [[ + return vim.tbl_extend() + ]]) + ) + + eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)', + pcall_err(exec_lua, [[ + return vim.tbl_extend("keep") + ]]) + ) + + eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)', + pcall_err(exec_lua, [[ + return vim.tbl_extend("keep", {}) + ]]) + ) + end) + it('vim.deep_equal', function() eq(true, exec_lua [[ return vim.deep_equal({a=1}, {a=1}) ]]) eq(true, exec_lua [[ return vim.deep_equal({a={b=1}}, {a={b=1}}) ]])