@flamework-experimental/transformer 2.0.0-alpha.0

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.
Files changed (72) hide show
  1. package/README.md +66 -0
  2. package/flamework-schema.json +76 -0
  3. package/flamework.config.schema.json +197 -0
  4. package/out/classes/buildInfo.js +467 -0
  5. package/out/classes/diagnostics.js +110 -0
  6. package/out/classes/logger.js +201 -0
  7. package/out/classes/nodeMetadata.js +232 -0
  8. package/out/classes/transformState.js +623 -0
  9. package/out/index.js +75 -0
  10. package/out/transformations/expressions/transformAccessExpression.js +35 -0
  11. package/out/transformations/expressions/transformBinaryExpression.js +57 -0
  12. package/out/transformations/expressions/transformCallExpression.js +33 -0
  13. package/out/transformations/expressions/transformDeleteExpression.js +22 -0
  14. package/out/transformations/expressions/transformNewExpression.js +17 -0
  15. package/out/transformations/expressions/transformUnaryExpression.js +63 -0
  16. package/out/transformations/macros/intrinsics/components.js +64 -0
  17. package/out/transformations/macros/intrinsics/env.js +31 -0
  18. package/out/transformations/macros/intrinsics/guards.js +43 -0
  19. package/out/transformations/macros/intrinsics/inlining.js +22 -0
  20. package/out/transformations/macros/intrinsics/networking.js +131 -0
  21. package/out/transformations/macros/intrinsics/parameters.js +81 -0
  22. package/out/transformations/macros/intrinsics/paths.js +42 -0
  23. package/out/transformations/macros/updateComponentConfig.js +409 -0
  24. package/out/transformations/plugins/nodeFactory.js +159 -0
  25. package/out/transformations/plugins/pluginHost.js +235 -0
  26. package/out/transformations/plugins/typeFacade.js +242 -0
  27. package/out/transformations/statements/transformClassDeclaration.js +282 -0
  28. package/out/transformations/transformExpression.js +34 -0
  29. package/out/transformations/transformFile.js +78 -0
  30. package/out/transformations/transformNetworkingCall.js +566 -0
  31. package/out/transformations/transformNode.js +27 -0
  32. package/out/transformations/transformStatement.js +57 -0
  33. package/out/transformations/transformStatementList.js +64 -0
  34. package/out/transformations/transformUserMacro.js +698 -0
  35. package/out/transformer.js +52 -0
  36. package/out/util/cache.js +10 -0
  37. package/out/util/constants.js +5 -0
  38. package/out/util/diagnosticsUtils.js +112 -0
  39. package/out/util/env.js +267 -0
  40. package/out/util/factory.js +583 -0
  41. package/out/util/functions/addLeadingComment.js +13 -0
  42. package/out/util/functions/arePathsEqual.js +14 -0
  43. package/out/util/functions/assert.js +17 -0
  44. package/out/util/functions/buildGuardFromType.js +713 -0
  45. package/out/util/functions/buildInstanceShape.js +156 -0
  46. package/out/util/functions/buildSerializerFromType.js +2309 -0
  47. package/out/util/functions/createPathTranslator.js +54 -0
  48. package/out/util/functions/emitTypescriptMismatch.js +80 -0
  49. package/out/util/functions/getDeclarationName.js +23 -0
  50. package/out/util/functions/getDeclarationOfType.js +7 -0
  51. package/out/util/functions/getIndexExpression.js +16 -0
  52. package/out/util/functions/getInstanceTypeFromType.js +75 -0
  53. package/out/util/functions/getNodeList.js +6 -0
  54. package/out/util/functions/getPackageJson.js +44 -0
  55. package/out/util/functions/getSuperClasses.js +51 -0
  56. package/out/util/functions/isAttributesAccess.js +23 -0
  57. package/out/util/functions/isCleanBuildDirectory.js +13 -0
  58. package/out/util/functions/isDefinedType.js +16 -0
  59. package/out/util/functions/isPathDescendantOf.js +25 -0
  60. package/out/util/functions/isTupleType.js +10 -0
  61. package/out/util/functions/parseCommandLine.js +31 -0
  62. package/out/util/functions/shuffle.js +39 -0
  63. package/out/util/functions/tryResolve.js +15 -0
  64. package/out/util/functions/validateConstraintMetadata.js +60 -0
  65. package/out/util/packages.js +12 -0
  66. package/out/util/projectConfig.js +221 -0
  67. package/out/util/schema.js +80 -0
  68. package/out/util/tsInternals.js +16 -0
  69. package/out/util/uid.js +227 -0
  70. package/package.json +45 -0
  71. package/rojo-schema.json +34 -0
  72. package/types.d.ts +4 -0
