Error handling overhaul

This commit is contained in:
Pablo Ariel Mayobre 2023-02-14 18:14:24 -03:00
parent 743d662ef9
commit 892f4d4700
6 changed files with 57 additions and 28 deletions

View file

@ -16,19 +16,19 @@ Component.__mt = {
-- @treturn Component A new ComponentClass
function Component.new(name, populate)
if (type(name) ~= "string") then
error("bad argument #1 to 'Component.new' (string expected, got "..type(name)..")", 2)
Utils.error(2, "bad argument #1 to 'Component.new' (string expected, got %s)", type(name))
end
if (string.match(name, Components.__REJECT_MATCH) ~= "") then
error("bad argument #1 to 'Component.new' (Component names can't start with '"..Components.__REJECT_PREFIX.."', got "..name..")", 2)
Utils.error(2, "bad argument #1 to 'Component.new' (Component names can't start with '%s', got %s)", Components.__REJECT_PREFIX, name)
end
if (rawget(Components, name)) then
error("bad argument #1 to 'Component.new' (ComponentClass with name '"..name.."' was already registerd)", 2) -- luacheck: ignore
Utils.error(2, "bad argument #1 to 'Component.new' (ComponentClass with name '%s' was already registerd)", name) -- luacheck: ignore
end
if (type(populate) ~= "function" and type(populate) ~= "nil") then
error("bad argument #1 to 'Component.new' (function/nil expected, got "..type(populate)..")", 2)
Utils.error(2, "bad argument #1 to 'Component.new' (function/nil expected, got %s)", type(populate))
end
local componentClass = setmetatable({

View file

@ -18,7 +18,7 @@ Entity.__mt = {
-- @treturn Entity A new Entity
function Entity.new(world)
if (world ~= nil and not Type.isWorld(world)) then
error("bad argument #1 to 'Entity.new' (world/nil expected, got "..type(world)..")", 2)
Utils.error(2, "bad argument #1 to 'Entity.new' (world/nil expected, got %s)", type(world))
end
local e = setmetatable({
@ -68,7 +68,7 @@ function Entity:give(name, ...)
local ok, componentClass = Components.try(name)
if not ok then
error("bad argument #1 to 'Entity:get' ("..componentClass..")", 2)
Utils.error(2, "bad argument #1 to 'Entity:get' (%s)", componentClass)
end
give(self, name, componentClass, ...)
@ -85,7 +85,7 @@ function Entity:ensure(name, ...)
local ok, componentClass = Components.try(name)
if not ok then
error("bad argument #1 to 'Entity:ensure' ("..componentClass..")", 2)
Utils.error(2, "bad argument #1 to 'Entity:ensure' (%s)", componentClass)
end
if self[name] then
@ -104,7 +104,7 @@ function Entity:remove(name)
local ok, componentClass = Components.try(name)
if not ok then
error("bad argument #1 to 'Entity:remove' ("..componentClass..")", 2)
Utils.error(2, "bad argument #1 to 'Entity:remove' (%s)", componentClass)
end
remove(self, name)
@ -118,7 +118,7 @@ end
-- @treturn Entity self
function Entity:assemble(assemblage, ...)
if type(assemblage) ~= "function" then
error("bad argument #1 to 'Entity:assemble' (function expected, got "..type(assemblage)..")")
Utils.error(2, "bad argument #1 to 'Entity:assemble' (function expected, got %s)", type(assemblage))
end
assemblage(self, ...)
@ -154,7 +154,7 @@ function Entity:has(name)
local ok, componentClass = Components.try(name)
if not ok then
error("bad argument #1 to 'Entity:has' ("..componentClass..")", 2)
Utils.error(2, "bad argument #1 to 'Entity:has' (%s)", componentClass)
end
return self[name] and true or false
@ -167,7 +167,7 @@ function Entity:get(name)
local ok, componentClass = Components.try(name)
if not ok then
error("bad argument #1 to 'Entity:get' ("..componentClass..")", 2)
Utils.error(2, "bad argument #1 to 'Entity:get' (%s)", componentClass)
end
return self[name]
@ -219,7 +219,7 @@ function Entity:deserialize(data)
local componentData = data[i]
if (not Components.has(componentData.__name)) then
error("bad argument #1 to 'Entity:deserialize' (ComponentClass '"..tostring(componentData.__name).."' wasn't yet loaded)") -- luacheck: ignore
Utils.error(2, "bad argument #1 to 'Entity:deserialize' (ComponentClass '%s' wasn't yet loaded)", tostring(componentData.__name)) -- luacheck: ignore
end
local componentClass = Components[componentData.__name]

View file

@ -6,6 +6,7 @@ local PATH = (...):gsub('%.[^%.]+$', '')
local List = require(PATH..".list")
local Type = require(PATH..".type")
local Utils = require(PATH..".utils")
local Components = require(PATH..".components")
@ -20,18 +21,18 @@ Filter.__mt = {
-- @tparam onComponent Optional function, called when a component is valid.
function Filter.validate (name, def, onComponent)
if type(def) ~= 'table' then
error("invalid component list for filter '"..name.."' (table expected, got "..type(def)..")", 3)
Utils.error(3, "invalid component list for filter '%s' (table expected, got %s)", name, type(def))
end
if not onComponent and def.constructor and not Type.isCallable(def.constructor) then
error("invalid pool constructor (callable expected, got "..type(def.constructor)..")", 3)
Utils.error(3, "invalid pool constructor for filter '%s' (callable expected, got %s)", name, type(def.constructor))
end
for n, component in ipairs(def) do
local ok, err, reject = Components.try(component, true)
if not ok then
error("invalid component for filter '"..name.."' at position #"..n.." ("..err..")", 3)
Utils.error(3, "invalid component for filter '%s' at position #%d (%s)", name, n, err)
end
if onComponent then
@ -61,14 +62,38 @@ function Filter.parse (name, def)
return required, rejected
end
local REQUIRED_METHODS = {"add", "remove", "has", "clear"}
local VALID_POOL_TYPES = {table=true, userdata=true, lightuserdata=true, cdata=true}
function Filter.isValidPool (name, pool)
local poolType = type(pool)
--Check that pool is not nil
if not VALID_POOL_TYPES[poolType] then
Utils.error(3, "invalid value returned by pool '%s' constructor (table expected, got %s).", name, type(pool))
end
--Check if methods are callables
for _, method in ipairs(REQUIRED_METHODS) do
if not Type.isCallable(pool[method]) then
Utils.error(3, "invalid :%s method on pool '%s' (callable expected, got %s).", method, name, type(pool[method]))
end
end
end
--- Creates a new Filter
-- @string name Name for the Filter.
-- @tparam table definition Table containing the Filter Definition
-- @treturn Filter The new Filter
-- @treturn Pool The associated Pool
function Filter.new (name, def)
local constructor = def.constructor or List
local pool = constructor(def)
local pool
if def.constructor then
pool = def.constructor(def)
Filter.isValidPool(name, pool)
else
pool = List()
end
local required, rejected = Filter.parse(name, def)

View file

@ -50,7 +50,7 @@ System.mt = {
function System.new(definition)
for name, def in pairs(definition) do
if type(name) ~= 'string' then
error("invalid name for filter (string key expected, got "..type(name)..")", 2)
Utils.error(2, "invalid name for filter (string key expected, got %s)", type(name))
end
Filter.validate(name, def)

View file

@ -3,6 +3,10 @@
local Utils = {}
function Utils.error(level, str, ...)
error(string.format(str, ...), level + 1)
end
--- Does a shallow copy of a table and appends it to a target table.
-- @param orig Table to copy
-- @param target Table to append to
@ -22,13 +26,13 @@ end
-- @treturn table The namespace table
function Utils.loadNamespace(pathOrFiles, namespace)
if type(pathOrFiles) ~= "string" and type(pathOrFiles) ~= "table" then
error("bad argument #1 to 'loadNamespace' (string/table of strings expected, got "..type(pathOrFiles)..")", 2)
Utils.error(2, "bad argument #1 to 'loadNamespace' (string/table of strings expected, got %s)", type(pathOrFiles))
end
if type(pathOrFiles) == "string" then
local info = love.filesystem.getInfo(pathOrFiles) -- luacheck: ignore
if info == nil or info.type ~= "directory" then
error("bad argument #1 to 'loadNamespace' (path '"..pathOrFiles.."' not found)", 2)
Utils.error(2, "bad argument #1 to 'loadNamespace' (path '%s' not found)", pathOrFiles)
end
local files = love.filesystem.getDirectoryItems(pathOrFiles)
@ -50,7 +54,7 @@ function Utils.loadNamespace(pathOrFiles, namespace)
elseif type(pathOrFiles) == "table" then
for _, path in ipairs(pathOrFiles) do
if type(path) ~= "string" then
error("bad argument #2 to 'loadNamespace' (string/table of strings expected, got table containing "..type(path)..")", 2) -- luacheck: ignore
Utils.error(2, "bad argument #2 to 'loadNamespace' (string/table of strings expected, got table containing %s)", type(path)) -- luacheck: ignore
end
local name = path

View file

@ -52,7 +52,7 @@ end
-- @treturn World self
function World:addEntity(e)
if not Type.isEntity(e) then
error("bad argument #1 to 'World:addEntity' (Entity expected, got "..type(e)..")", 2)
Utils.error(2, "bad argument #1 to 'World:addEntity' (Entity expected, got %s)", type(e))
end
if e.__world then
@ -70,7 +70,7 @@ end
-- @treturn World self
function World:removeEntity(e)
if not Type.isEntity(e) then
error("bad argument #1 to 'World:removeEntity' (Entity expected, got "..type(e)..")", 2)
Utils.error(2, "bad argument #1 to 'World:removeEntity' (Entity expected, got %s)", type(e))
end
self.__removed:add(e)
@ -207,7 +207,7 @@ function World:addSystem(systemClass)
local ok, err = tryAddSystem(self, systemClass)
if not ok then
error("bad argument #1 to 'World:addSystem' ("..err..")", 2)
Utils.error(2, "bad argument #1 to 'World:addSystem' (%s)", err)
end
return self
@ -225,7 +225,7 @@ function World:addSystems(...)
local ok, err = tryAddSystem(self, systemClass)
if not ok then
error("bad argument #"..i.." to 'World:addSystems' ("..err..")", 2)
Utils.error(2, "bad argument #%d to 'World:addSystems' (%s)", i, err)
end
end
@ -237,7 +237,7 @@ end
-- @treturn boolean
function World:hasSystem(systemClass)
if not Type.isSystemClass(systemClass) then
error("bad argument #1 to 'World:getSystem' (systemClass expected, got "..type(systemClass)..")", 2)
Utils.error(2, "bad argument #1 to 'World:hasSystem' (SystemClass expected, got %s)", type(systemClass))
end
return self.__systemLookup[systemClass] and true or false
@ -248,7 +248,7 @@ end
-- @treturn System System to get
function World:getSystem(systemClass)
if not Type.isSystemClass(systemClass) then
error("bad argument #1 to 'World:getSystem' (systemClass expected, got "..type(systemClass)..")", 2)
Utils.error(2, "bad argument #1 to 'World:getSystem' (SystemClass expected, got %s)", type(systemClass))
end
return self.__systemLookup[systemClass]
@ -261,7 +261,7 @@ end
-- @treturn World self
function World:emit(functionName, ...)
if not functionName or type(functionName) ~= "string" then
error("bad argument #1 to 'World:emit' (String expected, got "..type(functionName)..")")
Utils.error(2, "bad argument #1 to 'World:emit' (String expected, got %s)", type(functionName))
end
local shouldFlush = self.__emitSDepth == 0