lenix 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +46 -2
- package/{bin → lint}/dist/lint.mjs +2 -2
- package/{bin/.eslint-preset.json → lint/lint-preset.json} +54 -18
- package/{bin → lint}/lint.mts +2 -2
- package/lua/LICENSE +21 -0
- package/lua/_dev/firstAttempt.lua +202 -0
- package/lua/_dev/secondAttempt.lua +166 -0
- package/lua/_dev/tests.lua +298 -0
- package/lua/index.lua +322 -0
- package/lua/lenix-0.1.0-1.rockspec +25 -0
- package/package.json +14 -10
- package/bin/Readme.md +0 -33
- /package/{bin → lint}/tsconfig.json +0 -0
- /package/{bin/mac-lua_modules.sh → lua/mac-lua-modules.sh} +0 -0
- /package/{dist → ts/dist}/fetch/index.d.ts +0 -0
- /package/{dist → ts/dist}/fetch/index.js +0 -0
- /package/{dist → ts/dist}/fxmanifest/fxmanifest.json +0 -0
- /package/{dist → ts/dist}/fxmanifest/index.d.ts +0 -0
- /package/{dist → ts/dist}/fxmanifest/index.js +0 -0
- /package/{dist → ts/dist}/index.d.ts +0 -0
- /package/{dist → ts/dist}/index.js +0 -0
- /package/{dist → ts/dist}/wait/index.d.ts +0 -0
- /package/{dist → ts/dist}/wait/index.js +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
--[[ These are the tests that we have tried to get working with Lua-OOP, if you have any suggestions or improvements, please let us know. ]]
|
|
2
|
+
|
|
3
|
+
local User = class({
|
|
4
|
+
name = {nil, false},
|
|
5
|
+
age = {nil, false},
|
|
6
|
+
constructor = function(self, super, name, age)
|
|
7
|
+
self.name = name
|
|
8
|
+
self.age = age
|
|
9
|
+
end
|
|
10
|
+
})
|
|
11
|
+
local u = User:new("Alice", 25)
|
|
12
|
+
assert(u.name == "Alice" and u.age == 25, "Test 1 failed")
|
|
13
|
+
local User = class({
|
|
14
|
+
password = {nil, true}, -- private
|
|
15
|
+
constructor = function(self, super, pwd)
|
|
16
|
+
self.password = pwd
|
|
17
|
+
end
|
|
18
|
+
})
|
|
19
|
+
local u = User:new("secret")
|
|
20
|
+
local ok = pcall(function() print(u.password) end)
|
|
21
|
+
assert(not ok, "Test 2 failed: private property accessible")
|
|
22
|
+
|
|
23
|
+
-- Test 3: Private property accessible internally
|
|
24
|
+
local User = class({
|
|
25
|
+
password = {nil, true},
|
|
26
|
+
getPassword = {function(self) return self.password end, false},
|
|
27
|
+
constructor = function(self, super, pwd)
|
|
28
|
+
self.password = pwd
|
|
29
|
+
end
|
|
30
|
+
})
|
|
31
|
+
local u = User:new("secret")
|
|
32
|
+
assert(u.getPassword() == "secret", "Test 3 failed")
|
|
33
|
+
local User = class({
|
|
34
|
+
count = {0, false, true}, -- static
|
|
35
|
+
name = {nil, false},
|
|
36
|
+
constructor = function(self, super, name)
|
|
37
|
+
self.name = name
|
|
38
|
+
end
|
|
39
|
+
})
|
|
40
|
+
User.count = 5
|
|
41
|
+
local u = User:new("Alice")
|
|
42
|
+
local ok = pcall(function() print(u.count) end)
|
|
43
|
+
assert(not ok, "Test 4 failed: static accessible on instance")
|
|
44
|
+
assert(User.count == 5, "Test 4 failed: static not on class")
|
|
45
|
+
|
|
46
|
+
-- Test 5: Instance properties on instance, not class
|
|
47
|
+
local ok2 = pcall(function() print(User.name) end)
|
|
48
|
+
assert(not ok2, "Test 5 failed: instance accessible on class")
|
|
49
|
+
local User = class({
|
|
50
|
+
id = {1, false, false, true}, -- immutable
|
|
51
|
+
constructor = function(self, super, id)
|
|
52
|
+
self.id = id
|
|
53
|
+
end
|
|
54
|
+
})
|
|
55
|
+
local u = User:new(100)
|
|
56
|
+
local ok = pcall(function() u.id = 999 end)
|
|
57
|
+
assert(not ok, "Test 6 failed: immutable modified")
|
|
58
|
+
assert(u.id == 100, "Test 6 failed: immutable changed")
|
|
59
|
+
|
|
60
|
+
-- Test 7: Mutable property can be changed
|
|
61
|
+
local User = class({
|
|
62
|
+
name = {nil, false, false, false}, -- mutable
|
|
63
|
+
constructor = function(self, super, name)
|
|
64
|
+
self.name = name
|
|
65
|
+
end
|
|
66
|
+
})
|
|
67
|
+
local u = User:new("Alice")
|
|
68
|
+
u.name = "Bob"
|
|
69
|
+
assert(u.name == "Bob", "Test 7 failed")
|
|
70
|
+
local User = class({
|
|
71
|
+
_value = {0, true},
|
|
72
|
+
get = {
|
|
73
|
+
value = function(self) return self._value * 2 end
|
|
74
|
+
},
|
|
75
|
+
constructor = function(self, super, val)
|
|
76
|
+
self._value = val
|
|
77
|
+
end
|
|
78
|
+
})
|
|
79
|
+
local u = User:new(5)
|
|
80
|
+
assert(u.value == 10, "Test 8 failed")
|
|
81
|
+
|
|
82
|
+
-- Test 9: Setter works
|
|
83
|
+
local User = class({
|
|
84
|
+
_value = {0, true},
|
|
85
|
+
getValue = {function(self) return self._value end, false}, -- Add getter
|
|
86
|
+
set = {
|
|
87
|
+
value = function(self, val) self._value = val * 2 end
|
|
88
|
+
},
|
|
89
|
+
constructor = function(self) self._value = 0 end
|
|
90
|
+
})
|
|
91
|
+
local u = User:new()
|
|
92
|
+
u.value = 5
|
|
93
|
+
assert(u.getValue() == 10, "Test 9 failed")
|
|
94
|
+
|
|
95
|
+
-- Test 10: Getter can't be modified (correct version)
|
|
96
|
+
local User = class({
|
|
97
|
+
_value = {0, true},
|
|
98
|
+
get = {
|
|
99
|
+
value = function(self) return self._value end -- Getter only, no setter
|
|
100
|
+
},
|
|
101
|
+
constructor = function(self) self._value = 10 end
|
|
102
|
+
})
|
|
103
|
+
local u = User:new()
|
|
104
|
+
local ok = pcall(function() u.value = 20 end) -- Try to set getter-only property
|
|
105
|
+
assert(not ok, "Test 10 failed: getter modified")
|
|
106
|
+
|
|
107
|
+
local Parent = class({
|
|
108
|
+
id = {1, false},
|
|
109
|
+
constructor = function(self, super, id)
|
|
110
|
+
self.id = id
|
|
111
|
+
end
|
|
112
|
+
})
|
|
113
|
+
local Child = class({
|
|
114
|
+
name = {nil, false},
|
|
115
|
+
constructor = function(self, super, name, id)
|
|
116
|
+
super(id)
|
|
117
|
+
self.name = name
|
|
118
|
+
end
|
|
119
|
+
}, Parent)
|
|
120
|
+
local c = Child:new("Alice", 100)
|
|
121
|
+
assert(c.id == 100 and c.name == "Alice", "Test 11 failed")
|
|
122
|
+
|
|
123
|
+
-- Test 12: Child inherits parent getters
|
|
124
|
+
local Parent = class({
|
|
125
|
+
value = {10, false},
|
|
126
|
+
get = {
|
|
127
|
+
getValue = function(self) return self.value end
|
|
128
|
+
},
|
|
129
|
+
constructor = function(self, super, val)
|
|
130
|
+
self.value = val
|
|
131
|
+
end
|
|
132
|
+
})
|
|
133
|
+
local Child = class({
|
|
134
|
+
name = {nil, false},
|
|
135
|
+
constructor = function(self, super, name, val)
|
|
136
|
+
super(val)
|
|
137
|
+
self.name = name
|
|
138
|
+
end
|
|
139
|
+
}, Parent)
|
|
140
|
+
local c = Child:new("Test", 42)
|
|
141
|
+
assert(c.getValue == 42, "Test 12 failed")
|
|
142
|
+
|
|
143
|
+
-- Test 13: Child inherits parent setters
|
|
144
|
+
local Parent = class({
|
|
145
|
+
_value = {0, true},
|
|
146
|
+
getValue = {function(self) return self._value end, false},
|
|
147
|
+
set = {
|
|
148
|
+
value = function(self, val) self._value = val * 2 end
|
|
149
|
+
},
|
|
150
|
+
constructor = function(self)
|
|
151
|
+
self._value = 0
|
|
152
|
+
end
|
|
153
|
+
})
|
|
154
|
+
local Child = class({
|
|
155
|
+
name = {nil, false},
|
|
156
|
+
constructor = function(self, super, name)
|
|
157
|
+
super()
|
|
158
|
+
self.name = name
|
|
159
|
+
end
|
|
160
|
+
}, Parent)
|
|
161
|
+
local c = Child:new("Test")
|
|
162
|
+
c.value = 5
|
|
163
|
+
assert(c.getValue() == 10, "Test 13 failed")
|
|
164
|
+
local Parent = class({
|
|
165
|
+
secret = {nil, true}, -- private
|
|
166
|
+
constructor = function(self, super, sec)
|
|
167
|
+
self.secret = sec
|
|
168
|
+
end
|
|
169
|
+
})
|
|
170
|
+
local Child = class({
|
|
171
|
+
name = {nil, false},
|
|
172
|
+
constructor = function(self, super, name, sec)
|
|
173
|
+
super(sec)
|
|
174
|
+
self.name = name
|
|
175
|
+
end
|
|
176
|
+
}, Parent)
|
|
177
|
+
local c = Child:new("Alice", "password")
|
|
178
|
+
local ok = pcall(function() print(c.secret) end)
|
|
179
|
+
assert(not ok, "Test 14 failed: parent private accessible")
|
|
180
|
+
|
|
181
|
+
-- Test 15: Parent immutable property blocked in child
|
|
182
|
+
local Parent = class({
|
|
183
|
+
id = {1, false, false, true}, -- immutable
|
|
184
|
+
constructor = function(self, super, id)
|
|
185
|
+
self.id = id
|
|
186
|
+
end
|
|
187
|
+
})
|
|
188
|
+
local Child = class({
|
|
189
|
+
constructor = function(self, super, id)
|
|
190
|
+
super(id)
|
|
191
|
+
end
|
|
192
|
+
}, Parent)
|
|
193
|
+
local c = Child:new(100)
|
|
194
|
+
local ok = pcall(function() c.id = 999 end)
|
|
195
|
+
assert(not ok, "Test 15 failed: parent immutable modified")
|
|
196
|
+
local Parent = class({
|
|
197
|
+
greet = {function(self) return "Hello from parent" end, false, false, false, true},
|
|
198
|
+
constructor = function(self) end
|
|
199
|
+
})
|
|
200
|
+
local Child = class({
|
|
201
|
+
greet = {function(self) return "Hello from child" end, false, false, true, false, true},
|
|
202
|
+
constructor = function(self, super) super() end
|
|
203
|
+
}, Parent)
|
|
204
|
+
local c = Child:new()
|
|
205
|
+
print(c.greet()) -- Should print "Hello from child", probably prints "Hello from parent"
|
|
206
|
+
local Grandparent = class({
|
|
207
|
+
id = {1, false},
|
|
208
|
+
constructor = function(self, super, id)
|
|
209
|
+
self.id = id
|
|
210
|
+
end
|
|
211
|
+
})
|
|
212
|
+
local Parent = class({
|
|
213
|
+
name = {nil, false},
|
|
214
|
+
constructor = function(self, super, name, id)
|
|
215
|
+
super(id)
|
|
216
|
+
self.name = name
|
|
217
|
+
end
|
|
218
|
+
}, Grandparent)
|
|
219
|
+
local Child = class({
|
|
220
|
+
age = {nil, false},
|
|
221
|
+
constructor = function(self, super, age, name, id)
|
|
222
|
+
super(name, id)
|
|
223
|
+
self.age = age
|
|
224
|
+
end
|
|
225
|
+
}, Parent)
|
|
226
|
+
local c = Child:new(20, "Alice", 100)
|
|
227
|
+
assert(c.id == 100 and c.name == "Alice" and c.age == 20, "Test 17 failed")
|
|
228
|
+
local Parent = class({
|
|
229
|
+
count = {0, false, true}, -- static
|
|
230
|
+
constructor = function(self) end
|
|
231
|
+
})
|
|
232
|
+
local Child = class({
|
|
233
|
+
constructor = function(self, super) super() end
|
|
234
|
+
}, Parent)
|
|
235
|
+
assert(Child.count == 0, "Test 18 failed")
|
|
236
|
+
-- This might fail - test it
|
|
237
|
+
|
|
238
|
+
local User = class({
|
|
239
|
+
name = {nil, false},
|
|
240
|
+
greet = {function(self) return "Hello " .. self.name end, false},
|
|
241
|
+
constructor = function(self, super, name)
|
|
242
|
+
self.name = name
|
|
243
|
+
end
|
|
244
|
+
})
|
|
245
|
+
local u = User:new("Alice")
|
|
246
|
+
assert(u.greet() == "Hello Alice", "Test 19 failed")
|
|
247
|
+
|
|
248
|
+
-- Test 20: Static methods work
|
|
249
|
+
local User = class({
|
|
250
|
+
create = {function(self, name) return "Created " .. name end, false, true}, -- 481
|
|
251
|
+
constructor = function(self) end
|
|
252
|
+
})
|
|
253
|
+
assert(User.create("Alice") == "Created Alice", "Test 20 failed")
|
|
254
|
+
local User = class({
|
|
255
|
+
name = {nil, false},
|
|
256
|
+
constructor = function(self, super, name)
|
|
257
|
+
self.name = name
|
|
258
|
+
end
|
|
259
|
+
})
|
|
260
|
+
local u1 = User:new("Alice")
|
|
261
|
+
local u2 = User:new("Bob")
|
|
262
|
+
u1.name = "Charlie"
|
|
263
|
+
assert(u1.name == "Charlie" and u2.name == "Bob", "Test 21 failed")
|
|
264
|
+
|
|
265
|
+
-- Test 22: Metatable protection
|
|
266
|
+
local User = class({
|
|
267
|
+
constructor = function(self) end
|
|
268
|
+
})
|
|
269
|
+
local u = User:new()
|
|
270
|
+
local mt = getmetatable(u)
|
|
271
|
+
assert(mt == "access denied", "Test 22 failed: metatable exposed")
|
|
272
|
+
|
|
273
|
+
-- Test 23: Constructor validation
|
|
274
|
+
local User = class({
|
|
275
|
+
name = {nil, false},
|
|
276
|
+
age = {nil, false},
|
|
277
|
+
constructor = function(self, super, name)
|
|
278
|
+
self.name = name
|
|
279
|
+
-- Forgot to set age
|
|
280
|
+
end
|
|
281
|
+
})
|
|
282
|
+
local ok = pcall(function() User:new("Alice") end)
|
|
283
|
+
assert(not ok, "Test 23 failed: validation missed unset property")
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
local Parent = class({
|
|
287
|
+
greet = {function(self) return "Hello from parent" end, false, false, false, true},
|
|
288
|
+
constructor = function(self) end
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
local Child = class({
|
|
292
|
+
greet = {function(self) return "Hello from child" end, false, false, false, false, true},
|
|
293
|
+
constructor = function(self, super) super() end
|
|
294
|
+
}, Parent)
|
|
295
|
+
|
|
296
|
+
local c = Child:new()
|
|
297
|
+
print(c.greet()) -- Should print "Hello from child"
|
|
298
|
+
|
package/lua/index.lua
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
assert(_VERSION == "Lua 5.4", "THIS MODULE REQUIRES Lua 5.4")
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
---@alias MemberKey string | "get" | "set" | "constructor"
|
|
5
|
+
---@alias Member ShorthandedMemberValue | MemberEntries | Getter | Setter | Constructor
|
|
6
|
+
---@alias ShorthandedMemberValue number | string | boolean | fun(self: unknown, ...: unknown): unknown?
|
|
7
|
+
---@alias MemberEntries {[1]: MemberValue, [2]?: MemberFlag, [3]?: MemberFlag, [4]?: MemberFlag, [5]?: MemberFlag, [6]?: MemberFlag}
|
|
8
|
+
---@alias MemberValue number | string | boolean | table | nil | fun(self: unknown, ...: unknown): unknown
|
|
9
|
+
---@alias MemberFlag boolean | nil
|
|
10
|
+
---@alias Getter fun(self: unknown): unknown
|
|
11
|
+
---@alias Setter fun(self: unknown, value: unknown): nil
|
|
12
|
+
---@alias Constructor fun(self: unknown, super: fun(...: any): unknown, ...: unknown): unknown
|
|
13
|
+
---@alias Members table<string, PropertyFlags>
|
|
14
|
+
---@alias MembersValues table<string, MemberValue>
|
|
15
|
+
---@alias RawMembers table<MemberKey, Member>
|
|
16
|
+
|
|
17
|
+
---@class PropertyFlags
|
|
18
|
+
---@field private MemberFlag
|
|
19
|
+
---@field static MemberFlag
|
|
20
|
+
---@field final MemberFlag
|
|
21
|
+
---@field virtual MemberFlag
|
|
22
|
+
---@field override MemberFlag
|
|
23
|
+
|
|
24
|
+
---@param Members RawMembers
|
|
25
|
+
---@param Parent? unknown
|
|
26
|
+
local class<const> = function (Members, Parent)
|
|
27
|
+
---@type Members
|
|
28
|
+
local members<const> = {}
|
|
29
|
+
---@type MembersValues
|
|
30
|
+
local membersValues<const> = {}
|
|
31
|
+
local default<const> = function(existingValue, defaultValue)
|
|
32
|
+
if existingValue ~= nil then
|
|
33
|
+
return existingValue
|
|
34
|
+
else return defaultValue end
|
|
35
|
+
end
|
|
36
|
+
---@type table<string, Getter>
|
|
37
|
+
local getters<const> = {}
|
|
38
|
+
---@type table<string, Setter>
|
|
39
|
+
local setters<const> = {}
|
|
40
|
+
|
|
41
|
+
for memberKey, member in pairs(Members) do
|
|
42
|
+
assert(member ~= nil, ("syntax error: expected member, got `%s`"):format(type(member)))
|
|
43
|
+
if memberKey == "constructor" then
|
|
44
|
+
if type(member) ~= "function" then error(("syntax error: constructor expected `function`, got `%s`"):format(type(member))) end
|
|
45
|
+
elseif memberKey == "get" then
|
|
46
|
+
if type(member) ~= "table" then error(("syntax error: get expected `table`, got `%s`"):format(type(member))) end
|
|
47
|
+
---@cast member table<string, Getter>
|
|
48
|
+
for getterKey, getter in pairs(member) do
|
|
49
|
+
if type(getter) ~= "function" then error(("syntax error: the getters(`%s`) can be only a `function`, got `%s`"):format(getterKey, type(getter))) end
|
|
50
|
+
local getterInfo<const> = debug.getinfo(getter, "u")
|
|
51
|
+
if getterInfo.nparams ~= 1 then error(("syntax error: the getters(`%s`) can not have parameters (excluding `self`)"):format(getterKey)) end
|
|
52
|
+
getters[getterKey] = getter
|
|
53
|
+
end
|
|
54
|
+
elseif memberKey == "set" then
|
|
55
|
+
if type(member) ~= "table" then error(("syntax error: set expected `table`, got `%s`"):format(type(member))) end
|
|
56
|
+
---@cast member table<string, Setter>
|
|
57
|
+
for setterKey, setter in pairs(member) do
|
|
58
|
+
if type(setter) ~= "function" then error(("syntax error: the setters(`%s`) can be only a `function`, got `%s`"):format(setterKey, type(setter))) end
|
|
59
|
+
local getterInfo<const> = debug.getinfo(setter, "u")
|
|
60
|
+
if getterInfo.nparams ~= 2 then error(("syntax error: the setters(`%s`) must have exactly one parameter (excluding `self`)"):format(setterKey)) end
|
|
61
|
+
setters[setterKey] = setter
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
members[memberKey] = {}
|
|
65
|
+
if type(member) == "table" then
|
|
66
|
+
membersValues[memberKey] = member[1]
|
|
67
|
+
members[memberKey] = {
|
|
68
|
+
private = default(member[2], true),
|
|
69
|
+
static = default(member[3], false),
|
|
70
|
+
final = default(member[4], false),
|
|
71
|
+
virtual = default(member[5], false),
|
|
72
|
+
override = default(member[6], true),
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
membersValues[memberKey] = member
|
|
76
|
+
members[memberKey] = {
|
|
77
|
+
private = true,
|
|
78
|
+
static = false,
|
|
79
|
+
final = true,
|
|
80
|
+
virtual = false,
|
|
81
|
+
override = false,
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
for memberKey, member in pairs(members) do
|
|
88
|
+
if member.override then
|
|
89
|
+
if not Parent or not Parent.__extended then
|
|
90
|
+
error(("cannot override `%s`: no parent class was derived"):format(memberKey))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
local parentMember<const> = Parent.__extended.members[memberKey]
|
|
94
|
+
if not parentMember then
|
|
95
|
+
error(("override failed: no such `%s` parent method"):format(memberKey))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if not parentMember.virtual then
|
|
99
|
+
error(("override denied: the parent method `%s` is not virtual"):format(memberKey))
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if Parent and Parent.__extended then
|
|
105
|
+
for memberKey, member in pairs(Parent.__extended.members) do
|
|
106
|
+
if not members[memberKey] then
|
|
107
|
+
members[memberKey] = member
|
|
108
|
+
membersValues[memberKey] = Parent.__extended.membersValues[memberKey]
|
|
109
|
+
else
|
|
110
|
+
if not members[memberKey].override then
|
|
111
|
+
error(("method `%s` already exists in parent, did you mean to use the override flag"):format(memberKey))
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
for getterKey, getter in pairs(Parent.__extended.getters) do
|
|
117
|
+
if not getters[getterKey] then
|
|
118
|
+
getters[getterKey] = getter
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
for setterKey, setter in pairs(Parent.__extended.setters) do
|
|
123
|
+
if not setters[setterKey] then
|
|
124
|
+
setters[setterKey] = setter
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
return setmetatable({
|
|
130
|
+
__extended = {
|
|
131
|
+
members = members,
|
|
132
|
+
membersValues = membersValues,
|
|
133
|
+
getters = getters,
|
|
134
|
+
setters = setters
|
|
135
|
+
},
|
|
136
|
+
new = function(self, ...)
|
|
137
|
+
---@type MembersValues
|
|
138
|
+
local instance<const> = {}
|
|
139
|
+
for memberKey, member in pairs(members) do
|
|
140
|
+
if not member.static then
|
|
141
|
+
instance[memberKey] = membersValues[memberKey]
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
if Members.constructor and not Parent then
|
|
146
|
+
Members.constructor(instance, nil, ...)
|
|
147
|
+
elseif Members.constructor and Parent then
|
|
148
|
+
local super<const> = function(...)
|
|
149
|
+
local parentInstance<const> = Parent:new(...)
|
|
150
|
+
|
|
151
|
+
local parentMetatable<const> = debug.getmetatable(parentInstance)
|
|
152
|
+
if parentMetatable and parentMetatable.__instance then
|
|
153
|
+
for memberKey, memberValue in pairs(parentMetatable.__instance) do
|
|
154
|
+
local parentMember<const> = Parent.__extended.members[memberKey]
|
|
155
|
+
if members[memberKey] and members[memberKey].override then
|
|
156
|
+
elseif parentMember and not parentMember.private then
|
|
157
|
+
instance[memberKey] = memberValue
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
return parentInstance
|
|
163
|
+
end
|
|
164
|
+
Members.constructor(instance, super, ...)
|
|
165
|
+
else error("no constructor was provided") end
|
|
166
|
+
|
|
167
|
+
for memberKey, member in pairs(members) do
|
|
168
|
+
if not instance[memberKey] and not member.static and not member.private then
|
|
169
|
+
error(("the `%s` was not instantiated in constructor"):format(memberKey))
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
if Parent and Parent.__extended then
|
|
174
|
+
for memberKey, member in pairs(Parent.__extended.members) do
|
|
175
|
+
if not instance[memberKey] and not member.static and not member.private then
|
|
176
|
+
error(("derived member `%s` was not instantiated"):format(memberKey))
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
return setmetatable({}, {
|
|
182
|
+
__metatable = "access denied",
|
|
183
|
+
__instance = instance,
|
|
184
|
+
__index = function(_, memberKey)
|
|
185
|
+
local member<const> = members[memberKey]
|
|
186
|
+
if not member then
|
|
187
|
+
if getters[memberKey] then
|
|
188
|
+
return getters[memberKey](instance)
|
|
189
|
+
elseif Parent and Parent.__extended then
|
|
190
|
+
local parentMember<const> = Parent.__extended.members[memberKey]
|
|
191
|
+
if parentMember then
|
|
192
|
+
if parentMember.private then
|
|
193
|
+
error(("`%s` is not a public member"):format(memberKey))
|
|
194
|
+
end
|
|
195
|
+
return instance[memberKey]
|
|
196
|
+
end
|
|
197
|
+
elseif setters[memberKey] then
|
|
198
|
+
error(("`%s` setter can not be accessed"):format(memberKey))
|
|
199
|
+
end
|
|
200
|
+
error(("`%s` does not exist"):format(memberKey))
|
|
201
|
+
end
|
|
202
|
+
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
203
|
+
assert(not member.static, ("`%s` is a static member"):format(memberKey))
|
|
204
|
+
|
|
205
|
+
local value<const> = instance[memberKey]
|
|
206
|
+
if type(value) == "function" then
|
|
207
|
+
return function(_, ...)
|
|
208
|
+
return value(instance, ...)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
return value
|
|
213
|
+
end,
|
|
214
|
+
__newindex = function(_, memberKey, memberValue)
|
|
215
|
+
if setters[memberKey] then
|
|
216
|
+
setters[memberKey](instance, memberValue)
|
|
217
|
+
return
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
local member = members[memberKey]
|
|
221
|
+
|
|
222
|
+
if not member and Parent and Parent.__extended then
|
|
223
|
+
member = Parent.__extended.members[memberKey]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
if not member then
|
|
227
|
+
if getters[memberKey] then
|
|
228
|
+
error(("getters can not be modified: at `%s`"):format(memberKey))
|
|
229
|
+
end
|
|
230
|
+
error(("`%s` does not exist"):format(memberKey))
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
234
|
+
assert(not member.static, ("`%s` is a static member"):format(memberKey))
|
|
235
|
+
assert(not member.final, ("`%s` is a readonly member"):format(memberKey))
|
|
236
|
+
|
|
237
|
+
instance[memberKey] = memberValue
|
|
238
|
+
end
|
|
239
|
+
})
|
|
240
|
+
end
|
|
241
|
+
}, {
|
|
242
|
+
__metatable = "access denied",
|
|
243
|
+
__index = function(self, memberKey)
|
|
244
|
+
local member<const> = members[memberKey]
|
|
245
|
+
if not member then
|
|
246
|
+
if getters[memberKey] then
|
|
247
|
+
return getters[memberKey](membersValues)
|
|
248
|
+
elseif Parent then
|
|
249
|
+
return Parent[memberKey]
|
|
250
|
+
elseif setters[memberKey] then
|
|
251
|
+
error(("setters can not be accessed: at `%s`"):format(memberKey))
|
|
252
|
+
end
|
|
253
|
+
error(("`%s` does not exist"):format(memberKey))
|
|
254
|
+
end
|
|
255
|
+
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
256
|
+
assert(member.static, ("`%s` is not a static member"):format(memberKey))
|
|
257
|
+
local value<const> = membersValues[memberKey]
|
|
258
|
+
|
|
259
|
+
if type(value) == "function" then
|
|
260
|
+
return function(...)
|
|
261
|
+
return value(membersValues, ...)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
return value
|
|
266
|
+
end,
|
|
267
|
+
__newindex = function(self, memberKey, memberValue)
|
|
268
|
+
local member<const> = members[memberKey]
|
|
269
|
+
if not member then
|
|
270
|
+
if setters[memberKey] then
|
|
271
|
+
setters[memberKey](membersValues, memberValue)
|
|
272
|
+
return
|
|
273
|
+
elseif Parent then
|
|
274
|
+
Parent[memberKey] = memberValue
|
|
275
|
+
return
|
|
276
|
+
elseif getters[memberKey] then
|
|
277
|
+
error(("getters can not be modified: at `%s`"):format(memberKey))
|
|
278
|
+
end
|
|
279
|
+
error(("`%s` does not exist"):format(memberKey))
|
|
280
|
+
end
|
|
281
|
+
assert(not member.private, ("`%s` is not a public member"):format(memberKey))
|
|
282
|
+
assert(member.static, ("`%s` is not a static member"):format(memberKey))
|
|
283
|
+
assert(not member.final, ("`%s` is a readonly member"):format(memberKey))
|
|
284
|
+
membersValues[memberKey] = memberValue
|
|
285
|
+
end
|
|
286
|
+
})
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
-- annotation tests section
|
|
291
|
+
local private<const>, static<const>, final<const>, virtual<const>, override<const> = true, true, true, true, true
|
|
292
|
+
class({
|
|
293
|
+
property1 = 10,
|
|
294
|
+
property4 = {10},
|
|
295
|
+
property7 = {10, private, false, final, false, override},
|
|
296
|
+
property2 = "hello",
|
|
297
|
+
property5 = {"hello"},
|
|
298
|
+
property8 = {"hello", false, static, false, virtual, false},
|
|
299
|
+
property3 = true,
|
|
300
|
+
property6 = {true},
|
|
301
|
+
property9 = {true, private, false, final, false, override},
|
|
302
|
+
property10 = nil, -- SYNTAX ERROR
|
|
303
|
+
property11 = {nil},
|
|
304
|
+
property12 = {nil, false, static, false, virtual, false},
|
|
305
|
+
method1 = function(self) end,
|
|
306
|
+
method2 = {function(self) end},
|
|
307
|
+
method3 = {function(self) end, private, false, final, false, override},
|
|
308
|
+
get = {
|
|
309
|
+
getter1 = function(self)
|
|
310
|
+
return self.property1
|
|
311
|
+
end,
|
|
312
|
+
},
|
|
313
|
+
set = {
|
|
314
|
+
setter1 = function(self, value)
|
|
315
|
+
self.property1 = value
|
|
316
|
+
end,
|
|
317
|
+
},
|
|
318
|
+
constructor = function(self, super, value)
|
|
319
|
+
super(value)
|
|
320
|
+
self.property1 = value
|
|
321
|
+
end
|
|
322
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package = "lenix"
|
|
2
|
+
version = "0.1.0-1"
|
|
3
|
+
|
|
4
|
+
source = {
|
|
5
|
+
url = "git+https://github.com/lenixdev/lenix.git",
|
|
6
|
+
tag = "v0.1.0"
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
description = {
|
|
10
|
+
summary = "Lua OOP class module similar to TypeScript/JavaScript/Java/C++ classes",
|
|
11
|
+
detailed = "Lua object oriented programming class module with support for constructors, getters, setters, inheritance, static members, private members, final members, and virtual/override methods.",
|
|
12
|
+
homepage = "https://github.com/lenixdev/lenix/lua",
|
|
13
|
+
license = "MIT"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
dependencies = {
|
|
17
|
+
"lua == 5.4"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
build = {
|
|
21
|
+
type = "builtin",
|
|
22
|
+
modules = {
|
|
23
|
+
lenix = "index.lua"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lenix",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.3.2",
|
|
4
|
+
"description": "The Monorepo for the software engineering community",
|
|
5
5
|
"author": "Lenix",
|
|
6
6
|
"license": "GPL-3.0",
|
|
7
7
|
"type": "module",
|
|
@@ -15,21 +15,24 @@
|
|
|
15
15
|
"fxmanifest",
|
|
16
16
|
"api",
|
|
17
17
|
"oop",
|
|
18
|
-
"class"
|
|
18
|
+
"class",
|
|
19
|
+
"eslint",
|
|
20
|
+
"linter"
|
|
19
21
|
],
|
|
20
22
|
"repository": {
|
|
21
23
|
"type": "git",
|
|
22
24
|
"url": "git+https://github.com/lenixdev/lenix.git"
|
|
23
25
|
},
|
|
24
|
-
"main": "./dist/index.js",
|
|
25
|
-
"types": "./dist/index.d.ts",
|
|
26
|
+
"main": "./ts/dist/index.js",
|
|
27
|
+
"types": "./ts/dist/index.d.ts",
|
|
26
28
|
"bin": {
|
|
27
|
-
"mac-lua-modules": "
|
|
28
|
-
"lenix": "./
|
|
29
|
+
"mac-lua-modules": "lua/mac-lua-modules.sh",
|
|
30
|
+
"lenix": "./lint/dist/lint.mjs"
|
|
29
31
|
},
|
|
30
32
|
"files": [
|
|
31
|
-
"dist",
|
|
32
|
-
"
|
|
33
|
+
"ts/dist",
|
|
34
|
+
"lua",
|
|
35
|
+
"lint"
|
|
33
36
|
],
|
|
34
37
|
"dependencies": {
|
|
35
38
|
"@eslint/js": "^10.0.1",
|
|
@@ -48,6 +51,7 @@
|
|
|
48
51
|
"typescript": "^5.3.3"
|
|
49
52
|
},
|
|
50
53
|
"scripts": {
|
|
51
|
-
"build": "tsc -p
|
|
54
|
+
"build": "tsc -p ts/fxmanifest/tsconfig.json && tsc-alias && tsc -p lint/tsconfig.json",
|
|
55
|
+
"bump": "pnpm version patch"
|
|
52
56
|
}
|
|
53
57
|
}
|