aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r--runtime/lua/vim/diagnostic.lua12
-rw-r--r--runtime/lua/vim/keymap.lua2
-rw-r--r--runtime/lua/vim/lsp.lua2
-rw-r--r--runtime/lua/vim/lsp/protocol.lua2
-rw-r--r--runtime/lua/vim/shared.lua70
-rw-r--r--runtime/lua/vim/version.lua6
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