Skip to content

Commit

Permalink
refactor(standard): add non-instanced is_a/instanceOf method (#4722)
Browse files Browse the repository at this point in the history
* refactor(standard): add non-instanced  is_a/instanceOf method

* fix typo

* this one can be changed too now that it exists

* remove old comment
  • Loading branch information
Rathoz authored Sep 17, 2024
1 parent 68428aa commit 5ce1047
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 45 deletions.
7 changes: 4 additions & 3 deletions components/infobox/commons/infobox.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions components/prize_pool/commons/prize_pool_base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion components/squad/commons/squad_row.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion components/widget/widget.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
34 changes: 19 additions & 15 deletions standard/class.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand All @@ -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 = {}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
5 changes: 2 additions & 3 deletions standard/condition.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand Down
5 changes: 1 addition & 4 deletions standard/error.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
17 changes: 6 additions & 11 deletions standard/links_stream.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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()
Expand Down Expand Up @@ -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

Expand Down
8 changes: 3 additions & 5 deletions standard/result_or_error.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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

--[[
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 5ce1047

Please sign in to comment.