perf(spec): more efficient merging of specs and added `Plugin._.super`

This commit is contained in:
Folke Lemaitre 2023-01-04 09:35:00 +01:00
parent 6d46a3028d
commit bce0c6e327
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
3 changed files with 77 additions and 59 deletions

View File

@ -6,6 +6,9 @@ local Cache = require("lazy.core.cache")
---@class LazyCorePlugin ---@class LazyCorePlugin
local M = {} local M = {}
local list_merge = { "dependencies" }
vim.list_extend(list_merge, vim.tbl_values(Handler.types))
---@class LazySpecLoader ---@class LazySpecLoader
---@field plugins table<string, LazyPlugin> ---@field plugins table<string, LazyPlugin>
---@field disabled table<string, LazyPlugin> ---@field disabled table<string, LazyPlugin>
@ -99,6 +102,7 @@ function Spec:add(plugin, results, is_dep)
self.plugins[plugin.name] = plugin self.plugins[plugin.name] = plugin
return results and table.insert(results, plugin.name) return results and table.insert(results, plugin.name)
else else
-- FIXME: we should somehow merge when needed
plugin._.kind = "disabled" plugin._.kind = "disabled"
self.disabled[plugin.name] = plugin self.disabled[plugin.name] = plugin
self.plugins[plugin.name] = nil self.plugins[plugin.name] = nil
@ -198,36 +202,29 @@ end
---@param new LazyPlugin ---@param new LazyPlugin
---@return LazyPlugin ---@return LazyPlugin
function Spec:merge(old, new) function Spec:merge(old, new)
local is_dep = old._.dep and new._.dep 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 ---@diagnostic disable-next-line: no-unknown
for k, v in pairs(new) do for _, value in ipairs(old[prop]) do
if k == "_" then props[#props + 1] = value
elseif old[k] ~= nil and old[k] ~= v then end
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 ---@diagnostic disable-next-line: no-unknown
old[k] = values for _, value in ipairs(new[prop]) do
elseif k == "config" or k == "priority" then if not vim.tbl_contains(props, value) then
old[k] = v props[#props + 1] = value
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 end
end 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 ---@diagnostic disable-next-line: no-unknown
old[k] = v new[prop] = props
end end
end end
old._.dep = is_dep new._.super = old
return old setmetatable(new, { __index = old })
return new
end end
function M.update_state() function M.update_state()

View File

@ -31,7 +31,51 @@ function M.check()
vim.health.report_ok("packer_compiled.lua not found") vim.health.report_ok("packer_compiled.lua not found")
end end
local valid = { local spec = Config.spec
for _, plugin in pairs(spec.plugins) do
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:")
for _, notif in ipairs(spec.notifs) do
local lines = vim.split(notif.msg, "\n")
for _, line in ipairs(lines) do
if notif.level == vim.log.levels.ERROR then
vim.health.report_error(line)
else
vim.health.report_warn(line)
end
end
end
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, 1,
"name", "name",
"url", "url",
@ -57,29 +101,5 @@ function M.check()
"cond", "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
end
if #spec.notifs > 0 then
vim.health.report_error("Issues were reported when loading your specs:")
for _, notif in ipairs(spec.notifs) do
local lines = vim.split(notif.msg, "\n")
for _, line in ipairs(lines) do
if notif.level == vim.log.levels.ERROR then
vim.health.report_error(line)
else
vim.health.report_warn(line)
end
end
end
end
end
return M return M

View File

@ -13,6 +13,7 @@
---@field kind? LazyPluginKind ---@field kind? LazyPluginKind
---@field dep? boolean True if this plugin is only in the spec as a dependency ---@field dep? boolean True if this plugin is only in the spec as a dependency
---@field cond? boolean ---@field cond? boolean
---@field super? LazyPlugin
---@class LazyPluginHooks ---@class LazyPluginHooks
---@field init? fun(LazyPlugin) Will always be run ---@field init? fun(LazyPlugin) Will always be run