From bce0c6e327c953c644c20c043303826340596e8e Mon Sep 17 00:00:00 2001 From: Folke Lemaitre Date: Wed, 4 Jan 2023 09:35:00 +0100 Subject: [PATCH] perf(spec): more efficient merging of specs and added `Plugin._.super` --- lua/lazy/core/plugin.lua | 47 ++++++++++------------ lua/lazy/health.lua | 86 +++++++++++++++++++++++++--------------- lua/lazy/types.lua | 1 + 3 files changed, 76 insertions(+), 58 deletions(-) diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua index 38259604..ccc2745b 100644 --- a/lua/lazy/core/plugin.lua +++ b/lua/lazy/core/plugin.lua @@ -6,6 +6,9 @@ local Cache = require("lazy.core.cache") ---@class LazyCorePlugin local M = {} +local list_merge = { "dependencies" } +vim.list_extend(list_merge, vim.tbl_values(Handler.types)) + ---@class LazySpecLoader ---@field plugins table ---@field disabled table @@ -99,6 +102,7 @@ function Spec:add(plugin, results, is_dep) self.plugins[plugin.name] = plugin return results and table.insert(results, plugin.name) else + -- FIXME: we should somehow merge when needed plugin._.kind = "disabled" self.disabled[plugin.name] = plugin self.plugins[plugin.name] = nil @@ -198,36 +202,29 @@ end ---@param new LazyPlugin ---@return LazyPlugin function Spec:merge(old, new) - local is_dep = old._.dep and new._.dep - - ---@diagnostic disable-next-line: no-unknown - for k, v in pairs(new) do - if k == "_" then - elseif old[k] ~= nil and old[k] ~= v then - if Handler.types[k] then - local values = type(v) == "string" and { v } or v - vim.list_extend(values, type(old[k]) == "string" and { old[k] } or old[k]) - ---@diagnostic disable-next-line: no-unknown - old[k] = values - elseif k == "config" or k == "priority" then - old[k] = v - elseif k == "dependencies" then - for _, dep in ipairs(v) do - if not vim.tbl_contains(old[k], dep) then - table.insert(old[k], dep) - end + new._.dep = old._.dep and new._.dep + + for _, prop in ipairs(list_merge) do + if new[prop] and old[prop] then + ---@type any[] + local props = {} + ---@diagnostic disable-next-line: no-unknown + for _, value in ipairs(old[prop]) do + props[#props + 1] = value + end + ---@diagnostic disable-next-line: no-unknown + for _, value in ipairs(new[prop]) do + if not vim.tbl_contains(props, value) then + props[#props + 1] = value end - else - old[k] = v - self:warn("Overwriting key `" .. k .. "`\n" .. vim.inspect({ old = old, new = new })) end - else ---@diagnostic disable-next-line: no-unknown - old[k] = v + new[prop] = props end end - old._.dep = is_dep - return old + new._.super = old + setmetatable(new, { __index = old }) + return new end function M.update_state() diff --git a/lua/lazy/health.lua b/lua/lazy/health.lua index 7b8fe8a1..24b9de21 100644 --- a/lua/lazy/health.lua +++ b/lua/lazy/health.lua @@ -31,41 +31,10 @@ function M.check() vim.health.report_ok("packer_compiled.lua not found") end - local valid = { - 1, - "name", - "url", - "enabled", - "lazy", - "dev", - "dependencies", - "init", - "config", - "build", - "branch", - "tag", - "commit", - "version", - "module", - "pin", - "cmd", - "event", - "keys", - "ft", - "dir", - "priority", - "cond", - "_", - } local spec = Config.spec for _, plugin in pairs(spec.plugins) do - for key in pairs(plugin) do - if not vim.tbl_contains(valid, key) then - if key ~= "module" or type(plugin.module) ~= "boolean" then - vim.health.report_warn("{" .. plugin.name .. "}: unknown key <" .. key .. ">") - end - end - end + M.check_valid(plugin) + M.check_override(plugin) end if #spec.notifs > 0 then vim.health.report_error("Issues were reported when loading your specs:") @@ -82,4 +51,55 @@ function M.check() end end +---@param plugin LazyPlugin +function M.check_valid(plugin) + for key in pairs(plugin) do + if not vim.tbl_contains(M.valid, key) then + if key ~= "module" or type(plugin.module) ~= "boolean" then + vim.health.report_warn("{" .. plugin.name .. "}: unknown key <" .. key .. ">") + end + end + end +end + +---@param plugin LazyPlugin +function M.check_override(plugin) + if not plugin._.super then + return + end + + for key, value in pairs(plugin._.super) do + if key ~= "_" and plugin[key] and plugin[key] ~= value then + vim.health.report_warn("{" .. plugin.name .. "}: overriding <" .. key .. ">") + end + end +end + +M.valid = { + 1, + "name", + "url", + "enabled", + "lazy", + "dev", + "dependencies", + "init", + "config", + "build", + "branch", + "tag", + "commit", + "version", + "module", + "pin", + "cmd", + "event", + "keys", + "ft", + "dir", + "priority", + "cond", + "_", +} + return M diff --git a/lua/lazy/types.lua b/lua/lazy/types.lua index c461c4c8..ab3832f3 100644 --- a/lua/lazy/types.lua +++ b/lua/lazy/types.lua @@ -13,6 +13,7 @@ ---@field kind? LazyPluginKind ---@field dep? boolean True if this plugin is only in the spec as a dependency ---@field cond? boolean +---@field super? LazyPlugin ---@class LazyPluginHooks ---@field init? fun(LazyPlugin) Will always be run