start of error handling

This commit is contained in:
Michael Freno
2025-11-13 09:59:26 -05:00
parent da2e780267
commit 252cd37f3c

View File

@@ -22,6 +22,7 @@ local LayoutEngine = req("LayoutEngine")
local Renderer = req("Renderer") local Renderer = req("Renderer")
local EventHandler = req("EventHandler") local EventHandler = req("EventHandler")
local ScrollManager = req("ScrollManager") local ScrollManager = req("ScrollManager")
local ErrorHandler = req("ErrorHandler")
-- Extract utilities -- Extract utilities
local enums = utils.enums local enums = utils.enums
@@ -211,6 +212,52 @@ Public API methods to access internal state:
local Element = {} local Element = {}
Element.__index = Element Element.__index = Element
-- Validation helper functions
local function validateEnum(value, enumTable, propName, moduleName)
if value == nil then
return true
end
for _, validValue in pairs(enumTable) do
if value == validValue then
return true
end
end
-- Build list of valid options
local validOptions = {}
for _, v in pairs(enumTable) do
table.insert(validOptions, "'" .. v .. "'")
end
table.sort(validOptions)
ErrorHandler.error(moduleName or "Element", string.format("%s must be one of: %s. Got: '%s'", propName, table.concat(validOptions, ", "), tostring(value)))
end
local function validateRange(value, min, max, propName, moduleName)
if value == nil then
return true
end
if type(value) ~= "number" then
ErrorHandler.error(moduleName or "Element", string.format("%s must be a number, got %s", propName, type(value)))
end
if value < min or value > max then
ErrorHandler.error(moduleName or "Element", string.format("%s must be between %s and %s, got %s", propName, tostring(min), tostring(max), tostring(value)))
end
return true
end
local function validateType(value, expectedType, propName, moduleName)
if value == nil then
return true
end
local actualType = type(value)
if actualType ~= expectedType then
ErrorHandler.error(moduleName or "Element", string.format("%s must be %s, got %s", propName, expectedType, actualType))
end
return true
end
---@param props ElementProps ---@param props ElementProps
---@return Element ---@return Element
function Element.new(props) function Element.new(props)
@@ -292,7 +339,10 @@ function Element.new(props)
self.passwordMode = props.passwordMode or false self.passwordMode = props.passwordMode or false
-- Validate property combinations: passwordMode disables multiline -- Validate property combinations: passwordMode disables multiline
if self.passwordMode then if self.passwordMode and props.multiline then
ErrorHandler.warn("Element", "passwordMode is enabled, multiline will be disabled")
self.multiline = false
elseif self.passwordMode then
self.multiline = false self.multiline = false
end end
@@ -375,6 +425,11 @@ function Element.new(props)
} }
self.borderColor = props.borderColor or Color.new(0, 0, 0, 1) self.borderColor = props.borderColor or Color.new(0, 0, 0, 1)
self.backgroundColor = props.backgroundColor or Color.new(0, 0, 0, 0) self.backgroundColor = props.backgroundColor or Color.new(0, 0, 0, 0)
-- Validate and set opacity
if props.opacity ~= nil then
validateRange(props.opacity, 0, 1, "opacity")
end
self.opacity = props.opacity or 1 self.opacity = props.opacity or 1
-- Handle cornerRadius (can be number or table) -- Handle cornerRadius (can be number or table)
@@ -415,13 +470,28 @@ function Element.new(props)
self.text = self._textBuffer self.text = self._textBuffer
end end
-- Validate and set textAlign
if props.textAlign then
validateEnum(props.textAlign, TextAlign, "textAlign")
end
self.textAlign = props.textAlign or TextAlign.START self.textAlign = props.textAlign or TextAlign.START
-- Image properties -- Image properties
self.imagePath = props.imagePath self.imagePath = props.imagePath
self.image = props.image self.image = props.image
-- Validate objectFit
if props.objectFit then
local validObjectFit = { fill = "fill", contain = "contain", cover = "cover", ["scale-down"] = "scale-down", none = "none" }
validateEnum(props.objectFit, validObjectFit, "objectFit")
end
self.objectFit = props.objectFit or "fill" self.objectFit = props.objectFit or "fill"
self.objectPosition = props.objectPosition or "center center" self.objectPosition = props.objectPosition or "center center"
-- Validate and set imageOpacity
if props.imageOpacity ~= nil then
validateRange(props.imageOpacity, 0, 1, "imageOpacity")
end
self.imageOpacity = props.imageOpacity or 1 self.imageOpacity = props.imageOpacity or 1
-- Auto-load image if imagePath is provided -- Auto-load image if imagePath is provided
@@ -570,12 +640,12 @@ function Element.new(props)
-- Pixel units -- Pixel units
self.textSize = value self.textSize = value
else else
error("Unknown textSize unit: " .. unit) ErrorHandler.error("Element", "Unknown textSize unit: " .. unit)
end end
else else
-- Validate pixel textSize value -- Validate pixel textSize value
if props.textSize <= 0 then if props.textSize <= 0 then
error("textSize must be greater than 0, got: " .. tostring(props.textSize)) ErrorHandler.error("Element", "textSize must be greater than 0, got: " .. tostring(props.textSize))
end end
-- Pixel textSize value -- Pixel textSize value
@@ -925,6 +995,7 @@ function Element.new(props)
-- Track if positioning was explicitly set -- Track if positioning was explicitly set
if props.positioning then if props.positioning then
validateEnum(props.positioning, Positioning, "positioning")
self.positioning = props.positioning self.positioning = props.positioning
self._originalPositioning = props.positioning self._originalPositioning = props.positioning
self._explicitlyAbsolute = (props.positioning == Positioning.ABSOLUTE) self._explicitlyAbsolute = (props.positioning == Positioning.ABSOLUTE)
@@ -1119,6 +1190,26 @@ function Element.new(props)
end end
if self.positioning == Positioning.FLEX then if self.positioning == Positioning.FLEX then
-- Validate enum properties
if props.flexDirection then
validateEnum(props.flexDirection, FlexDirection, "flexDirection")
end
if props.flexWrap then
validateEnum(props.flexWrap, FlexWrap, "flexWrap")
end
if props.justifyContent then
validateEnum(props.justifyContent, JustifyContent, "justifyContent")
end
if props.alignItems then
validateEnum(props.alignItems, AlignItems, "alignItems")
end
if props.alignContent then
validateEnum(props.alignContent, AlignContent, "alignContent")
end
if props.justifySelf then
validateEnum(props.justifySelf, JustifySelf, "justifySelf")
end
self.flexDirection = props.flexDirection or FlexDirection.HORIZONTAL self.flexDirection = props.flexDirection or FlexDirection.HORIZONTAL
self.flexWrap = props.flexWrap or FlexWrap.NOWRAP self.flexWrap = props.flexWrap or FlexWrap.NOWRAP
self.justifyContent = props.justifyContent or JustifyContent.FLEX_START self.justifyContent = props.justifyContent or JustifyContent.FLEX_START