diff --git a/components/infobox/commons/infobox.lua b/components/infobox/commons/infobox.lua index 7b22fb4e424..cc2ed123525 100644 --- a/components/infobox/commons/infobox.lua +++ b/components/infobox/commons/infobox.lua @@ -9,9 +9,12 @@ local Array = require('Module:Array') local Class = require('Module:Class') local Logic = require('Module:Logic') +local Lua = require('Module:Lua') local Variables = require('Module:Variables') local WarningBox = require('Module:WarningBox') +local Widget = Lua.import('Module:Widget') + ---@class Infobox ---@field frame Frame? ---@field root Html? @@ -79,9 +82,7 @@ end ---@return Html function Infobox:build(widgets) for _, widget in ipairs(widgets) do - if widget == nil or widget['is_a'] == nil then - error('Infobox:build can only accept Widgets') - end + assert(Class.instanceOf(widget, Widget), 'Infobox:build can only accept Widgets') self.content:node(widget:tryMake(self.injector)) end diff --git a/components/prize_pool/commons/prize_pool_base.lua b/components/prize_pool/commons/prize_pool_base.lua index 5156ade16d4..eddfccdd239 100644 --- a/components/prize_pool/commons/prize_pool_base.lua +++ b/components/prize_pool/commons/prize_pool_base.lua @@ -919,7 +919,7 @@ end ---@param widgetInjector WidgetInjector An instance of a class that implements the WidgetInjector interface ---@return self function BasePrizePool:setWidgetInjector(widgetInjector) - assert(widgetInjector:is_a(WidgetInjector), 'setWidgetInjector: Not a Widget Injector') + assert(Class.instanceOf(widgetInjector, WidgetInjector), 'setWidgetInjector: Not a Widget Injector') self._widgetInjector = widgetInjector return self end @@ -928,7 +928,7 @@ end ---@param lpdbInjector LpdbInjector An instance of a class that implements the LpdbInjector interface ---@return self function BasePrizePool:setLpdbInjector(lpdbInjector) - assert(lpdbInjector:is_a(LpdbInjector), 'setLpdbInjector: Not an LPDB Injector') + assert(Class.instanceOf(lpdbInjector, LpdbInjector), 'setLpdbInjector: Not an LPDB Injector') self._lpdbInjector = lpdbInjector return self end diff --git a/components/squad/commons/squad_row.lua b/components/squad/commons/squad_row.lua index 30f29f29a2d..0c51ad54c3b 100644 --- a/components/squad/commons/squad_row.lua +++ b/components/squad/commons/squad_row.lua @@ -22,7 +22,7 @@ local RoleIcons = { sub = Icon.makeIcon{iconName = 'substitute', hover = 'Substitute'}, } ----@class SquadRow +---@class SquadRow: BaseClass ---@operator call(ModelRow): SquadRow ---@field children Widget[] ---@field model ModelRow diff --git a/components/widget/widget.lua b/components/widget/widget.lua index 28bc9cf88d6..6ccd37b692d 100644 --- a/components/widget/widget.lua +++ b/components/widget/widget.lua @@ -54,7 +54,7 @@ function Widget:tryChildren(injector) children = self:makeChildren(injector) or {} end return Array.map(children, function(child) - if type(child) == 'table' and type(child['is_a']) == 'function' and child:is_a(Widget) then + if Class.instanceOf(child, Widget) then ---@cast child Widget return Logic.tryOrElseLog( function() return child:tryMake(injector) end, diff --git a/standard/class.lua b/standard/class.lua index bb7fc56d20d..0065995560e 100644 --- a/standard/class.lua +++ b/standard/class.lua @@ -6,10 +6,6 @@ -- Please see https://github.com/Liquipedia/Lua-Modules to contribute -- ---- --- @author Vogan for Liquipedia --- - local Arguments = require('Module:Arguments') local Class = {} @@ -18,7 +14,8 @@ Class.PRIVATE_FUNCTION_SPECIFIER = '_' ---@class BaseClass ---@operator call:self ----@field is_a fun(self, BaseClass):boolean +---@field is_a fun(self, class: BaseClass):boolean #deprecated +---@field init fun(self, ...) function Class.new(base, init) local instance = {} @@ -59,16 +56,9 @@ function Class.new(base, init) return Class.export(instance, options) end - instance.is_a = function(self, class) - local m = getmetatable(self) - while m do - if m == class then - return true - end - m = m._base - end - return false - end + ---@deprecated + instance.is_a = Class.instanceOf + setmetatable(instance, metatable) return instance end @@ -159,4 +149,18 @@ function Class._frameToArgs(frame, options) return (Table.isNotEmpty(namedArgs) and namedArgs or nil), indexedArgs end +---@param instance any +---@param class BaseClass +---@return boolean +function Class.instanceOf(instance, class) + local metatable = getmetatable(instance) + while metatable do + if metatable == class then + return true + end + metatable = metatable._base + end + return false +end + return Class diff --git a/standard/condition.lua b/standard/condition.lua index 3ff8f44371b..0ee410c05b4 100644 --- a/standard/condition.lua +++ b/standard/condition.lua @@ -34,7 +34,7 @@ local ConditionTree = Class.new(_ConditionNode, function ConditionTree:add(node) if not node then return self - elseif node.is_a ~= nil and node:is_a(_ConditionNode) then + elseif Class.instanceOf(node, _ConditionNode) then table.insert(self._nodes, node) else -- List of nodes @@ -50,7 +50,7 @@ function ConditionTree:toString() assert(self.booleanOperator ~= nil) return table.concat(Array.map(self._nodes, function(node) - if node:is_a(ConditionTree) then + if Class.instanceOf(node, ConditionTree) then return String.interpolate('(${node})', {node = node:toString()}) end @@ -66,7 +66,6 @@ end ---@field name ColumnName ---@field comparator lpdbComparator ---@field value string|number ----@field is_a function local ConditionNode = Class.new(_ConditionNode, function(self, name, comparator, value) self.name = name diff --git a/standard/error.lua b/standard/error.lua index da927d75e6d..18fe7125890 100644 --- a/standard/error.lua +++ b/standard/error.lua @@ -66,10 +66,7 @@ end) ---@param error Error ---@return boolean function Error.isError(error) - return type(error) == 'table' - and type(error.is_a) == 'function' - and error:is_a(Error) - and type(error.message) == 'string' + return Class.instanceOf(error, Error) and type(error.message) == 'string' end function Error:__tostring() diff --git a/standard/links_stream.lua b/standard/links_stream.lua index 33f97d41fa7..6da24c7a930 100644 --- a/standard/links_stream.lua +++ b/standard/links_stream.lua @@ -222,9 +222,7 @@ local StreamKey = Class.new( ) StreamLinks.StreamKey = StreamKey ----@param tbl string ----@param languageCode string ----@param index integer +---@overload fun(self, tbl: string, languageCode: string, index: integer): StreamKey ---@overload fun(self, tbl: StreamKey): StreamKey ---@overload fun(self, tbl: string): StreamKey function StreamKey:new(tbl, languageCode, index) @@ -236,6 +234,7 @@ function StreamKey:new(tbl, languageCode, index) index = tbl.index -- All three parameters are supplied elseif languageCode and index then + ---@cast tbl -StreamKey platform = tbl elseif type(tbl) == 'string' then local components = mw.text.split(tbl, '_', true) @@ -251,8 +250,8 @@ function StreamKey:new(tbl, languageCode, index) end end - self.platform = platform --[[@as string]] - self.languageCode = languageCode --[[@as string]] + self.platform = platform + self.languageCode = languageCode self.index = tonumber(index) --[[@as integer]] self:_isValid() self.languageCode = self.languageCode:lower() @@ -298,14 +297,10 @@ function StreamKey:_isValid() return true end ----@param value StreamKey ----@return true +---@overload fun(value: StreamKey): true ---@overload fun(value: any): false function StreamKey._isStreamKey(value) - if type(value) == 'table' and type(value.is_a) == 'function' and value:is_a(StreamKey) then - return true - end - return false + return Class.instanceOf(value, StreamKey) end StreamKey.__tostring = StreamKey.toString diff --git a/standard/result_or_error.lua b/standard/result_or_error.lua index cac5c5cfaf5..0043a35d3e4 100644 --- a/standard/result_or_error.lua +++ b/standard/result_or_error.lua @@ -66,12 +66,12 @@ end ---@return boolean function ResultOrError:isResult() - return self:is_a(ResultOrError.Result) + return Class.instanceOf(self, ResultOrError.Result) end ---@return boolean function ResultOrError:isError() - return self:is_a(ResultOrError.Error) + return Class.instanceOf(self, ResultOrError.Error) end --[[ @@ -136,9 +136,7 @@ function ResultOrError.try(f, originalError) xpcall( function() local result = f() - local isResultOrError = type(result) == 'table' - and type(result.is_a) == 'function' - and result:is_a(ResultOrError) + local isResultOrError = Class.instanceOf(result, ResultOrError) resultOrError = isResultOrError and result or ResultOrError.Result(result)