Skip to content

Commit

Permalink
feat: rewrite of spec resolving
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Jun 24, 2024
1 parent 8d35e60 commit 75ffe56
Show file tree
Hide file tree
Showing 9 changed files with 555 additions and 426 deletions.
159 changes: 159 additions & 0 deletions lua/lazy/core/fragments.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
local Config = require("lazy.core.config")

local M = {}

M._fid = 0

local function next_id()
M._fid = M._fid + 1
return M._fid
end

---@class LazyFragments
---@field fragments table<number, LazyFragment>
---@field frag_stack number[]
---@field dep_stack number[]
---@field dirty table<number, boolean>
---@field spec LazySpecLoader
local F = {}

---@param spec LazySpecLoader
---@return LazyFragments
function M.new(spec)
local self = setmetatable({}, { __index = F })
self.fragments = {}
self.frag_stack = {}
self.dep_stack = {}
self.spec = spec
self.dirty = {}
return self
end

---@param id number
function F:get(id)
return self.fragments[id]
end

---@param id number
function F:del(id)
-- del fragment
local fragment = self.fragments[id]
if not fragment then
return
end

self.dirty[id] = true

-- remove from parent
local pid = fragment.pid
if pid then
local parent = self.fragments[pid]
if parent.frags then
---@param fid number
parent.frags = vim.tbl_filter(function(fid)
return fid ~= id
end, parent.frags)
end
if parent.deps then
---@param fid number
parent.deps = vim.tbl_filter(function(fid)
return fid ~= id
end, parent.deps)
end
self.dirty[pid] = true
end

-- remove children
if fragment.frags then
for _, fid in ipairs(fragment.frags) do
self:del(fid)
end
end

self.fragments[id] = nil
end

---@param plugin LazyPluginSpec
function F:add(plugin)
local id = next_id()

local pid = self.frag_stack[#self.frag_stack]

---@type LazyFragment
local fragment = {
id = id,
pid = pid,
name = plugin.name,
url = plugin.url,
dir = plugin.dir,
spec = plugin --[[@as LazyPlugin]],
}

-- short url / ref
if plugin[1] then
local slash = plugin[1]:find("/", 1, true)
if slash then
local prefix = plugin[1]:sub(1, 4)
if prefix == "http" or prefix == "git@" then
fragment.url = fragment.url or plugin[1]
else
fragment.name = fragment.name or plugin[1]:sub(slash + 1)
fragment.url = fragment.url or Config.options.git.url_format:format(plugin[1])
end
else
fragment.name = fragment.name or plugin[1]
end
end

-- name
fragment.name = fragment.name
or fragment.url and self.spec.get_name(fragment.url)
or fragment.dir and self.spec.get_name(fragment.dir)
if not fragment.name then
return self.spec:error("Invalid plugin spec " .. vim.inspect(plugin))
end

if type(plugin.config) == "table" then
self.spec:warn(
"{" .. fragment.name .. "}: setting a table to `Plugin.config` is deprecated. Please use `Plugin.opts` instead"
)
---@diagnostic disable-next-line: assign-type-mismatch
plugin.opts = plugin.config
plugin.config = nil
end

self.fragments[id] = fragment

-- add to parent
if pid then
local parent = self.fragments[pid]
parent.frags = parent.frags or {}
table.insert(parent.frags, id)
end

-- add to parent's deps
local did = self.dep_stack[#self.dep_stack]
if did and did == pid then
fragment.dep = true
local parent = self.fragments[did]
parent.deps = parent.deps or {}
table.insert(parent.deps, id)
end

table.insert(self.frag_stack, id)
-- dependencies
if plugin.dependencies then
table.insert(self.dep_stack, id)
self.spec:normalize(plugin.dependencies)
table.remove(self.dep_stack)
end
-- child specs
if plugin.specs then
self.spec:normalize(plugin.specs)
end
table.remove(self.frag_stack)

return fragment
end

return M
8 changes: 5 additions & 3 deletions lua/lazy/core/loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function M.startup()
M.source(vim.env.VIMRUNTIME .. "/filetype.lua")

-- backup original rtp
local rtp = vim.opt.rtp:get()
local rtp = vim.opt.rtp:get() --[[@as string[] ]]

-- 1. run plugin init
Util.track({ start = "init" })
Expand Down Expand Up @@ -136,15 +136,17 @@ function M.startup()
if not path:find("after/?$") then
-- these paths don't will already have their ftdetect ran,
-- by sourcing filetype.lua above, so skip them
M.did_ftdetect[path] = true
M.did_ftdetect[path] = path
M.packadd(path)
end
end
Util.track()

-- 4. load after plugins
Util.track({ start = "after" })
for _, path in ipairs(vim.opt.rtp:get()) do
for _, path in
ipairs(vim.opt.rtp:get() --[[@as string[] ]])
do
if path:find("after/?$") then
M.source_runtime(path, "plugin")
end
Expand Down
Loading

0 comments on commit 75ffe56

Please sign in to comment.