forked from Liquipedia/Lua-Modules
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclass.lua
More file actions
164 lines (141 loc) · 3.54 KB
/
Copy pathclass.lua
File metadata and controls
164 lines (141 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
---
-- @Liquipedia
-- wiki=commons
-- page=Module:Class
--
-- Please see https://github.com/Liquipedia/Lua-Modules to contribute
--
---
-- @author Vogan for Liquipedia
--
local Arguments = require('Module:Arguments')
local Class = {}
Class.PRIVATE_FUNCTION_SPECIFIER = '_'
function Class.new(base, init)
local instance = {}
if not init and type(base) == 'function' then
init = base
base = nil
elseif type(base) == 'table' then
for index, value in pairs(base) do
instance[index] = value
end
instance._base = base
end
instance.__index = instance
local metatable = {}
metatable.__call = function(class_tbl, ...)
local object = {}
setmetatable(object, instance)
-- Call constructors
if init and base and base.init then
-- If the base class has a constructor,
-- make sure to call that first
base.init(object, ...)
init(object, ...)
elseif init then
-- Else we just call our own
init(object, ...)
else
-- And in cases where we don't have one but the
-- base class does, call that one
if base and base.init then
base.init(object, ...)
end
end
return object
end
instance.init = init
instance.export = function(options)
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
setmetatable(instance, metatable)
return instance
end
---@generic T
---@param class T
---@param options ?table
---@return T
function Class.export(class, options)
for name, f in pairs(class) do
-- We only want to export functions, and only functions which are public (no underscore)
if (
type(f) == 'function' and
(not string.find(name, Class.PRIVATE_FUNCTION_SPECIFIER))
) then
class[name] = Class._wrapFunction(class[name], options)
end
end
return class
end
local Table = {}
-- Duplicate Table.isNotEmpty() here to avoid circular dependencies with Table
function Table.isNotEmpty(tbl)
-- luacheck: push ignore (Loop can be executed at most once)
for _ in pairs(tbl) do
return true
end
-- luacheck: pop
return false
end
---
-- Wrap the given function with an argument parses so that both wikicode and lua
-- arguments are accepted
--
function Class._wrapFunction(f, options)
options = options or {}
local alwaysRewriteArgs = options.trim
or options.removeBlanks
or options.valueFunc ~= nil
return function(...)
-- We cannot call getArgs with a spread operator when these are just lua
-- args, so we need to wrap it
local input = {...}
local frame = input[1]
local shouldRewriteArgs = alwaysRewriteArgs
or (
#input == 1
and type(frame) == 'table'
and type(frame.args) == 'table'
)
if shouldRewriteArgs then
local namedArgs, indexedArgs = Class._frameToArgs(frame, options)
if namedArgs then
return f(namedArgs, unpack(indexedArgs))
else
return f(unpack(indexedArgs))
end
else
return f(...)
end
end
end
--[[
Translates a frame object into arguments expected by a lua function.
]]
function Class._frameToArgs(frame, options)
local args = Arguments.getArgs(frame, options)
-- getArgs adds a metatable to the table. This breaks unpack. So we remove it.
-- We also add all named params to a special table, since unpack removes them.
local indexedArgs = {}
local namedArgs = {}
for key, value in pairs(args) do
if type(key) == 'number' then
indexedArgs[key] = value
else
namedArgs[key] = value
end
end
return (Table.isNotEmpty(namedArgs) and namedArgs or nil), indexedArgs
end
return Class