From c02268ac6e6aab92249d020d75efc588bd9d24fa Mon Sep 17 00:00:00 2001
From: Folke Lemaitre <folke.lemaitre@gmail.com>
Date: Tue, 23 Jul 2024 17:24:33 +0200
Subject: [PATCH] feat(plugin): improve error handling and show better error
 message

---
 lua/lazy/core/plugin.lua | 41 ++++++++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/lua/lazy/core/plugin.lua b/lua/lazy/core/plugin.lua
index d121fdf..1aef7c7 100644
--- a/lua/lazy/core/plugin.lua
+++ b/lua/lazy/core/plugin.lua
@@ -146,33 +146,43 @@ function Spec:import(spec)
 
   local imported = 0
 
-  ---@type (string|(fun():LazyPluginSpec))[]
+  ---@type {modname: string, load: fun():(LazyPluginSpec?, string?)}[]
   local modspecs = {}
 
   if type(import) == "string" then
     Util.lsmod(import, function(modname, modpath)
-      modspecs[#modspecs + 1] = modname
-      package.preload[modname] = function()
-        return loadfile(modpath)()
-      end
+      modspecs[#modspecs + 1] = {
+        modname = modname,
+        load = function()
+          local mod, err = loadfile(modpath)
+          if mod then
+            return mod()
+          else
+            return nil, err
+          end
+        end,
+      }
+    end)
+    table.sort(modspecs, function(a, b)
+      return a.modname < b.modname
     end)
-    table.sort(modspecs)
   else
-    modspecs = { spec.import }
+    modspecs = { modname = import_name, load = spec.import }
   end
 
   for _, modspec in ipairs(modspecs) do
     imported = imported + 1
-    local modname = type(modspec) == "string" and modspec or import_name
+    local modname = modspec.modname
     Util.track({ import = modname })
     self.importing = modname
     -- unload the module so we get a clean slate
     ---@diagnostic disable-next-line: no-unknown
     package.loaded[modname] = nil
     Util.try(function()
-      local mod = type(modspec) == "function" and modspec() or require(modspec)
-      if type(mod) ~= "table" then
-        self.importing = nil
+      local mod, err = modspec.load()
+      if err then
+        self:error("Failed to load `" .. modname .. "`:\n" .. err)
+      elseif type(mod) ~= "table" then
         return self:error(
           "Invalid spec module: `"
             .. modname
@@ -180,18 +190,17 @@ function Spec:import(spec)
             .. type(mod)
             .. "` was returned instead"
         )
+      else
+        self:normalize(mod)
       end
-      self:normalize(mod)
-      self.importing = nil
-      Util.track()
     end, {
       msg = "Failed to load `" .. modname .. "`",
       on_error = function(msg)
         self:error(msg)
-        self.importing = nil
-        Util.track()
       end,
     })
+    self.importing = nil
+    Util.track()
   end
   if imported == 0 then
     self:error("No specs found for module " .. spec.import)