Skip to content

Commit

Permalink
feat(plugins): Given an optional plugin, conditionally discard deps (#…
Browse files Browse the repository at this point in the history
…947)

* deps_of_all_optional: First, refactor the code responsible for disabling unneeded deps to be more generic

* deps_of_all_optional: Second, also disable unneeded deps from plugins marked as all optional

* deps_of_all_optional: add tests proving unneeded optional deps are now also discarded

* deps_of_all_optional: forgot return type

---------

Co-authored-by: abeldekat <abel@nomail.com>
  • Loading branch information
abeldekat and abeldekat committed Jul 22, 2023
1 parent af4d24b commit e7334d8
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 24 deletions.
70 changes: 46 additions & 24 deletions lua/lazy/core/plugin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,31 @@ function Spec:warn(msg)
self:log(msg, vim.log.levels.WARN)
end

---@param gathered_deps string[]
---@param dep_of table<string,string[]>
---@param on_disable fun(string):nil
function Spec:fix_dependencies(gathered_deps, dep_of, on_disable)
local function should_disable(dep_name)
for _, parent in ipairs(dep_of[dep_name] or {}) do
if self.plugins[parent] then
return false
end
end
return true
end

for _, dep_name in ipairs(gathered_deps) do
-- only check if the plugin is still enabled and it is a dep
if self.plugins[dep_name] and self.plugins[dep_name]._.dep then
-- check if the dep is still used by another plugin
if should_disable(dep_name) then
-- disable the dep when no longer needed
on_disable(dep_name)
end
end
end
end

function Spec:fix_cond()
for _, plugin in pairs(self.plugins) do
local cond = plugin.cond
Expand All @@ -159,7 +184,9 @@ function Spec:fix_cond()
end
end

---@return string[]
function Spec:fix_optional()
local all_optional_deps = {}
if not self.optional then
---@param plugin LazyPlugin
local function all_optional(plugin)
Expand All @@ -170,9 +197,13 @@ function Spec:fix_optional()
for _, plugin in pairs(self.plugins) do
if plugin.optional and all_optional(plugin) then
self.plugins[plugin.name] = nil
if plugin.dependencies then
vim.list_extend(all_optional_deps, plugin.dependencies)
end
end
end
end
return all_optional_deps
end

function Spec:fix_disabled()
Expand All @@ -183,15 +214,16 @@ function Spec:fix_disabled()
end
end

self:fix_optional()
self:fix_cond()

---@type table<string,string[]> plugin to parent plugin
local dep_of = {}

---@type string[] dependencies of disabled plugins
local disabled_deps = {}

---@type string[] dependencies of plugins that are completely optional
local all_optional_deps = self:fix_optional()
self:fix_cond()

for _, plugin in pairs(self.plugins) do
local enabled = not (plugin.enabled == false or (type(plugin.enabled) == "function" and not plugin.enabled()))
if enabled then
Expand All @@ -209,27 +241,17 @@ function Spec:fix_disabled()
end
end

-- check deps of disabled plugins
for _, dep in ipairs(disabled_deps) do
-- only check if the plugin is still enabled and it is a dep
if self.plugins[dep] and self.plugins[dep]._.dep then
-- check if the dep is still used by another plugin
local keep = false
for _, parent in ipairs(dep_of[dep] or {}) do
if self.plugins[parent] then
keep = true
break
end
end
-- disable the dep when no longer needed
if not keep then
local plugin = self.plugins[dep]
plugin._.kind = "disabled"
self.plugins[plugin.name] = nil
self.disabled[plugin.name] = plugin
end
end
end
-- fix deps of plugins that are completely optional
self:fix_dependencies(all_optional_deps, dep_of, function(dep_name)
self.plugins[dep_name] = nil
end)
-- fix deps of disabled plugins
self:fix_dependencies(disabled_deps, dep_of, function(dep_name)
local plugin = self.plugins[dep_name]
plugin._.kind = "disabled"
self.plugins[plugin.name] = nil
self.disabled[plugin.name] = plugin
end)
end

---@param msg string
Expand Down
19 changes: 19 additions & 0 deletions tests/core/plugin_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,25 @@ describe("plugin spec opt", function()
end
end
end)

it("handles the optional keyword", function()
local tests = {
[{ { "foo/bax" }, { "foo/bar", optional = true, dependencies = "foo/dep1" } }] = false,
[{ { "foo/bax", dependencies = "foo/dep1" }, { "foo/bar", optional = true, dependencies = "foo/dep1" } }] = true,
}
for test, ret in pairs(tests) do
local spec = Plugin.Spec.new(test)
assert(#spec.notifs == 0)
assert(spec.plugins.bax)
assert(not spec.plugins.bar)
assert(#spec.disabled == 0)
if ret then
assert(spec.plugins.dep1)
else
assert(not spec.plugins.opt1)
end
end
end)
end)

describe("plugin opts", function()
Expand Down

0 comments on commit e7334d8

Please sign in to comment.