@@ -0,0 +1,713 @@
1
+ "use strict";
2
+ var __read = (this && this.__read) || function (o, n) {
3
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
4
+ if (!m) return o;
5
+ var i = m.call(o), r, ar = [], e;
6
+ try {
7
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
8
+ }
9
+ catch (error) { e = { error: error }; }
10
+ finally {
11
+ try {
12
+ if (r && !r.done && (m = i["return"])) m.call(i);
13
+ }
14
+ finally { if (e) throw e.error; }
15
+ }
16
+ return ar;
17
+ };
18
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
20
+ if (ar || !(i in from)) {
21
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
22
+ ar[i] = from[i];
23
+ }
24
+ }
25
+ return to.concat(ar || Array.prototype.slice.call(from));
26
+ };
27
+ var __values = (this && this.__values) || function(o) {
28
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
29
+ if (m) return m.call(o);
30
+ if (o && typeof o.length === "number") return {
31
+ next: function () {
32
+ if (o && i >= o.length) o = void 0;
33
+ return { value: o && o[i++], done: !o };
34
+ }
35
+ };
36
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
37
+ };
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.buildGuardsFromType = buildGuardsFromType;
43
+ exports.buildGuardFromType = buildGuardFromType;
44
+ exports.buildGuardFromTypeWithDedup = buildGuardFromTypeWithDedup;
45
+ exports.createGuardGenerator = createGuardGenerator;
46
+ exports.simplifyUnion = simplifyUnion;
47
+ exports.extractTypes = extractTypes;
48
+ exports.getLiteral = getLiteral;
49
+ exports.isInstanceType = isInstanceType;
50
+ exports.isConditionalType = isConditionalType;
51
+ var typescript_1 = __importDefault(require("typescript"));
52
+ var diagnostics_1 = require("../../classes/diagnostics");
53
+ var factory_1 = require("../factory");
54
+ var getDeclarationOfType_1 = require("./getDeclarationOfType");
55
+ var getInstanceTypeFromType_1 = require("./getInstanceTypeFromType");
56
+ var assert_1 = __importDefault(require("assert"));
57
+ var tsInternals_1 = require("../tsInternals");
58
+ /**
59
+ * Convert a type into a list of typeguards.
60
+ * @param state The TransformState
61
+ * @param file The file that this type belongs to
62
+ * @param type The type to convert
63
+ * @param isInterfaceType Determines whether unknown should be omitted.
64
+ * @returns An array of property assignments.
65
+ */
66
+ function buildGuardsFromType(state, node, type, file, isInterfaceType) {
67
+ if (file === void 0) { file = state.getSourceFile(node); }
68
+ if (isInterfaceType === void 0) { isInterfaceType = false; }
69
+ var generator = createGuardGenerator(state, file, node);
70
+ return generator.buildGuardsFromType(type, isInterfaceType);
71
+ }
72
+ // This compiles directly to `t.typeof` for any userdata that `t` does not have an alias for, or users might not have yet.
73
+ var RBX_TYPES_NEW = ["buffer", "InstanceHandle"];
74
+ var RBX_TYPES = __spreadArray([
75
+ "UDim",
76
+ "UDim2",
77
+ "BrickColor",
78
+ "Color3",
79
+ "Vector2",
80
+ "Vector3",
81
+ "NumberSequence",
82
+ "NumberSequenceKeypoint",
83
+ "ColorSequence",
84
+ "ColorSequenceKeypoint",
85
+ "NumberRange",
86
+ "Rect",
87
+ "DockWidgetPluginGuiInfo",
88
+ "CFrame",
89
+ "Axes",
90
+ "Faces",
91
+ "Font",
92
+ "Instance",
93
+ "Ray",
94
+ "Random",
95
+ "Region3",
96
+ "Region3int16",
97
+ "Enum",
98
+ "TweenInfo",
99
+ "PhysicalProperties",
100
+ "Vector3int16",
101
+ "Vector2int16",
102
+ "PathWaypoint",
103
+ "EnumItem",
104
+ "RBXScriptSignal",
105
+ "RBXScriptConnection",
106
+ "FloatCurveKey",
107
+ "OverlapParams",
108
+ "thread"
109
+ ], __read(RBX_TYPES_NEW), false);
110
+ var OBJECT_IGNORED_FIELD_TYPES = typescript_1.default.TypeFlags.Unknown | typescript_1.default.TypeFlags.Never | typescript_1.default.TypeFlags.UniqueESSymbol;
111
+ var DEDUP_HEURISTIC_LIMIT = 5;
112
+ var DEDUP_HEURISTIC_FLAGS = typescript_1.default.TypeFlags.Object | typescript_1.default.TypeFlags.UnionOrIntersection;
113
+ /**
114
+ * Finds the object and union types that appear at least `dedupLimit` times within `type`, which are
115
+ * worth emitting once as a local and referencing, rather than inlining at every occurrence.
116
+ */
117
+ function getTypesRequiringDedupHeuristic(type, dedupLimit) {
118
+ var e_1, _a;
119
+ if (dedupLimit === void 0) { dedupLimit = DEDUP_HEURISTIC_LIMIT; }
120
+ var seenCount = new Map();
121
+ // Types currently being walked, so that a self-referential type (`Vector3.Unit` is a `Vector3`)
122
+ // is counted where it recurs but not descended into again.
123
+ var visiting = new Set();
124
+ function recurse(type, modifier) {
125
+ var _a;
126
+ if (modifier === void 0) { modifier = 1; }
127
+ if (type.flags & DEDUP_HEURISTIC_FLAGS) {
128
+ var typeSeenCount = (_a = seenCount.get(type)) !== null && _a !== void 0 ? _a : 0;
129
+ seenCount.set(type, typeSeenCount + modifier);
130
+ }
131
+ if (visiting.has(type)) {
132
+ return;
133
+ }
134
+ visiting.add(type);
135
+ recurseChildren(type, modifier);
136
+ visiting.delete(type);
137
+ }
138
+ function recurseChildren(type, modifier) {
139
+ var e_2, _a, e_3, _b;
140
+ if (type.isUnionOrIntersection()) {
141
+ type.types.forEach(function (ty) { return recurse(ty, modifier); });
142
+ }
143
+ else if (type.flags & typescript_1.default.TypeFlags.Object && !isInstanceType(type)) {
144
+ try {
145
+ for (var _c = __values(type.getProperties()), _d = _c.next(); !_d.done; _d = _c.next()) {
146
+ var property = _d.value;
147
+ var propertyType = type.checker.getTypeOfPropertyOfType(type, property.name);
148
+ if (!propertyType) {
149
+ continue;
150
+ }
151
+ recurse(propertyType, modifier);
152
+ }
153
+ }
154
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
155
+ finally {
156
+ try {
157
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
158
+ }
159
+ finally { if (e_2) throw e_2.error; }
160
+ }
161
+ try {
162
+ for (var _e = __values(type.checker.getIndexInfosOfType(type)), _f = _e.next(); !_f.done; _f = _e.next()) {
163
+ var indexInfo = _f.value;
164
+ recurse(indexInfo.keyType, modifier);
165
+ recurse(indexInfo.type, modifier);
166
+ }
167
+ }
168
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
169
+ finally {
170
+ try {
171
+ if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
172
+ }
173
+ finally { if (e_3) throw e_3.error; }
174
+ }
175
+ }
176
+ }
177
+ recurse(type);
178
+ var requiresDedup = new Set();
179
+ try {
180
+ for (var seenCount_1 = __values(seenCount), seenCount_1_1 = seenCount_1.next(); !seenCount_1_1.done; seenCount_1_1 = seenCount_1.next()) {
181
+ var _b = __read(seenCount_1_1.value, 2), type_1 = _b[0], count = _b[1];
182
+ if (count >= dedupLimit) {
183
+ requiresDedup.add(type_1);
184
+ // We subtract all the children, as deduplicating the parent effectively removes `count - 1` of any children from the emit.
185
+ recurse(type_1, -(count - 1));
186
+ }
187
+ }
188
+ }
189
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
190
+ finally {
191
+ try {
192
+ if (seenCount_1_1 && !seenCount_1_1.done && (_a = seenCount_1.return)) _a.call(seenCount_1);
193
+ }
194
+ finally { if (e_1) throw e_1.error; }
195
+ }
196
+ return requiresDedup;
197
+ }
198
+ /**
199
+ * Convert a type into a type guard.
200
+ * @param state The TransformState
201
+ * @param file The file that this type belongs to
202
+ * @param type The type to convert
203
+ * @returns An array of property assignments.
204
+ */
205
+ function buildGuardFromType(state, node, type, file) {
206
+ if (file === void 0) { file = state.getSourceFile(node); }
207
+ var generator = createGuardGenerator(state, file, node);
208
+ return generator.buildGuard(type);
209
+ }
210
+ /**
211
+ * Convert a type into a type guard, deduplicating large guards when the
212
+ * `optimizations.guardGenerationDedupLimit` transformer option is set.
213
+ *
214
+ * The returned statements declare the shared guards and must be emitted ahead of the expression.
215
+ * @param state The TransformState
216
+ * @param file The file that this type belongs to
217
+ * @param type The type to convert
218
+ */
219
+ function buildGuardFromTypeWithDedup(state, node, type, file) {
220
+ var _a;
221
+ if (file === void 0) { file = state.getSourceFile(node); }
222
+ var generator = createGuardGenerator(state, file, node);
223
+ var dedupLimit = (_a = state.config.optimizations) === null || _a === void 0 ? void 0 : _a.guardGenerationDedupLimit;
224
+ if (dedupLimit !== undefined) {
225
+ generator.calculateDedup(type, Math.max(dedupLimit, 1));
226
+ }
227
+ return {
228
+ guard: generator.buildGuard(type),
229
+ statements: generator.dedupStatements,
230
+ };
231
+ }
232
+ /**
233
+ * Creates a stateful guard generator.
234
+ */
235
+ function createGuardGenerator(state, file, diagnosticNode) {
236
+ var tracking = new Array();
237
+ var dedupStatements = new Array();
238
+ var dedupIds = new Map();
239
+ var requiresDedup = new Set();
240
+ return { buildGuard: buildGuard, buildGuardsFromType: buildGuardsFromType, calculateDedup: calculateDedup, dedupStatements: dedupStatements };
241
+ function fail(err) {
242
+ var e_4, _a;
243
+ var basicDiagnostic = diagnostics_1.Diagnostics.createDiagnostic(diagnosticNode, typescript_1.default.DiagnosticCategory.Error, err);
244
+ var previousType;
245
+ try {
246
+ for (var tracking_1 = __values(tracking), tracking_1_1 = tracking_1.next(); !tracking_1_1.done; tracking_1_1 = tracking_1.next()) {
247
+ var location_1 = tracking_1_1.value;
248
+ if (location_1[1] === previousType) {
249
+ continue;
250
+ }
251
+ previousType = location_1[1];
252
+ typescript_1.default.addRelatedInfo(basicDiagnostic, diagnostics_1.Diagnostics.createDiagnostic(factory_1.f.is.namedDeclaration(location_1[0]) ? location_1[0].name : location_1[0], typescript_1.default.DiagnosticCategory.Error, "Type was defined here: ".concat(state.typeChecker.typeToString(location_1[1]))));
253
+ }
254
+ }
255
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
256
+ finally {
257
+ try {
258
+ if (tracking_1_1 && !tracking_1_1.done && (_a = tracking_1.return)) _a.call(tracking_1);
259
+ }
260
+ finally { if (e_4) throw e_4.error; }
261
+ }
262
+ throw new diagnostics_1.DiagnosticError(basicDiagnostic);
263
+ }
264
+ function calculateDedup(type, dedupLimit) {
265
+ requiresDedup = getTypesRequiringDedupHeuristic(type, dedupLimit);
266
+ }
267
+ function buildGuard(type) {
268
+ var _a, _b, _c, _d, _e;
269
+ if (requiresDedup.has(type)) {
270
+ var existingId = dedupIds.get(type);
271
+ if (existingId) {
272
+ return existingId;
273
+ }
274
+ }
275
+ var declaration = (0, getDeclarationOfType_1.getDeclarationOfType)(type);
276
+ if (declaration) {
277
+ tracking.push([declaration, type]);
278
+ }
279
+ var guard = buildGuardInner(type);
280
+ if (declaration) {
281
+ (0, assert_1.default)(((_a = tracking.pop()) === null || _a === void 0 ? void 0 : _a[0]) === declaration, "Popped value was not expected");
282
+ }
283
+ if (requiresDedup.has(type)) {
284
+ var dedupId = factory_1.f.identifier((_e = (_c = (_b = type.aliasSymbol) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : (_d = type.symbol) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : "dedup", true);
285
+ dedupIds.set(type, dedupId);
286
+ dedupStatements.push(factory_1.f.variableStatement(dedupId, guard));
287
+ return dedupId;
288
+ }
289
+ return guard;
290
+ }
291
+ function buildGuardInner(type) {
292
+ var e_5, _a, e_6, _b;
293
+ var _c, _d, _e, _f, _g;
294
+ var typeChecker = state.typeChecker;
295
+ var tId = state.getGuardLibrary(file);
296
+ if (type.isUnion()) {
297
+ return buildUnionGuard(type);
298
+ }
299
+ if (isInstanceType(type)) {
300
+ var instanceType = (0, getInstanceTypeFromType_1.getInstanceTypeFromType)(file, type);
301
+ var additionalGuards = new Array();
302
+ try {
303
+ for (var _h = __values(type.getProperties()), _j = _h.next(); !_j.done; _j = _h.next()) {
304
+ var property = _j.value;
305
+ var propertyType = type.checker.getTypeOfPropertyOfType(type, property.name);
306
+ if (propertyType && !instanceType.getProperty(property.name)) {
307
+ // assume intersections are children
308
+ additionalGuards.push(factory_1.f.propertyAssignmentDeclaration(property.name, buildGuard(propertyType)));
309
+ }
310
+ }
311
+ }
312
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
313
+ finally {
314
+ try {
315
+ if (_j && !_j.done && (_a = _h.return)) _a.call(_h);
316
+ }
317
+ finally { if (e_5) throw e_5.error; }
318
+ }
319
+ var baseGuard = factory_1.f.call(factory_1.f.field(tId, "instanceIsA"), [instanceType.symbol.name]);
320
+ return additionalGuards.length === 0
321
+ ? baseGuard
322
+ : listLikeGuard("intersection", [
323
+ baseGuard,
324
+ factory_1.f.call(factory_1.f.field(tId, "children"), [factory_1.f.object(additionalGuards)]),
325
+ ]);
326
+ }
327
+ if (type.isIntersection()) {
328
+ return buildIntersectionGuard(type);
329
+ }
330
+ if (isConditionalType(type)) {
331
+ return listLikeGuard("union", [buildGuard(type.resolvedTrueType), buildGuard(type.resolvedFalseType)]);
332
+ }
333
+ if ((type.flags & typescript_1.default.TypeFlags.TypeVariable) !== 0) {
334
+ var constraint = type.checker.getBaseConstraintOfType(type);
335
+ if (!constraint)
336
+ fail("could not find constraint of type parameter");
337
+ return buildGuard(constraint);
338
+ }
339
+ var literals = getLiteral(type);
340
+ if (literals) {
341
+ return listLikeGuard("literal", literals);
342
+ }
343
+ if (typeChecker.isTupleType(type)) {
344
+ var typeArgs = (_c = type.resolvedTypeArguments) !== null && _c !== void 0 ? _c : [];
345
+ return factory_1.f.call(factory_1.f.field(tId, "strictArray"), typeArgs.map(function (x) { return buildGuard(x); }));
346
+ }
347
+ if (typeChecker.isArrayType(type)) {
348
+ var typeArg = (_d = type.typeArguments) === null || _d === void 0 ? void 0 : _d[0];
349
+ return factory_1.f.call(factory_1.f.field(tId, "array"), [typeArg ? buildGuard(typeArg) : factory_1.f.field(tId, "any")]);
350
+ }
351
+ if (type.getCallSignatures().length > 0) {
352
+ return factory_1.f.field(tId, "callback");
353
+ }
354
+ var voidType = typeChecker.getVoidType();
355
+ var undefinedType = typeChecker.getUndefinedType();
356
+ if (type === voidType || type === undefinedType) {
357
+ return factory_1.f.field(tId, "none");
358
+ }
359
+ var anyType = typeChecker.getAnyType();
360
+ if (type === anyType) {
361
+ return factory_1.f.field(tId, "any");
362
+ }
363
+ var stringType = typeChecker.getStringType();
364
+ if (type === stringType) {
365
+ return factory_1.f.field(tId, "string");
366
+ }
367
+ var numberType = typeChecker.getNumberType();
368
+ if (type === numberType) {
369
+ return factory_1.f.field(tId, "number");
370
+ }
371
+ if ((type.flags & typescript_1.default.TypeFlags.Unknown) !== 0) {
372
+ return listLikeGuard("union", [factory_1.f.field(tId, "any"), factory_1.f.field(tId, "none")]);
373
+ }
374
+ if (type.flags & typescript_1.default.TypeFlags.TemplateLiteral) {
375
+ // `${string}-id` becomes an anchored Lua pattern: the literal parts verbatim, each placeholder
376
+ // matching anything, which is as much as a runtime check can tell about the placeholders.
377
+ var template = type;
378
+ var escape_1 = function (text) { return text.replace(/[%^$().[\]*+\-?]/g, function (char) { return "%".concat(char); }); };
379
+ var pattern = "^".concat(template.texts.map(escape_1).join(".*"), "$");
380
+ return factory_1.f.call(factory_1.f.field(tId, "match"), [factory_1.f.string(pattern)]);
381
+ }
382
+ // `Uppercase<T>` and friends are strings with a shape no runtime check can see.
383
+ if (type.flags & typescript_1.default.TypeFlags.StringMapping) {
384
+ return factory_1.f.field(tId, "string");
385
+ }
386
+ var symbol = type.getSymbol();
387
+ if (!symbol) {
388
+ fail("An unknown type was encountered with no symbol: ".concat(typeChecker.typeToString(type)));
389
+ }
390
+ var mapSymbol = typeChecker.resolveName("Map", undefined, typescript_1.default.SymbolFlags.Type, false);
391
+ var readonlyMapSymbol = typeChecker.resolveName("ReadonlyMap", undefined, typescript_1.default.SymbolFlags.Type, false);
392
+ var weakMapSymbol = typeChecker.resolveName("WeakMap", undefined, typescript_1.default.SymbolFlags.Type, false);
393
+ if (symbol === mapSymbol || symbol === readonlyMapSymbol || symbol === weakMapSymbol) {
394
+ var keyType = (_e = type.typeArguments) === null || _e === void 0 ? void 0 : _e[0];
395
+ var valueType = (_f = type.typeArguments) === null || _f === void 0 ? void 0 : _f[1];
396
+ return factory_1.f.call(factory_1.f.field(tId, "map"), [
397
+ keyType ? buildGuard(keyType) : factory_1.f.field(tId, "any"),
398
+ valueType ? buildGuard(valueType) : factory_1.f.field(tId, "any"),
399
+ ]);
400
+ }
401
+ var setSymbol = typeChecker.resolveName("Set", undefined, typescript_1.default.SymbolFlags.Type, false);
402
+ var readonlySetSymbol = typeChecker.resolveName("ReadonlySet", undefined, typescript_1.default.SymbolFlags.Type, false);
403
+ if (symbol === setSymbol || symbol === readonlySetSymbol) {
404
+ var valueType = (_g = type.typeArguments) === null || _g === void 0 ? void 0 : _g[0];
405
+ return factory_1.f.call(factory_1.f.field(tId, "set"), [valueType ? buildGuard(valueType) : factory_1.f.field(tId, "any")]);
406
+ }
407
+ var promiseSymbol = typeChecker.resolveName("Promise", undefined, typescript_1.default.SymbolFlags.Type, false);
408
+ if (symbol === promiseSymbol) {
409
+ return factory_1.f.field("Promise", "is");
410
+ }
411
+ try {
412
+ for (var RBX_TYPES_1 = __values(RBX_TYPES), RBX_TYPES_1_1 = RBX_TYPES_1.next(); !RBX_TYPES_1_1.done; RBX_TYPES_1_1 = RBX_TYPES_1.next()) {
413
+ var guard = RBX_TYPES_1_1.value;
414
+ var guardSymbol = typeChecker.resolveName(guard, undefined, typescript_1.default.SymbolFlags.Type, false);
415
+ if (!guardSymbol && symbol.name === guard) {
416
+ fail("Could not find symbol for ".concat(guard));
417
+ }
418
+ if (symbol === guardSymbol) {
419
+ if (RBX_TYPES_NEW.includes(guard)) {
420
+ return factory_1.f.call(factory_1.f.field(tId, "typeof"), [guard]);
421
+ }
422
+ else {
423
+ return factory_1.f.field(tId, guard);
424
+ }
425
+ }
426
+ }
427
+ }
428
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
429
+ finally {
430
+ try {
431
+ if (RBX_TYPES_1_1 && !RBX_TYPES_1_1.done && (_b = RBX_TYPES_1.return)) _b.call(RBX_TYPES_1);
432
+ }
433
+ finally { if (e_6) throw e_6.error; }
434
+ }
435
+ if (type.isClass()) {
436
+ fail("Class \"".concat(type.symbol.name, "\" was encountered. Flamework does not support generating guards for classes."));
437
+ }
438
+ var isObject = isObjectType(type);
439
+ var indexInfos = type.checker.getIndexInfosOfType(type);
440
+ if (isObject && type.getApparentProperties().length === 0 && indexInfos.length === 0) {
441
+ return factory_1.f.field(tId, "any");
442
+ }
443
+ if (isObject || type.isClassOrInterface()) {
444
+ var guards = [];
445
+ if (type.getApparentProperties().length > 0) {
446
+ guards.push(factory_1.f.call(factory_1.f.field(tId, "interface"), [factory_1.f.object(buildGuardsFromType(type, true))]));
447
+ }
448
+ var indexInfo = indexInfos[0];
449
+ if (indexInfo) {
450
+ if (indexInfos.length > 1) {
451
+ fail("Flamework cannot generate types with multiple index signatures.");
452
+ }
453
+ guards.push(factory_1.f.call(factory_1.f.field(tId, "map"), [buildGuard(indexInfo.keyType), buildGuard(indexInfo.type)]));
454
+ }
455
+ return guards.length > 1 ? listLikeGuard("intersection", guards) : guards[0];
456
+ }
457
+ fail("An unknown type was encountered: ".concat(typeChecker.typeToString(type)));
458
+ }
459
+ function buildUnionGuard(type) {
460
+ var tId = state.getGuardLibrary(file);
461
+ var boolType = type.checker.getBooleanType();
462
+ if (type === boolType) {
463
+ return factory_1.f.field(tId, "boolean");
464
+ }
465
+ var _a = simplifyUnion(type), enums = _a.enums, literals = _a.literals, simplifiedTypes = _a.types;
466
+ var _b = __read(extractTypes(type.checker, simplifiedTypes), 2), isOptional = _b[0], types = _b[1];
467
+ var guards = types.map(function (type) { return buildGuard(type); });
468
+ guards.push.apply(guards, __spreadArray([], __read(enums.map(function (enumId) { return factory_1.f.call(factory_1.f.field(tId, "enum"), [factory_1.f.field("Enum", enumId)]); })), false));
469
+ if (literals.length > 0) {
470
+ guards.push(listLikeGuard("literal", literals));
471
+ }
472
+ var union = guards.length > 1 ? listLikeGuard("union", guards) : guards[0];
473
+ if (!union)
474
+ return factory_1.f.field(tId, "none");
475
+ return isOptional ? factory_1.f.call(factory_1.f.field(tId, "optional"), [union]) : union;
476
+ }
477
+ function buildIntersectionGuard(type) {
478
+ if (type.checker.getIndexInfosOfType(type).length > 1) {
479
+ fail("Flamework cannot generate intersections with multiple index signatures.");
480
+ }
481
+ // We find any disjoint types (strings, numbers, etc) as intersections with them are invalid.
482
+ // Most intersections with disjoint types are used to introduce nominal fields.
483
+ var disjointType = type.types.find(function (v) { return v.flags & tsInternals_1.TYPE_FLAG_DISJOINT_DOMAINS; });
484
+ if (disjointType) {
485
+ return buildGuard(disjointType);
486
+ }
487
+ var guards = type.types.map(buildGuard);
488
+ return listLikeGuard("intersection", guards);
489
+ }
490
+ function buildGuardsFromType(type, isInterfaceType) {
491
+ var e_7, _a;
492
+ var _b, _c;
493
+ if (isInterfaceType === void 0) { isInterfaceType = false; }
494
+ var typeChecker = state.typeChecker;
495
+ var declaration = (0, getDeclarationOfType_1.getDeclarationOfType)(type);
496
+ if (declaration) {
497
+ tracking.push([declaration, type]);
498
+ }
499
+ var guards = new Array();
500
+ try {
501
+ for (var _d = __values(type.getProperties()), _e = _d.next(); !_e.done; _e = _d.next()) {
502
+ var property = _e.value;
503
+ var declaration_1 = property.valueDeclaration;
504
+ var propertyType = typeChecker.getTypeOfPropertyOfType(type, property.name);
505
+ if (!propertyType)
506
+ fail("Could not find type for field");
507
+ if (isInterfaceType && (propertyType.flags & OBJECT_IGNORED_FIELD_TYPES) !== 0) {
508
+ continue;
509
+ }
510
+ if (declaration_1) {
511
+ tracking.push([declaration_1, propertyType]);
512
+ }
513
+ var attribute = buildGuard(propertyType);
514
+ guards.push(factory_1.f.propertyAssignmentDeclaration(property.name, attribute));
515
+ if (declaration_1) {
516
+ (0, assert_1.default)(((_b = tracking.pop()) === null || _b === void 0 ? void 0 : _b[0]) === declaration_1, "Popped value was not expected");
517
+ }
518
+ }
519
+ }
520
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
521
+ finally {
522
+ try {
523
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
524
+ }
525
+ finally { if (e_7) throw e_7.error; }
526
+ }
527
+ if (declaration) {
528
+ (0, assert_1.default)(((_c = tracking.pop()) === null || _c === void 0 ? void 0 : _c[0]) === declaration, "Popped value was not expected");
529
+ }
530
+ return guards;
531
+ }
532
+ /**
533
+ * Emits `t.<guard>(a, b)` for up to two members and `t.<guard>List({ ... })` beyond that.
534
+ *
535
+ * A Luau call has a hard limit on its argument count, so a large union or literal set spelled
536
+ * out as varargs fails to compile; the list variants take a table instead. This does not track
537
+ * the real register count, but fixing that fully would mean moving away from `t`.
538
+ */
539
+ function listLikeGuard(guard, list) {
540
+ var tId = state.getGuardLibrary(file);
541
+ if (list.length <= 2) {
542
+ return factory_1.f.call(factory_1.f.field(tId, guard), list);
543
+ }
544
+ return factory_1.f.call(factory_1.f.field(tId, "".concat(guard, "List")), [list]);
545
+ }
546
+ }
547
+ function simplifyUnion(type) {
548
+ var e_8, _a, e_9, _b;
549
+ var _c, _d;
550
+ var enumType = type.checker.resolveName("Enum", undefined, typescript_1.default.SymbolFlags.Type, false);
551
+ if (type.aliasSymbol &&
552
+ type.aliasSymbol.parent &&
553
+ type.checker.getMergedSymbol(type.aliasSymbol.parent) === enumType) {
554
+ return { enums: [type.aliasSymbol.name], types: [], literals: [] };
555
+ }
556
+ var currentTypes = type.types;
557
+ var possibleEnums = new Map();
558
+ var enums = new Array();
559
+ var types = new Array();
560
+ var literals = new Array();
561
+ var isBoolean = currentTypes.filter(function (v) { return v.flags & typescript_1.default.TypeFlags.BooleanLiteral; }).length === 2;
562
+ if (isBoolean) {
563
+ types.push(type.checker.getBooleanType());
564
+ }
565
+ try {
566
+ for (var currentTypes_1 = __values(currentTypes), currentTypes_1_1 = currentTypes_1.next(); !currentTypes_1_1.done; currentTypes_1_1 = currentTypes_1.next()) {
567
+ var type_2 = currentTypes_1_1.value;
568
+ // We do not need to generate symbol types as they don't exist in Lua.
569
+ if (type_2.flags & typescript_1.default.TypeFlags.ESSymbolLike) {
570
+ continue;
571
+ }
572
+ // This is a full `boolean`, so we can skip the individual literals.
573
+ if (isBoolean && type_2.flags & typescript_1.default.TypeFlags.BooleanLiteral) {
574
+ continue;
575
+ }
576
+ var literal = getLiteral(type_2, true);
577
+ if (literal) {
578
+ literals.push.apply(literals, __spreadArray([], __read(literal), false));
579
+ continue;
580
+ }
581
+ if (!type_2.symbol || !type_2.symbol.parent) {
582
+ types.push(type_2);
583
+ continue;
584
+ }
585
+ var enumKind = type_2.symbol.parent;
586
+ if (!enumKind || !enumKind.parent || type_2.checker.getMergedSymbol(enumKind.parent) !== enumType) {
587
+ types.push(type_2);
588
+ continue;
589
+ }
590
+ if (type_2.symbol === ((_c = enumKind.exports) === null || _c === void 0 ? void 0 : _c.get(type_2.symbol.escapedName))) {
591
+ var enumValues = possibleEnums.get(enumKind);
592
+ if (!enumValues)
593
+ possibleEnums.set(enumKind, (enumValues = new Set()));
594
+ enumValues.add(type_2);
595
+ }
596
+ }
597
+ }
598
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
599
+ finally {
600
+ try {
601
+ if (currentTypes_1_1 && !currentTypes_1_1.done && (_a = currentTypes_1.return)) _a.call(currentTypes_1);
602
+ }
603
+ finally { if (e_8) throw e_8.error; }
604
+ }
605
+ var _loop_1 = function (symbol, set) {
606
+ var e_10, _f;
607
+ // Every item of the enum is present. The namespace also exports `GetEnumItems` and, for some
608
+ // enums, alias constants (`KeyCode.Unknown` is `None`), so only the item interfaces are counted.
609
+ var items = 0;
610
+ (_d = symbol.exports) === null || _d === void 0 ? void 0 : _d.forEach(function (member) {
611
+ if (member.flags & typescript_1.default.SymbolFlags.Interface)
612
+ items++;
613
+ });
614
+ if (set.size === items) {
615
+ enums.push(symbol.name);
616
+ }
617
+ else {
618
+ try {
619
+ for (var set_1 = (e_10 = void 0, __values(set)), set_1_1 = set_1.next(); !set_1_1.done; set_1_1 = set_1.next()) {
620
+ var type_3 = set_1_1.value;
621
+ literals.push(factory_1.f.field(factory_1.f.field("Enum", symbol.name), type_3.symbol.name));
622
+ }
623
+ }
624
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
625
+ finally {
626
+ try {
627
+ if (set_1_1 && !set_1_1.done && (_f = set_1.return)) _f.call(set_1);
628
+ }
629
+ finally { if (e_10) throw e_10.error; }
630
+ }
631
+ }
632
+ };
633
+ try {
634
+ for (var possibleEnums_1 = __values(possibleEnums), possibleEnums_1_1 = possibleEnums_1.next(); !possibleEnums_1_1.done; possibleEnums_1_1 = possibleEnums_1.next()) {
635
+ var _e = __read(possibleEnums_1_1.value, 2), symbol = _e[0], set = _e[1];
636
+ _loop_1(symbol, set);
637
+ }
638
+ }
639
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
640
+ finally {
641
+ try {
642
+ if (possibleEnums_1_1 && !possibleEnums_1_1.done && (_b = possibleEnums_1.return)) _b.call(possibleEnums_1);
643
+ }
644
+ finally { if (e_9) throw e_9.error; }
645
+ }
646
+ return { enums: enums, types: types, literals: literals };
647
+ }
648
+ function extractTypes(typeChecker, types) {
649
+ var undefinedtype = typeChecker.getUndefinedType();
650
+ var voidType = typeChecker.getVoidType();
651
+ return [
652
+ types.some(function (type) { return type === undefinedtype || type === voidType; }),
653
+ types.filter(function (type) { return type !== undefinedtype && type !== voidType; }),
654
+ ];
655
+ }
656
+ function getLiteral(type, withoutEnums) {
657
+ var e_11, _a;
658
+ var _b;
659
+ if (withoutEnums === void 0) { withoutEnums = false; }
660
+ if (type.isStringLiteral() || type.isNumberLiteral()) {
661
+ return [typeof type.value === "string" ? factory_1.f.string(type.value) : factory_1.f.number(type.value)];
662
+ }
663
+ var trueType = type.checker.getTrueType();
664
+ if (type === trueType) {
665
+ return [factory_1.f.bool(true)];
666
+ }
667
+ var falseType = type.checker.getFalseType();
668
+ if (type === falseType) {
669
+ return [factory_1.f.bool(false)];
670
+ }
671
+ if (type.flags & typescript_1.default.TypeFlags.Enum) {
672
+ var declarations = type.symbol.declarations;
673
+ if (!declarations || declarations.length != 1 || !factory_1.f.is.enumDeclaration(declarations[0]))
674
+ return;
675
+ var declaration = declarations[0];
676
+ var memberValues = new Array();
677
+ try {
678
+ for (var _c = __values(declaration.members), _d = _c.next(); !_d.done; _d = _c.next()) {
679
+ var member = _d.value;
680
+ var constant = type.checker.getConstantValue(member);
681
+ if (constant === undefined)
682
+ return;
683
+ memberValues.push(typeof constant === "string" ? factory_1.f.string(constant) : factory_1.f.number(constant));
684
+ }
685
+ }
686
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
687
+ finally {
688
+ try {
689
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
690
+ }
691
+ finally { if (e_11) throw e_11.error; }
692
+ }
693
+ return memberValues;
694
+ }
695
+ if (!withoutEnums) {
696
+ var symbol = type.getSymbol();
697
+ if (!symbol)
698
+ return;
699
+ var enumType = type.checker.resolveName("Enum", undefined, typescript_1.default.SymbolFlags.Type, false);
700
+ if (((_b = symbol.parent) === null || _b === void 0 ? void 0 : _b.parent) && type.checker.getMergedSymbol(symbol.parent.parent) === enumType) {
701
+ return [factory_1.f.field(factory_1.f.field("Enum", symbol.parent.name), symbol.name)];
702
+ }
703
+ }
704
+ }
705
+ function isObjectType(type) {
706
+ return (type.flags & typescript_1.default.TypeFlags.Object) !== 0;
707
+ }
708
+ function isInstanceType(type) {
709
+ return type.getProperty("_nominal_Instance") !== undefined;
710
+ }
711
+ function isConditionalType(type) {
712
+ return (type.flags & typescript_1.default.TypeFlags.Conditional) !== 0;
713
+ }