diff options
Diffstat (limited to 'runtime/lua')
-rw-r--r-- | runtime/lua/vim/diagnostic.lua | 12 | ||||
-rw-r--r-- | runtime/lua/vim/keymap.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/protocol.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/shared.lua | 70 | ||||
-rw-r--r-- | runtime/lua/vim/version.lua | 6 |
6 files changed, 48 insertions, 46 deletions
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index a447463dff..897837a5ce 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -134,7 +134,7 @@ local function prefix_source(diagnostics) return d end - local t = vim.deepcopy(d) + local t = vim.deepcopy(d, true) t.message = string.format('%s: %s', d.source, d.message) return t end, diagnostics) @@ -146,7 +146,7 @@ local function reformat_diagnostics(format, diagnostics) diagnostics = { diagnostics, 't' }, }) - local formatted = vim.deepcopy(diagnostics) + local formatted = vim.deepcopy(diagnostics, true) for _, diagnostic in ipairs(formatted) do diagnostic.message = format(diagnostic) end @@ -373,7 +373,7 @@ local function get_diagnostics(bufnr, opts, clamp) or d.col < 0 or d.end_col < 0 then - d = vim.deepcopy(d) + d = vim.deepcopy(d, true) d.lnum = math.max(math.min(d.lnum, line_count), 0) d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0) d.col = math.max(d.col, 0) @@ -636,7 +636,7 @@ function M.config(opts, namespace) if not opts then -- Return current config - return vim.deepcopy(t) + return vim.deepcopy(t, true) end for k, v in pairs(opts) do @@ -723,7 +723,7 @@ end --- ---@return table A list of active diagnostic namespaces |vim.diagnostic|. function M.get_namespaces() - return vim.deepcopy(all_namespaces) + return vim.deepcopy(all_namespaces, true) end ---@class Diagnostic @@ -756,7 +756,7 @@ function M.get(bufnr, opts) opts = { opts, 't', true }, }) - return vim.deepcopy(get_diagnostics(bufnr, opts, false)) + return vim.deepcopy(get_diagnostics(bufnr, opts, false), true) end --- Get current diagnostics count. diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index bdea95f9ab..8e4e123fe0 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -44,7 +44,7 @@ function keymap.set(mode, lhs, rhs, opts) opts = { opts, 't', true }, }) - opts = vim.deepcopy(opts or {}) + opts = vim.deepcopy(opts or {}, true) ---@cast mode string[] mode = type(mode) == 'string' and { mode } or mode diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 27c5f7ce7b..b2aa943359 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1353,7 +1353,7 @@ function lsp.start_client(config) ---@param context? {bufnr: integer} ---@param handler? lsp.Handler only called if a server command function client._exec_cmd(command, context, handler) - context = vim.deepcopy(context or {}) --[[@as lsp.HandlerContext]] + context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]] context.bufnr = context.bufnr or api.nvim_get_current_buf() context.client_id = client.id local cmdname = command.command diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index df12c36396..35eb0305d7 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -314,7 +314,7 @@ local constants = { } for k, v in pairs(constants) do - local tbl = vim.deepcopy(v) + local tbl = vim.deepcopy(v, true) vim.tbl_add_reverse_lookup(tbl) protocol[k] = tbl end diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index bbbc888727..87ab21a28f 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -9,43 +9,36 @@ ---@diagnostic disable-next-line: lowercase-global vim = vim or {} -local function _id(v) - return v -end +---@generic T +---@param orig T +---@param cache? table<any,any> +---@return T +local function deepcopy(orig, cache) + if orig == vim.NIL then + return vim.NIL + elseif type(orig) == 'userdata' or type(orig) == 'thread' then + error('Cannot deepcopy object of type ' .. type(orig)) + elseif type(orig) ~= 'table' then + return orig + end -local deepcopy + --- @cast orig table<any,any> -local deepcopy_funcs = { - table = function(orig, cache) - if cache[orig] then - return cache[orig] - end - local copy = {} + if cache and cache[orig] then + return cache[orig] + end + local copy = {} --- @type table<any,any> + + if cache then cache[orig] = copy - local mt = getmetatable(orig) - for k, v in pairs(orig) do - copy[deepcopy(k, cache)] = deepcopy(v, cache) - end - return setmetatable(copy, mt) - end, - number = _id, - string = _id, - ['nil'] = _id, - boolean = _id, - ['function'] = _id, -} - -deepcopy = function(orig, _cache) - local f = deepcopy_funcs[type(orig)] - if f then - return f(orig, _cache or {}) - else - if type(orig) == 'userdata' and orig == vim.NIL then - return vim.NIL - end - error('Cannot deepcopy object of type ' .. type(orig)) end + + for k, v in pairs(orig) do + copy[deepcopy(k, cache)] = deepcopy(v, cache) + end + + return setmetatable(copy, getmetatable(orig)) end --- Returns a deep copy of the given object. Non-table objects are copied as @@ -54,11 +47,20 @@ end --- same functions as those in the input table. Userdata and threads are not --- copied and will throw an error. --- +--- Note: `noref=true` is much more performant on tables with unique table +--- fields, while `noref=false` is more performant on tables that reuse table +--- fields. +--- ---@generic T: table ---@param orig T Table to copy +---@param noref? boolean +--- When `false` (default) a contained table is only copied once and all +--- references point to this single copy. When `true` every occurrence of a +--- table results in a new copy. This also means that a cyclic reference can +--- cause `deepcopy()` to fail. ---@return T Table of copied keys and (nested) values. -function vim.deepcopy(orig) - return deepcopy(orig) +function vim.deepcopy(orig, noref) + return deepcopy(orig, not noref and {} or nil) end --- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua index 306eef90d3..0873402e29 100644 --- a/runtime/lua/vim/version.lua +++ b/runtime/lua/vim/version.lua @@ -158,7 +158,7 @@ end function M._version(version, strict) -- Adapted from https://github.com/folke/lazy.nvim if type(version) == 'table' then if version.major then - return setmetatable(vim.deepcopy(version), Version) + return setmetatable(vim.deepcopy(version, true), Version) end return setmetatable({ major = version[1] or 0, @@ -228,7 +228,7 @@ function VersionRange:has(version) version = M.parse(version) elseif getmetatable(version) ~= Version then -- Need metatable to compare versions. - version = setmetatable(vim.deepcopy(version), Version) + version = setmetatable(vim.deepcopy(version, true), Version) end if version then if version.prerelease ~= self.from.prerelease then @@ -298,7 +298,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim local semver = M.parse(version) if semver then local from = semver - local to = vim.deepcopy(semver) + local to = vim.deepcopy(semver, true) if mods == '' or mods == '=' then to.patch = to.patch + 1 elseif mods == '<' then |