@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.
- package/README.md +66 -0
- package/flamework-schema.json +76 -0
- package/flamework.config.schema.json +197 -0
- package/out/classes/buildInfo.js +467 -0
- package/out/classes/diagnostics.js +110 -0
- package/out/classes/logger.js +201 -0
- package/out/classes/nodeMetadata.js +232 -0
- package/out/classes/transformState.js +623 -0
- package/out/index.js +75 -0
- package/out/transformations/expressions/transformAccessExpression.js +35 -0
- package/out/transformations/expressions/transformBinaryExpression.js +57 -0
- package/out/transformations/expressions/transformCallExpression.js +33 -0
- package/out/transformations/expressions/transformDeleteExpression.js +22 -0
- package/out/transformations/expressions/transformNewExpression.js +17 -0
- package/out/transformations/expressions/transformUnaryExpression.js +63 -0
- package/out/transformations/macros/intrinsics/components.js +64 -0
- package/out/transformations/macros/intrinsics/env.js +31 -0
- package/out/transformations/macros/intrinsics/guards.js +43 -0
- package/out/transformations/macros/intrinsics/inlining.js +22 -0
- package/out/transformations/macros/intrinsics/networking.js +131 -0
- package/out/transformations/macros/intrinsics/parameters.js +81 -0
- package/out/transformations/macros/intrinsics/paths.js +42 -0
- package/out/transformations/macros/updateComponentConfig.js +409 -0
- package/out/transformations/plugins/nodeFactory.js +159 -0
- package/out/transformations/plugins/pluginHost.js +235 -0
- package/out/transformations/plugins/typeFacade.js +242 -0
- package/out/transformations/statements/transformClassDeclaration.js +282 -0
- package/out/transformations/transformExpression.js +34 -0
- package/out/transformations/transformFile.js +78 -0
- package/out/transformations/transformNetworkingCall.js +566 -0
- package/out/transformations/transformNode.js +27 -0
- package/out/transformations/transformStatement.js +57 -0
- package/out/transformations/transformStatementList.js +64 -0
- package/out/transformations/transformUserMacro.js +698 -0
- package/out/transformer.js +52 -0
- package/out/util/cache.js +10 -0
- package/out/util/constants.js +5 -0
- package/out/util/diagnosticsUtils.js +112 -0
- package/out/util/env.js +267 -0
- package/out/util/factory.js +583 -0
- package/out/util/functions/addLeadingComment.js +13 -0
- package/out/util/functions/arePathsEqual.js +14 -0
- package/out/util/functions/assert.js +17 -0
- package/out/util/functions/buildGuardFromType.js +713 -0
- package/out/util/functions/buildInstanceShape.js +156 -0
- package/out/util/functions/buildSerializerFromType.js +2309 -0
- package/out/util/functions/createPathTranslator.js +54 -0
- package/out/util/functions/emitTypescriptMismatch.js +80 -0
- package/out/util/functions/getDeclarationName.js +23 -0
- package/out/util/functions/getDeclarationOfType.js +7 -0
- package/out/util/functions/getIndexExpression.js +16 -0
- package/out/util/functions/getInstanceTypeFromType.js +75 -0
- package/out/util/functions/getNodeList.js +6 -0
- package/out/util/functions/getPackageJson.js +44 -0
- package/out/util/functions/getSuperClasses.js +51 -0
- package/out/util/functions/isAttributesAccess.js +23 -0
- package/out/util/functions/isCleanBuildDirectory.js +13 -0
- package/out/util/functions/isDefinedType.js +16 -0
- package/out/util/functions/isPathDescendantOf.js +25 -0
- package/out/util/functions/isTupleType.js +10 -0
- package/out/util/functions/parseCommandLine.js +31 -0
- package/out/util/functions/shuffle.js +39 -0
- package/out/util/functions/tryResolve.js +15 -0
- package/out/util/functions/validateConstraintMetadata.js +60 -0
- package/out/util/packages.js +12 -0
- package/out/util/projectConfig.js +221 -0
- package/out/util/schema.js +80 -0
- package/out/util/tsInternals.js +16 -0
- package/out/util/uid.js +227 -0
- package/package.json +45 -0
- package/rojo-schema.json +34 -0
- package/types.d.ts +4 -0
|
@@ -0,0 +1,698 @@
|
|
|
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.transformUserMacro = transformUserMacro;
|
|
43
|
+
exports.getDependencyInjectionMetadata = getDependencyInjectionMetadata;
|
|
44
|
+
var uuid_1 = require("uuid");
|
|
45
|
+
var typescript_1 = __importDefault(require("typescript"));
|
|
46
|
+
var diagnostics_1 = require("../classes/diagnostics");
|
|
47
|
+
var factory_1 = require("../util/factory");
|
|
48
|
+
var buildGuardFromType_1 = require("../util/functions/buildGuardFromType");
|
|
49
|
+
var uid_1 = require("../util/uid");
|
|
50
|
+
var nodeMetadata_1 = require("../classes/nodeMetadata");
|
|
51
|
+
var paths_1 = require("./macros/intrinsics/paths");
|
|
52
|
+
var env_1 = require("./macros/intrinsics/env");
|
|
53
|
+
var parameters_1 = require("./macros/intrinsics/parameters");
|
|
54
|
+
var networking_1 = require("./macros/intrinsics/networking");
|
|
55
|
+
var guards_1 = require("./macros/intrinsics/guards");
|
|
56
|
+
var buildSerializerFromType_1 = require("../util/functions/buildSerializerFromType");
|
|
57
|
+
var isTupleType_1 = require("../util/functions/isTupleType");
|
|
58
|
+
var inlining_1 = require("./macros/intrinsics/inlining");
|
|
59
|
+
var addLeadingComment_1 = require("../util/functions/addLeadingComment");
|
|
60
|
+
var components_1 = require("./macros/intrinsics/components");
|
|
61
|
+
var packages_1 = require("../util/packages");
|
|
62
|
+
function transformUserMacro(state, node, signature) {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
var signatureDeclaration = signature.getDeclaration();
|
|
65
|
+
var nodeMetadata = nodeMetadata_1.NodeMetadata.fromCache(state, signatureDeclaration);
|
|
66
|
+
var args = node.arguments ? __spreadArray([], __read(node.arguments), false) : [];
|
|
67
|
+
var parameters = new Map();
|
|
68
|
+
var highestParameterIndex = -1;
|
|
69
|
+
for (var i = 0; i < getParameterCount(state, signature); i++) {
|
|
70
|
+
// This parameter is passed explicitly, so we don't need to evaluate it.
|
|
71
|
+
if (!isUndefinedArgument(args[i])) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
var targetParameter = state.typeChecker.getParameterType(signature, i).getNonNullableType();
|
|
75
|
+
var userMacro = getUserMacroOfUnion(state, node, targetParameter);
|
|
76
|
+
if (userMacro) {
|
|
77
|
+
parameters.set(i, userMacro);
|
|
78
|
+
highestParameterIndex = Math.max(highestParameterIndex, i);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Every argument has to be visited, not just the ones up to the last generated parameter:
|
|
82
|
+
// arguments beyond it can contain macros of their own, and leaving them untransformed emits a
|
|
83
|
+
// call to a `declare`d function that only fails at runtime. `highestParameterIndex` still
|
|
84
|
+
// determines how far to pad with `nil` so that a generated parameter lands at the right index.
|
|
85
|
+
var argumentCount = Math.max(args.length, highestParameterIndex + 1);
|
|
86
|
+
for (var i = 0; i < argumentCount; i++) {
|
|
87
|
+
var userMacro = parameters.get(i);
|
|
88
|
+
if (userMacro) {
|
|
89
|
+
args[i] = buildUserMacro(state, node, userMacro);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
args[i] = args[i] ? state.transform(args[i]) : factory_1.f.nil();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
var networkingMiddleware = nodeMetadata.getSymbol("intrinsic-middleware");
|
|
96
|
+
if (networkingMiddleware) {
|
|
97
|
+
(0, networking_1.transformNetworkingMiddlewareIntrinsic)(state, signature, args, networkingMiddleware);
|
|
98
|
+
}
|
|
99
|
+
var componentConfigs = nodeMetadata.getSymbol("intrinsic-component-config");
|
|
100
|
+
if (componentConfigs) {
|
|
101
|
+
var decoratorParent = typescript_1.default.findAncestor(node, typescript_1.default.isDecorator);
|
|
102
|
+
if (decoratorParent && factory_1.f.is.classDeclaration(decoratorParent.parent)) {
|
|
103
|
+
(0, components_1.transformComponentConfig)(state, decoratorParent.parent, signature, componentConfigs, args);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
var inlineIntrinsic = nodeMetadata.getSymbol("intrinsic-inline");
|
|
107
|
+
if (inlineIntrinsic && inlineIntrinsic.length === 1) {
|
|
108
|
+
return (0, inlining_1.inlineMacroIntrinsic)(state, node, signature, args, inlineIntrinsic[0]);
|
|
109
|
+
}
|
|
110
|
+
(0, parameters_1.validateParameterConstIntrinsic)(node, signature, (_a = nodeMetadata.getSymbol("intrinsic-const")) !== null && _a !== void 0 ? _a : []);
|
|
111
|
+
// `intrinsic-flamework-rewrite` redirects the call to a real implementation, which is how a
|
|
112
|
+
// `declare`d macro such as `Flamework.implements` reaches `Flamework._implements` at runtime.
|
|
113
|
+
// Without it the emitted call targets a declaration that has no runtime value.
|
|
114
|
+
var callee;
|
|
115
|
+
var rewrite = (_b = nodeMetadata.getSymbol("intrinsic-flamework-rewrite")) === null || _b === void 0 ? void 0 : _b[0];
|
|
116
|
+
if (rewrite) {
|
|
117
|
+
if (!rewrite.parent) {
|
|
118
|
+
diagnostics_1.Diagnostics.error(node, "The rewrite target '".concat(rewrite.name, "' is not declared inside a namespace."));
|
|
119
|
+
}
|
|
120
|
+
var namespace = state.addFileImport(state.getSourceFile(node), packages_1.CORE_PACKAGE, rewrite.parent.name);
|
|
121
|
+
callee = factory_1.f.elementAccessExpression(namespace, rewrite.name);
|
|
122
|
+
}
|
|
123
|
+
callee !== null && callee !== void 0 ? callee : (callee = state.transformNode(node.expression));
|
|
124
|
+
if (typescript_1.default.isNewExpression(node)) {
|
|
125
|
+
return typescript_1.default.factory.updateNewExpression(node, callee, node.typeArguments, args);
|
|
126
|
+
}
|
|
127
|
+
else if (typescript_1.default.isCallExpression(node)) {
|
|
128
|
+
return typescript_1.default.factory.updateCallExpression(node, callee, node.typeArguments, args);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
diagnostics_1.Diagnostics.error(node, "Macro could not be transformed.");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function getDependencyInjectionMetadata(state, node, type, concise) {
|
|
135
|
+
var _a;
|
|
136
|
+
if (concise === void 0) { concise = false; }
|
|
137
|
+
var id = (0, uid_1.getTypeUid)(state, type, node);
|
|
138
|
+
var metadata = (_a = getInjectableMetadata(state, type)) === null || _a === void 0 ? void 0 : _a.map(function (v) {
|
|
139
|
+
return transformUserMacroType(state, node, v);
|
|
140
|
+
});
|
|
141
|
+
if (concise && !metadata) {
|
|
142
|
+
return factory_1.f.string(id);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
var object = {};
|
|
146
|
+
object.id = id;
|
|
147
|
+
if (metadata) {
|
|
148
|
+
object.metadata = metadata ? factory_1.f.array(metadata) : undefined;
|
|
149
|
+
}
|
|
150
|
+
return factory_1.f.object(object);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function getInjectableMetadata(state, type) {
|
|
154
|
+
var injectableConfig = state.typeChecker.getTypeOfPropertyOfType(type, "_flamework_injectable");
|
|
155
|
+
if (injectableConfig) {
|
|
156
|
+
var reflect = state.typeChecker.getTypeOfPropertyOfType(injectableConfig, "metadata");
|
|
157
|
+
if (reflect && (0, isTupleType_1.isTupleType)(state, reflect)) {
|
|
158
|
+
return reflect.typeArguments;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function transformUserMacroType(state, node, type) {
|
|
163
|
+
var macro = getUserMacroOfMany(state, node, type);
|
|
164
|
+
return buildUserMacro(state, node, macro);
|
|
165
|
+
}
|
|
166
|
+
function isUndefinedArgument(argument) {
|
|
167
|
+
return argument ? factory_1.f.is.identifier(argument) && argument.text === "undefined" : true;
|
|
168
|
+
}
|
|
169
|
+
function getLabels(state, type) {
|
|
170
|
+
var e_1, _a;
|
|
171
|
+
if (!(0, isTupleType_1.isTupleType)(state, type)) {
|
|
172
|
+
return {
|
|
173
|
+
kind: "literal",
|
|
174
|
+
value: undefined,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
var names = new Array();
|
|
178
|
+
var declarations = type.target.labeledElementDeclarations;
|
|
179
|
+
if (!declarations) {
|
|
180
|
+
return {
|
|
181
|
+
kind: "literal",
|
|
182
|
+
value: undefined,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
for (var declarations_1 = __values(declarations), declarations_1_1 = declarations_1.next(); !declarations_1_1.done; declarations_1_1 = declarations_1.next()) {
|
|
187
|
+
var namedMember = declarations_1_1.value;
|
|
188
|
+
// TypeScript 5.0+ allows nameless tuple elements, so we'll default to an empty string in that case.
|
|
189
|
+
names.push({
|
|
190
|
+
kind: "literal",
|
|
191
|
+
value: namedMember ? namedMember.name.text : "",
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
196
|
+
finally {
|
|
197
|
+
try {
|
|
198
|
+
if (declarations_1_1 && !declarations_1_1.done && (_a = declarations_1.return)) _a.call(declarations_1);
|
|
199
|
+
}
|
|
200
|
+
finally { if (e_1) throw e_1.error; }
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
kind: "many",
|
|
204
|
+
members: names,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function buildUserMacro(state, node, macro) {
|
|
208
|
+
var e_2, _a;
|
|
209
|
+
if (macro.kind === "generic") {
|
|
210
|
+
var metadata = getGenericMetadata(macro);
|
|
211
|
+
if (metadata) {
|
|
212
|
+
return factory_1.f.asNever(metadata);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else if (macro.kind === "caller") {
|
|
216
|
+
var metadata = getCallerMetadata(macro);
|
|
217
|
+
if (metadata) {
|
|
218
|
+
return factory_1.f.asNever(metadata);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (macro.kind === "many") {
|
|
222
|
+
if (Array.isArray(macro.members)) {
|
|
223
|
+
return factory_1.f.asNever(factory_1.f.array(macro.members.map(function (userMacro) { return buildUserMacro(state, node, userMacro); })));
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
var elements = new Array();
|
|
227
|
+
try {
|
|
228
|
+
for (var _b = __values(macro.members), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
229
|
+
var _d = __read(_c.value, 2), name_1 = _d[0], userMacro = _d[1];
|
|
230
|
+
var expression = buildUserMacro(state, node, userMacro);
|
|
231
|
+
if (factory_1.f.is.nil(expression.expression)) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
elements.push(factory_1.f.propertyAssignmentDeclaration(factory_1.f.string(name_1), expression));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
238
|
+
finally {
|
|
239
|
+
try {
|
|
240
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
241
|
+
}
|
|
242
|
+
finally { if (e_2) throw e_2.error; }
|
|
243
|
+
}
|
|
244
|
+
return factory_1.f.asNever(factory_1.f.object(elements, false));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else if (macro.kind === "literal") {
|
|
248
|
+
var value = macro.value;
|
|
249
|
+
return factory_1.f.asNever(typeof value === "string"
|
|
250
|
+
? factory_1.f.string(value)
|
|
251
|
+
: typeof value === "number"
|
|
252
|
+
? factory_1.f.number(value)
|
|
253
|
+
: typeof value === "boolean"
|
|
254
|
+
? factory_1.f.bool(value)
|
|
255
|
+
: factory_1.f.nil());
|
|
256
|
+
}
|
|
257
|
+
else if (macro.kind === "intrinsic") {
|
|
258
|
+
return factory_1.f.asNever(buildIntrinsicMacro(state, node, macro));
|
|
259
|
+
}
|
|
260
|
+
else if (macro.kind === "sharedRef") {
|
|
261
|
+
var result = buildUserMacro(state, node, macro.value);
|
|
262
|
+
if (typescript_1.default.isSimpleInlineableExpression(result.expression)) {
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
var nextStatement = typescript_1.default.findAncestor(node, factory_1.f.is.statement);
|
|
266
|
+
if (nextStatement && factory_1.f.is.file(nextStatement.parent)) {
|
|
267
|
+
// We are already at the next root, so we don't need to create temporaries.
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
var line = typescript_1.default.getLineOfLocalPosition(node.getSourceFile(), node.getStart());
|
|
271
|
+
var uniqueName = factory_1.f.identifier("".concat(getNodeDebugName(state, node), "_").concat(line + 1), true);
|
|
272
|
+
var comment = typescript_1.default.factory.createEmptyStatement();
|
|
273
|
+
var variable = factory_1.f.variableStatement(uniqueName, result);
|
|
274
|
+
(0, addLeadingComment_1.addLeadingComment)(comment, " Flamework hoisted this macro's metadata (".concat(uniqueName.text, ") to the file root."));
|
|
275
|
+
(0, addLeadingComment_1.addLeadingComment)(variable, " Flamework user macro metadata (line ".concat(line + 1, ")"));
|
|
276
|
+
state.nextRootStatements.push(variable);
|
|
277
|
+
state.prereq(comment);
|
|
278
|
+
return factory_1.f.asNever(uniqueName);
|
|
279
|
+
}
|
|
280
|
+
return factory_1.f.asNever(factory_1.f.nil());
|
|
281
|
+
function getGenericMetadata(macro) {
|
|
282
|
+
if (macro.metadata === "id") {
|
|
283
|
+
return factory_1.f.string((0, uid_1.getTypeUid)(state, macro.target, node));
|
|
284
|
+
}
|
|
285
|
+
if (macro.metadata === "guard") {
|
|
286
|
+
var result = (0, buildGuardFromType_1.buildGuardFromTypeWithDedup)(state, node, macro.target);
|
|
287
|
+
state.prereqList(result.statements);
|
|
288
|
+
return result.guard;
|
|
289
|
+
}
|
|
290
|
+
if (macro.metadata === "text") {
|
|
291
|
+
return factory_1.f.string(state.typeChecker.typeToString(macro.target));
|
|
292
|
+
}
|
|
293
|
+
if (macro.metadata === "dependency" || macro.metadata === "dependencyConcise") {
|
|
294
|
+
return getDependencyInjectionMetadata(state, node, macro.target, macro.metadata === "dependencyConcise");
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function getCallerMetadata(macro) {
|
|
298
|
+
var lineAndCharacter = typescript_1.default.getLineAndCharacterOfPosition(node.getSourceFile(), node.getStart());
|
|
299
|
+
if (macro.metadata === "line") {
|
|
300
|
+
return factory_1.f.number(lineAndCharacter.line + 1);
|
|
301
|
+
}
|
|
302
|
+
if (macro.metadata === "character") {
|
|
303
|
+
return factory_1.f.number(lineAndCharacter.character + 1);
|
|
304
|
+
}
|
|
305
|
+
if (macro.metadata === "width") {
|
|
306
|
+
return factory_1.f.number(node.getWidth());
|
|
307
|
+
}
|
|
308
|
+
if (macro.metadata === "uuid") {
|
|
309
|
+
return factory_1.f.string(getCallsiteUuid(state, node));
|
|
310
|
+
}
|
|
311
|
+
if (macro.metadata === "text") {
|
|
312
|
+
return factory_1.f.string(node.getText());
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function buildIntrinsicMacro(state, node, macro) {
|
|
317
|
+
var _a;
|
|
318
|
+
if (macro.id === "pathglob") {
|
|
319
|
+
var _b = __read(macro.inputs, 1), pathType = _b[0];
|
|
320
|
+
if (!pathType) {
|
|
321
|
+
throw new Error("Invalid intrinsic usage");
|
|
322
|
+
}
|
|
323
|
+
return (0, paths_1.buildPathGlobIntrinsic)(state, node, pathType);
|
|
324
|
+
}
|
|
325
|
+
if (macro.id === "path") {
|
|
326
|
+
var _c = __read(macro.inputs, 1), pathType = _c[0];
|
|
327
|
+
if (!pathType) {
|
|
328
|
+
throw new Error("Invalid intrinsic usage");
|
|
329
|
+
}
|
|
330
|
+
return (0, paths_1.buildPathIntrinsic)(state, node, pathType);
|
|
331
|
+
}
|
|
332
|
+
if (macro.id === "env") {
|
|
333
|
+
var _d = __read(macro.inputs, 2), nameType = _d[0], fallbackType = _d[1];
|
|
334
|
+
if (!nameType) {
|
|
335
|
+
throw new Error("Invalid intrinsic usage");
|
|
336
|
+
}
|
|
337
|
+
return (0, env_1.buildEnvIntrinsic)(state, node, nameType, fallbackType);
|
|
338
|
+
}
|
|
339
|
+
if (macro.id === "obfuscate-obj") {
|
|
340
|
+
var _e = __read(macro.inputs, 2), macroType = _e[0], hashType = _e[1];
|
|
341
|
+
if (!macroType || !hashType) {
|
|
342
|
+
throw new Error("Invalid intrinsic usage");
|
|
343
|
+
}
|
|
344
|
+
var innerMacro = getUserMacroOfMany(state, node, macroType);
|
|
345
|
+
if (!innerMacro) {
|
|
346
|
+
throw new Error("Intrinsic obfuscate-obj received no inner macro.");
|
|
347
|
+
}
|
|
348
|
+
(0, networking_1.transformObfuscatedObjectIntrinsic)(state, innerMacro, hashType);
|
|
349
|
+
return buildUserMacro(state, node, innerMacro);
|
|
350
|
+
}
|
|
351
|
+
if (macro.id === "shuffle-array") {
|
|
352
|
+
var _f = __read(macro.inputs, 1), macroType = _f[0];
|
|
353
|
+
if (!macroType) {
|
|
354
|
+
throw new Error("Invalid intrinsic usage");
|
|
355
|
+
}
|
|
356
|
+
var innerMacro = getUserMacroOfMany(state, node, macroType);
|
|
357
|
+
if (!innerMacro) {
|
|
358
|
+
throw new Error("Intrinsic obfuscate-obj received no inner macro.");
|
|
359
|
+
}
|
|
360
|
+
(0, networking_1.transformShuffleArrayIntrinsic)(state, innerMacro);
|
|
361
|
+
return buildUserMacro(state, node, innerMacro);
|
|
362
|
+
}
|
|
363
|
+
if (macro.id === "tuple-guards") {
|
|
364
|
+
var _g = __read(macro.inputs, 1), tupleType = _g[0];
|
|
365
|
+
if (!tupleType) {
|
|
366
|
+
throw new Error("Invalid intrinsic usage");
|
|
367
|
+
}
|
|
368
|
+
return (0, guards_1.buildTupleGuardsIntrinsic)(state, node, tupleType);
|
|
369
|
+
}
|
|
370
|
+
if (macro.id === "serializer") {
|
|
371
|
+
var _h = __read(macro.inputs, 1), type = _h[0];
|
|
372
|
+
if (!type) {
|
|
373
|
+
throw new Error("Invalid intrinsic usage");
|
|
374
|
+
}
|
|
375
|
+
return (0, buildSerializerFromType_1.buildSerializerFromType)(state, node, type);
|
|
376
|
+
}
|
|
377
|
+
// Networking metadata: the decoder for an argument list (or, given a function type, for its
|
|
378
|
+
// result), only built when the project enables serialization so it costs nothing otherwise. `nil`
|
|
379
|
+
// tells the runtime to pass values through. The matching encoding is generated at each call site
|
|
380
|
+
// (see transformNetworkingCall).
|
|
381
|
+
if (macro.id === "network-decoder" || macro.id === "network-result-decoder") {
|
|
382
|
+
var _j = __read(macro.inputs, 1), type = _j[0];
|
|
383
|
+
if (!type) {
|
|
384
|
+
throw new Error("Invalid intrinsic usage");
|
|
385
|
+
}
|
|
386
|
+
if (((_a = state.projectConfig.networking) === null || _a === void 0 ? void 0 : _a.serialization) !== true) {
|
|
387
|
+
return factory_1.f.nil();
|
|
388
|
+
}
|
|
389
|
+
return macro.id === "network-decoder"
|
|
390
|
+
? (0, buildSerializerFromType_1.buildDecoderFromType)(state, node, type)
|
|
391
|
+
: (0, buildSerializerFromType_1.buildResultDecoderFromType)(state, node, type);
|
|
392
|
+
}
|
|
393
|
+
if (macro.id === "plugin") {
|
|
394
|
+
var _k = __read(macro.inputs, 2), pluginName = _k[0], input = _k[1];
|
|
395
|
+
if (!pluginName || !pluginName.isStringLiteral() || !input) {
|
|
396
|
+
diagnostics_1.Diagnostics.error(node, 'A plugin macro must be declared as `Modding.Intrinsic<"plugin", [id, T], R>` where `id` is a string literal.');
|
|
397
|
+
}
|
|
398
|
+
if (!state.pluginHost) {
|
|
399
|
+
diagnostics_1.Diagnostics.error(node, "The macro type '".concat(pluginName.value, "' requires a plugin, but no plugins are configured."), "Add the plugin to the `plugins` array of the Flamework transformer options in your tsconfig.json.");
|
|
400
|
+
}
|
|
401
|
+
var transform = state.pluginHost.executeMacroType(pluginName.value, input, node);
|
|
402
|
+
if (!transform) {
|
|
403
|
+
var registered = state.pluginHost.getRegisteredMacroTypes();
|
|
404
|
+
diagnostics_1.Diagnostics.error(node, "No loaded plugin registered the macro type '".concat(pluginName.value, "'."), registered.length > 0
|
|
405
|
+
? "Registered macro types: ".concat(registered.join(", "))
|
|
406
|
+
: "No plugin registered any macro types.");
|
|
407
|
+
}
|
|
408
|
+
return transform;
|
|
409
|
+
}
|
|
410
|
+
throw "Unexpected intrinsic ID '".concat(macro.id, "' with ").concat(macro.inputs.length, " inputs");
|
|
411
|
+
}
|
|
412
|
+
function getMetadataFromType(metadataType) {
|
|
413
|
+
if (metadataType.isStringLiteral()) {
|
|
414
|
+
return metadataType.value;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
function getUserMacroOfMany(state, node, target) {
|
|
418
|
+
var e_3, _a, e_4, _b, e_5, _c;
|
|
419
|
+
var sharedRefMetadata = state.typeChecker.getTypeOfPropertyOfType(target, "_flamework_macro_shared_ref");
|
|
420
|
+
// A basic macro is a constant already, so `Constant` around it changes nothing and the value
|
|
421
|
+
// stays inline.
|
|
422
|
+
var basicUserMacro = getBasicUserMacro(state, node, target);
|
|
423
|
+
if (basicUserMacro) {
|
|
424
|
+
return basicUserMacro;
|
|
425
|
+
}
|
|
426
|
+
// `Constant<Emit<T>>` carries both markers; the shared-ref one has to win or the `Constant` is
|
|
427
|
+
// dropped and the table is rebuilt on every call.
|
|
428
|
+
if (sharedRefMetadata) {
|
|
429
|
+
return {
|
|
430
|
+
kind: "sharedRef",
|
|
431
|
+
type: sharedRefMetadata,
|
|
432
|
+
value: getUserMacroOfMany(state, node, sharedRefMetadata),
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
var manyMetadata = state.typeChecker.getTypeOfPropertyOfType(target, "_flamework_macro_many");
|
|
436
|
+
if (manyMetadata) {
|
|
437
|
+
return getUserMacroOfMany(state, node, manyMetadata);
|
|
438
|
+
}
|
|
439
|
+
if ((0, isTupleType_1.isTupleType)(state, target)) {
|
|
440
|
+
var userMacros = new Array();
|
|
441
|
+
try {
|
|
442
|
+
for (var _d = __values(state.typeChecker.getTypeArguments(target)), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
443
|
+
var member = _e.value;
|
|
444
|
+
var userMacro = getUserMacroOfMany(state, node, member);
|
|
445
|
+
userMacros.push(userMacro);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
449
|
+
finally {
|
|
450
|
+
try {
|
|
451
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
452
|
+
}
|
|
453
|
+
finally { if (e_3) throw e_3.error; }
|
|
454
|
+
}
|
|
455
|
+
return {
|
|
456
|
+
kind: "many",
|
|
457
|
+
members: userMacros,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
else if (state.typeChecker.isArrayType(target)) {
|
|
461
|
+
var targetType = state.typeChecker.getTypeArguments(target)[0];
|
|
462
|
+
var constituents = targetType.isUnion() ? targetType.types : [targetType];
|
|
463
|
+
var userMacros = new Array();
|
|
464
|
+
try {
|
|
465
|
+
for (var constituents_1 = __values(constituents), constituents_1_1 = constituents_1.next(); !constituents_1_1.done; constituents_1_1 = constituents_1.next()) {
|
|
466
|
+
var member = constituents_1_1.value;
|
|
467
|
+
// `never` may be encountered when a union has no constituents, so we should just return an empty array.
|
|
468
|
+
if (member.flags & typescript_1.default.TypeFlags.Never) {
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
var userMacro = getUserMacroOfMany(state, node, member);
|
|
472
|
+
userMacros.push(userMacro);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
476
|
+
finally {
|
|
477
|
+
try {
|
|
478
|
+
if (constituents_1_1 && !constituents_1_1.done && (_b = constituents_1.return)) _b.call(constituents_1);
|
|
479
|
+
}
|
|
480
|
+
finally { if (e_4) throw e_4.error; }
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
kind: "many",
|
|
484
|
+
members: userMacros,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
else if (isObjectType(target)) {
|
|
488
|
+
var userMacros = new Map();
|
|
489
|
+
try {
|
|
490
|
+
for (var _f = __values(target.getProperties()), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
491
|
+
var member = _g.value;
|
|
492
|
+
var memberType = state.typeChecker.getTypeOfPropertyOfType(target, member.name);
|
|
493
|
+
if (!memberType)
|
|
494
|
+
continue;
|
|
495
|
+
var userMacro = getUserMacroOfMany(state, node, memberType);
|
|
496
|
+
userMacros.set(member.name, userMacro);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
500
|
+
finally {
|
|
501
|
+
try {
|
|
502
|
+
if (_g && !_g.done && (_c = _f.return)) _c.call(_f);
|
|
503
|
+
}
|
|
504
|
+
finally { if (e_5) throw e_5.error; }
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
kind: "many",
|
|
508
|
+
members: userMacros,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
else if (target.isStringLiteral() || target.isNumberLiteral()) {
|
|
512
|
+
return {
|
|
513
|
+
kind: "literal",
|
|
514
|
+
value: target.value,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
else if (target.flags & typescript_1.default.TypeFlags.Undefined) {
|
|
518
|
+
return {
|
|
519
|
+
kind: "literal",
|
|
520
|
+
value: undefined,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
else if (target.flags & typescript_1.default.TypeFlags.BooleanLiteral) {
|
|
524
|
+
return {
|
|
525
|
+
kind: "literal",
|
|
526
|
+
value: target.regularType === state.typeChecker.getTrueType() ? true : false,
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
diagnostics_1.Diagnostics.error(node, "Unknown type '".concat(target.checker.typeToString(target), "' encountered"));
|
|
530
|
+
}
|
|
531
|
+
function getBasicUserMacro(state, node, target) {
|
|
532
|
+
var genericMetadata = state.typeChecker.getTypeOfPropertyOfType(target, "_flamework_macro_generic");
|
|
533
|
+
if (genericMetadata) {
|
|
534
|
+
var targetType = state.typeChecker.getTypeOfPropertyOfType(genericMetadata, "0");
|
|
535
|
+
var metadataType = state.typeChecker.getTypeOfPropertyOfType(genericMetadata, "1");
|
|
536
|
+
if (!targetType)
|
|
537
|
+
return;
|
|
538
|
+
if (!metadataType)
|
|
539
|
+
return;
|
|
540
|
+
var metadata = getMetadataFromType(metadataType);
|
|
541
|
+
if (!metadata) {
|
|
542
|
+
diagnostics_1.Diagnostics.error(node, "Flamework encountered invalid metadata: '".concat(state.typeChecker.typeToString(metadataType), "'"));
|
|
543
|
+
}
|
|
544
|
+
return {
|
|
545
|
+
kind: "generic",
|
|
546
|
+
target: targetType,
|
|
547
|
+
metadata: metadata,
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
var callerMetadata = state.typeChecker.getTypeOfPropertyOfType(target, "_flamework_macro_caller");
|
|
551
|
+
if (callerMetadata) {
|
|
552
|
+
var metadata = getMetadataFromType(callerMetadata);
|
|
553
|
+
if (!metadata)
|
|
554
|
+
return;
|
|
555
|
+
return {
|
|
556
|
+
kind: "caller",
|
|
557
|
+
metadata: metadata,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
var hashMetadata = state.typeChecker.getTypeOfPropertyOfType(target, "_flamework_macro_hash");
|
|
561
|
+
if (hashMetadata) {
|
|
562
|
+
var text = state.typeChecker.getTypeOfPropertyOfType(hashMetadata, "0");
|
|
563
|
+
var context = state.typeChecker.getTypeOfPropertyOfType(hashMetadata, "1");
|
|
564
|
+
var isObfuscation = state.typeChecker.getTypeOfPropertyOfType(hashMetadata, "2");
|
|
565
|
+
if (!text || !text.isStringLiteral())
|
|
566
|
+
return;
|
|
567
|
+
if (!context)
|
|
568
|
+
return;
|
|
569
|
+
var contextName = context.isStringLiteral() ? context.value : "@";
|
|
570
|
+
return {
|
|
571
|
+
kind: "literal",
|
|
572
|
+
value: isObfuscation
|
|
573
|
+
? state.obfuscateText(text.value, contextName)
|
|
574
|
+
: state.buildInfo.hashString(text.value, contextName),
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
var nonNullableTarget = target.getNonNullableType();
|
|
578
|
+
var labelMetadata = state.typeChecker.getTypeOfPropertyOfType(nonNullableTarget, "_flamework_macro_tuple_labels");
|
|
579
|
+
if (labelMetadata) {
|
|
580
|
+
return getLabels(state, labelMetadata);
|
|
581
|
+
}
|
|
582
|
+
var intrinsicMetadata = state.typeChecker.getTypeOfPropertyOfType(nonNullableTarget, "_flamework_intrinsic");
|
|
583
|
+
if (intrinsicMetadata) {
|
|
584
|
+
if ((0, isTupleType_1.isTupleType)(state, intrinsicMetadata) && intrinsicMetadata.typeArguments) {
|
|
585
|
+
var _a = __read(intrinsicMetadata.typeArguments), id = _a[0], inputs = _a.slice(1);
|
|
586
|
+
if (!id || !id.isStringLiteral())
|
|
587
|
+
return;
|
|
588
|
+
return {
|
|
589
|
+
kind: "intrinsic",
|
|
590
|
+
id: id.value,
|
|
591
|
+
inputs: inputs,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
function getUserMacroOfType(state, node, target) {
|
|
597
|
+
// The shared-ref marker is only inspected on the way through `getUserMacroOfMany`, so without
|
|
598
|
+
// this a `Modding.Caller.Constant<T>` parameter that is not wrapped in `Modding.Emit` generates
|
|
599
|
+
// no argument at all -- the macro silently does not fire and the parameter is nil at runtime.
|
|
600
|
+
// It is checked ahead of the `Emit` marker because `Constant<Emit<T>>` carries both, and finding
|
|
601
|
+
// `Emit` first silently dropped the `Constant`.
|
|
602
|
+
if (state.typeChecker.getTypeOfPropertyOfType(target, "_flamework_macro_shared_ref")) {
|
|
603
|
+
return getUserMacroOfMany(state, node, target);
|
|
604
|
+
}
|
|
605
|
+
var manyMetadata = state.typeChecker.getTypeOfPropertyOfType(target, "_flamework_macro_many");
|
|
606
|
+
if (manyMetadata) {
|
|
607
|
+
return getUserMacroOfMany(state, node, manyMetadata);
|
|
608
|
+
}
|
|
609
|
+
return getBasicUserMacro(state, node, target);
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* This allows user macros to specify signatures that can accept non-metadata, like in Flamework components.
|
|
613
|
+
* Multiple modding types in a single parameter aren't supported, and Flamework will choose a random one.
|
|
614
|
+
*
|
|
615
|
+
* For example, `string | Modding.Target.Id<T>`, will generate the ID for `T`, but also allow users to pass in one manually.
|
|
616
|
+
*/
|
|
617
|
+
function getUserMacroOfUnion(state, node, target) {
|
|
618
|
+
var e_6, _a;
|
|
619
|
+
if (!target.isUnion()) {
|
|
620
|
+
return getUserMacroOfType(state, node, target);
|
|
621
|
+
}
|
|
622
|
+
try {
|
|
623
|
+
for (var _b = __values(target.types), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
624
|
+
var constituent = _c.value;
|
|
625
|
+
var macro = getUserMacroOfType(state, node, constituent);
|
|
626
|
+
if (macro) {
|
|
627
|
+
return macro;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
632
|
+
finally {
|
|
633
|
+
try {
|
|
634
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
635
|
+
}
|
|
636
|
+
finally { if (e_6) throw e_6.error; }
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
function isObjectType(type) {
|
|
640
|
+
return type.isIntersection() ? type.types.every(isObjectType) : (type.flags & typescript_1.default.TypeFlags.Object) !== 0;
|
|
641
|
+
}
|
|
642
|
+
function getParameterCount(state, signature) {
|
|
643
|
+
var length = signature.parameters.length;
|
|
644
|
+
if (typescript_1.default.signatureHasRestParameter(signature)) {
|
|
645
|
+
var restType = state.typeChecker.getTypeOfSymbol(signature.parameters[length - 1]);
|
|
646
|
+
if ((0, isTupleType_1.isTupleType)(state, restType)) {
|
|
647
|
+
return length + restType.target.fixedLength - (restType.target.hasRestElement ? 0 : 1);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return length;
|
|
651
|
+
}
|
|
652
|
+
/** Namespace for the callsite uuids; any fixed uuid works, it only has to never change. */
|
|
653
|
+
var CALLSITE_UUID_NAMESPACE = "6f4c1d2e-8b3a-4e5f-9c7d-2a1b0e9f8d7c";
|
|
654
|
+
/**
|
|
655
|
+
* A uuid that is unique per callsite and identical across the compilations of one build.
|
|
656
|
+
*
|
|
657
|
+
* It is derived from the package, the file, the enclosing declaration and the offset within it, so
|
|
658
|
+
* every file a watcher recompiles agrees with the ones it did not, and without obfuscation two
|
|
659
|
+
* builds of the same source emit the same value. A random uuid per compilation would rename every
|
|
660
|
+
* remote folder on every rebuild.
|
|
661
|
+
*
|
|
662
|
+
* Under obfuscation the namespace is the build seed instead of a constant, so the uuids -- the
|
|
663
|
+
* names of every remote -- change with every build. A cheat that mapped them once would otherwise
|
|
664
|
+
* keep its map through every release.
|
|
665
|
+
*/
|
|
666
|
+
function getCallsiteUuid(state, node) {
|
|
667
|
+
var file = state.getSourceFile(node);
|
|
668
|
+
var declaration = typescript_1.default.findAncestor(node, isCallsiteScope);
|
|
669
|
+
var declarationName = (declaration === null || declaration === void 0 ? void 0 : declaration.name) && factory_1.f.is.identifier(declaration.name) ? declaration.name.text : "";
|
|
670
|
+
var offset = declaration ? node.getStart() - declaration.getStart() : node.getStart();
|
|
671
|
+
var key = "".concat(state.packageName, ":").concat(state.getFileId(file), "@").concat(declarationName, "+").concat(offset);
|
|
672
|
+
var namespace = state.config.obfuscation ? state.buildInfo.getBuildSeed() : CALLSITE_UUID_NAMESPACE;
|
|
673
|
+
return (0, uuid_1.v5)(key, namespace);
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* The declarations a callsite id is anchored to: the units a user names and moves around as one.
|
|
677
|
+
*
|
|
678
|
+
* TypeScript's own `isNamedDeclaration` accepts anything with a `name` property, which includes the
|
|
679
|
+
* property access in `callsite().uuid`, so it cannot be used here.
|
|
680
|
+
*/
|
|
681
|
+
function isCallsiteScope(node) {
|
|
682
|
+
return (typescript_1.default.isVariableDeclaration(node) ||
|
|
683
|
+
typescript_1.default.isFunctionDeclaration(node) ||
|
|
684
|
+
typescript_1.default.isMethodDeclaration(node) ||
|
|
685
|
+
typescript_1.default.isPropertyDeclaration(node) ||
|
|
686
|
+
typescript_1.default.isClassDeclaration(node) ||
|
|
687
|
+
typescript_1.default.isGetAccessorDeclaration(node) ||
|
|
688
|
+
typescript_1.default.isSetAccessorDeclaration(node));
|
|
689
|
+
}
|
|
690
|
+
function getNodeDebugName(state, node) {
|
|
691
|
+
if (factory_1.f.is.call(node)) {
|
|
692
|
+
var symbol = state.getSymbol(node.expression);
|
|
693
|
+
if (symbol) {
|
|
694
|
+
return symbol.name;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return "macro";
|
|
698
|
+
}
|