Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/tests/ClassFixture.cpp
2723 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
3
#include "ClassFixture.h"
4
5
#include "Luau/BuiltinDefinitions.h"
6
7
using std::nullopt;
8
9
namespace Luau
10
{
11
12
ExternTypeFixture::ExternTypeFixture(bool prepareAutocomplete)
13
: BuiltinsFixture(prepareAutocomplete)
14
{
15
}
16
17
Frontend& ExternTypeFixture::getFrontend()
18
{
19
Frontend& f = BuiltinsFixture::getFrontend();
20
21
GlobalTypes& globals = f.globals;
22
TypeArena& arena = globals.globalTypes;
23
TypeId numberType = getBuiltins()->numberType;
24
TypeId stringType = getBuiltins()->stringType;
25
26
unfreeze(arena);
27
28
TypeId connectionType = arena.addType(ExternType{"Connection", {}, nullopt, nullopt, {}, {}, "Connection", {}});
29
30
TypeId baseClassInstanceType = arena.addType(ExternType{"BaseClass", {}, nullopt, nullopt, {}, {}, "Test", {}});
31
getMutable<ExternType>(baseClassInstanceType)->props = {
32
{"BaseMethod", Property::readonly(makeFunction(arena, baseClassInstanceType, {numberType}, {}))},
33
{"BaseField", {numberType}},
34
35
{"Touched", Property::readonly(connectionType)},
36
};
37
38
getMutable<ExternType>(connectionType)->props = {
39
{"Connect", {makeFunction(arena, connectionType, {makeFunction(arena, nullopt, {baseClassInstanceType}, {})}, {})}}
40
};
41
42
TypeId baseClassType = arena.addType(ExternType{"BaseClass", {}, nullopt, nullopt, {}, {}, "Test", {}});
43
getMutable<ExternType>(baseClassType)->props = {
44
{"StaticMethod", {makeFunction(arena, nullopt, {}, {numberType})}},
45
{"Clone", {makeFunction(arena, nullopt, {baseClassInstanceType}, {baseClassInstanceType})}},
46
{"New", {makeFunction(arena, nullopt, {}, {baseClassInstanceType})}},
47
};
48
globals.globalScope->exportedTypeBindings["BaseClass"] = TypeFun{{}, baseClassInstanceType};
49
addGlobalBinding(globals, "BaseClass", baseClassType, "@test");
50
51
TypeId childClassInstanceType = arena.addType(ExternType{"ChildClass", {}, baseClassInstanceType, nullopt, {}, {}, "Test", {}});
52
53
getMutable<ExternType>(childClassInstanceType)->props = {
54
{"Method", {makeFunction(arena, childClassInstanceType, {}, {stringType})}},
55
};
56
57
TypeId childClassType = arena.addType(ExternType{"ChildClass", {}, baseClassType, nullopt, {}, {}, "Test", {}});
58
getMutable<ExternType>(childClassType)->props = {
59
{"New", {makeFunction(arena, nullopt, {}, {childClassInstanceType})}},
60
};
61
globals.globalScope->exportedTypeBindings["ChildClass"] = TypeFun{{}, childClassInstanceType};
62
addGlobalBinding(globals, "ChildClass", childClassType, "@test");
63
64
TypeId grandChildInstanceType = arena.addType(ExternType{"GrandChild", {}, childClassInstanceType, nullopt, {}, {}, "Test", {}});
65
66
getMutable<ExternType>(grandChildInstanceType)->props = {
67
{"Method", {makeFunction(arena, grandChildInstanceType, {}, {stringType})}},
68
};
69
70
TypeId grandChildType = arena.addType(ExternType{"GrandChild", {}, baseClassType, nullopt, {}, {}, "Test", {}});
71
getMutable<ExternType>(grandChildType)->props = {
72
{"New", {makeFunction(arena, nullopt, {}, {grandChildInstanceType})}},
73
};
74
globals.globalScope->exportedTypeBindings["GrandChild"] = TypeFun{{}, grandChildInstanceType};
75
addGlobalBinding(globals, "GrandChild", childClassType, "@test");
76
77
TypeId anotherChildInstanceType = arena.addType(ExternType{"AnotherChild", {}, baseClassInstanceType, nullopt, {}, {}, "Test", {}});
78
79
getMutable<ExternType>(anotherChildInstanceType)->props = {
80
{"Method", {makeFunction(arena, anotherChildInstanceType, {}, {stringType})}},
81
};
82
83
TypeId anotherChildType = arena.addType(ExternType{"AnotherChild", {}, baseClassType, nullopt, {}, {}, "Test", {}});
84
getMutable<ExternType>(anotherChildType)->props = {
85
{"New", {makeFunction(arena, nullopt, {}, {anotherChildInstanceType})}},
86
};
87
globals.globalScope->exportedTypeBindings["AnotherChild"] = TypeFun{{}, anotherChildInstanceType};
88
addGlobalBinding(globals, "AnotherChild", childClassType, "@test");
89
90
TypeId unrelatedClassInstanceType = arena.addType(ExternType{"UnrelatedClass", {}, nullopt, nullopt, {}, {}, "Test", {}});
91
92
TypeId unrelatedClassType = arena.addType(ExternType{"UnrelatedClass", {}, nullopt, nullopt, {}, {}, "Test", {}});
93
getMutable<ExternType>(unrelatedClassType)->props = {
94
{"New", {makeFunction(arena, nullopt, {}, {unrelatedClassInstanceType})}},
95
};
96
globals.globalScope->exportedTypeBindings["UnrelatedClass"] = TypeFun{{}, unrelatedClassInstanceType};
97
addGlobalBinding(globals, "UnrelatedClass", unrelatedClassType, "@test");
98
99
TypeId vector2MetaType = arena.addType(TableType{});
100
101
vector2InstanceType = arena.addType(ExternType{"Vector2", {}, nullopt, vector2MetaType, {}, {}, "Test", {}});
102
getMutable<ExternType>(vector2InstanceType)->props = {
103
{"X", {numberType}},
104
{"Y", {numberType}},
105
};
106
107
vector2Type = arena.addType(ExternType{"Vector2", {}, nullopt, nullopt, {}, {}, "Test", {}});
108
getMutable<ExternType>(vector2Type)->props = {
109
{"New", {makeFunction(arena, nullopt, {numberType, numberType}, {vector2InstanceType})}},
110
};
111
getMutable<TableType>(vector2MetaType)->props = {
112
{"__add", {makeFunction(arena, nullopt, {vector2InstanceType, vector2InstanceType}, {vector2InstanceType})}},
113
{"__mul",
114
{arena.addType(
115
IntersectionType{{
116
makeFunction(arena, vector2InstanceType, {vector2InstanceType}, {vector2InstanceType}),
117
makeFunction(arena, vector2InstanceType, {getBuiltins()->numberType}, {vector2InstanceType}),
118
}}
119
)}}
120
};
121
globals.globalScope->exportedTypeBindings["Vector2"] = TypeFun{{}, vector2InstanceType};
122
addGlobalBinding(globals, "Vector2", vector2Type, "@test");
123
124
TypeId callableClassMetaType = arena.addType(TableType{});
125
TypeId callableClassType = arena.addType(ExternType{"CallableClass", {}, nullopt, callableClassMetaType, {}, {}, "Test", {}});
126
getMutable<TableType>(callableClassMetaType)->props = {
127
{"__call", {makeFunction(arena, nullopt, {callableClassType, stringType}, {numberType})}},
128
};
129
globals.globalScope->exportedTypeBindings["CallableClass"] = TypeFun{{}, callableClassType};
130
131
auto addIndexableClass = [&arena, &globals](const char* className, TypeId keyType, TypeId returnType)
132
{
133
TypeId indexableClassMetaType = arena.addType(TableType{});
134
TypeId indexableClassType =
135
arena.addType(ExternType{className, {}, nullopt, indexableClassMetaType, {}, {}, "Test", {}, TableIndexer{keyType, returnType}});
136
globals.globalScope->exportedTypeBindings[className] = TypeFun{{}, indexableClassType};
137
};
138
139
// IndexableClass has a table indexer with a key type of 'number | string' and a return type of 'number'
140
addIndexableClass("IndexableClass", arena.addType(Luau::UnionType{{stringType, numberType}}), numberType);
141
// IndexableNumericKeyClass has a table indexer with a key type of 'number' and a return type of 'number'
142
addIndexableClass("IndexableNumericKeyClass", numberType, numberType);
143
144
// Add a confusing derived class which shares the same name internally, but has a unique alias
145
TypeId duplicateBaseClassInstanceType = arena.addType(ExternType{"BaseClass", {}, baseClassInstanceType, nullopt, {}, {}, "Test", {}});
146
147
getMutable<ExternType>(duplicateBaseClassInstanceType)->props = {
148
{"Method", {makeFunction(arena, duplicateBaseClassInstanceType, {}, {stringType})}},
149
};
150
151
addGlobalBinding(globals, "confusingBaseClassInstance", duplicateBaseClassInstanceType, "@test");
152
153
TypeId genericT = arena.addType(GenericType{Name{"T"}, Polarity::Mixed});
154
TypeId identity = arena.addType(
155
FunctionType{
156
{genericT},
157
{},
158
arena.addTypePack(TypePack{{genericT}, {}}),
159
arena.addTypePack(TypePack{{genericT}, {}}),
160
std::nullopt,
161
/* hasSelf */ false
162
}
163
);
164
165
TypeId classWithGenericMethod = arena.addType(
166
ExternType{"ClassWithGenericMethod", {{"identity", Property::readonly(identity)}}, std::nullopt, std::nullopt, {}, {}, "Test", {}}
167
);
168
169
globals.globalScope->exportedTypeBindings["ClassWithGenericMethod"] = TypeFun{{}, classWithGenericMethod};
170
addGlobalBinding(globals, "ClassWithGenericMethod", classWithGenericMethod, "@test");
171
172
for (const auto& [name, tf] : globals.globalScope->exportedTypeBindings)
173
persist(tf.type);
174
175
freeze(arena);
176
return *frontend;
177
}
178
179
} // namespace Luau
180
181