@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,159 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.unwrapNode = unwrapNode;
|
|
23
|
+
exports.createNodeFactory = createNodeFactory;
|
|
24
|
+
exports.createNodeHandle = handle;
|
|
25
|
+
var typescript_1 = __importDefault(require("typescript"));
|
|
26
|
+
var factory_1 = require("../../util/factory");
|
|
27
|
+
/**
|
|
28
|
+
* Plugins build nodes through this factory rather than touching `ts.factory`, so the emitted AST
|
|
29
|
+
* stays valid regardless of what a plugin does. Each returned handle is an opaque `Node` whose
|
|
30
|
+
* underlying `ts.Node` is recovered with {@link unwrapNode}.
|
|
31
|
+
*/
|
|
32
|
+
var NODES = new WeakMap();
|
|
33
|
+
function handle(node) {
|
|
34
|
+
var result = {};
|
|
35
|
+
NODES.set(result, node);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
function unwrapNode(node) {
|
|
39
|
+
var result = NODES.get(node);
|
|
40
|
+
if (!result) {
|
|
41
|
+
throw new Error("received a Node that was not created by this transformer's factory");
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
function expression(node) {
|
|
46
|
+
var result = unwrapNode(node);
|
|
47
|
+
if (!typescript_1.default.isExpression(result)) {
|
|
48
|
+
throw new Error("expected an expression, got ".concat(typescript_1.default.SyntaxKind[result.kind]));
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
function statement(node) {
|
|
53
|
+
var result = unwrapNode(node);
|
|
54
|
+
if (!typescript_1.default.isStatement(result)) {
|
|
55
|
+
throw new Error("expected a statement, got ".concat(typescript_1.default.SyntaxKind[result.kind]));
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
var BINARY_OPERATORS = {
|
|
60
|
+
"+": typescript_1.default.SyntaxKind.PlusToken,
|
|
61
|
+
"-": typescript_1.default.SyntaxKind.MinusToken,
|
|
62
|
+
"*": typescript_1.default.SyntaxKind.AsteriskToken,
|
|
63
|
+
"/": typescript_1.default.SyntaxKind.SlashToken,
|
|
64
|
+
"%": typescript_1.default.SyntaxKind.PercentToken,
|
|
65
|
+
"==": typescript_1.default.SyntaxKind.EqualsEqualsEqualsToken,
|
|
66
|
+
"!=": typescript_1.default.SyntaxKind.ExclamationEqualsEqualsToken,
|
|
67
|
+
"<": typescript_1.default.SyntaxKind.LessThanToken,
|
|
68
|
+
"<=": typescript_1.default.SyntaxKind.LessThanEqualsToken,
|
|
69
|
+
">": typescript_1.default.SyntaxKind.GreaterThanToken,
|
|
70
|
+
">=": typescript_1.default.SyntaxKind.GreaterThanEqualsToken,
|
|
71
|
+
"&&": typescript_1.default.SyntaxKind.AmpersandAmpersandToken,
|
|
72
|
+
"||": typescript_1.default.SyntaxKind.BarBarToken,
|
|
73
|
+
"??": typescript_1.default.SyntaxKind.QuestionQuestionToken,
|
|
74
|
+
};
|
|
75
|
+
function createNodeFactory() {
|
|
76
|
+
return {
|
|
77
|
+
expr: {
|
|
78
|
+
string: function (value) { return handle(factory_1.f.string(value)); },
|
|
79
|
+
number: function (value) {
|
|
80
|
+
return handle(value < 0
|
|
81
|
+
? typescript_1.default.factory.createPrefixUnaryExpression(typescript_1.default.SyntaxKind.MinusToken, typescript_1.default.factory.createNumericLiteral(-value))
|
|
82
|
+
: typescript_1.default.factory.createNumericLiteral(value));
|
|
83
|
+
},
|
|
84
|
+
bool: function (value) { return handle(value ? typescript_1.default.factory.createTrue() : typescript_1.default.factory.createFalse()); },
|
|
85
|
+
nil: function () { return handle(typescript_1.default.factory.createIdentifier("undefined")); },
|
|
86
|
+
identifier: function (name, unique) {
|
|
87
|
+
return handle(unique
|
|
88
|
+
? typescript_1.default.factory.createUniqueName(name, typescript_1.default.GeneratedIdentifierFlags.Optimistic)
|
|
89
|
+
: typescript_1.default.factory.createIdentifier(name));
|
|
90
|
+
},
|
|
91
|
+
array: function (values) { return handle(typescript_1.default.factory.createArrayLiteralExpression(values.map(expression))); },
|
|
92
|
+
object: function (fields) {
|
|
93
|
+
var entries = Array.isArray(fields)
|
|
94
|
+
? fields
|
|
95
|
+
: Object.entries(fields).map(function (_a) {
|
|
96
|
+
var _b = __read(_a, 2), name = _b[0], value = _b[1];
|
|
97
|
+
return ({ name: name, value: value });
|
|
98
|
+
});
|
|
99
|
+
return handle(typescript_1.default.factory.createObjectLiteralExpression(entries.map(function (v) {
|
|
100
|
+
return typescript_1.default.factory.createPropertyAssignment(createPropertyName(v.name), expression(v.value));
|
|
101
|
+
}), true));
|
|
102
|
+
},
|
|
103
|
+
call: function (target, args) {
|
|
104
|
+
return handle(typescript_1.default.factory.createCallExpression(expression(target), undefined, (args !== null && args !== void 0 ? args : []).map(expression)));
|
|
105
|
+
},
|
|
106
|
+
new: function (target, args) {
|
|
107
|
+
return handle(typescript_1.default.factory.createNewExpression(expression(target), undefined, (args !== null && args !== void 0 ? args : []).map(expression)));
|
|
108
|
+
},
|
|
109
|
+
property: function (target, name) {
|
|
110
|
+
return handle(typescript_1.default.factory.createPropertyAccessExpression(expression(target), name));
|
|
111
|
+
},
|
|
112
|
+
element: function (target, index) {
|
|
113
|
+
return handle(typescript_1.default.factory.createElementAccessExpression(expression(target), expression(index)));
|
|
114
|
+
},
|
|
115
|
+
binary: function (left, operator, right) {
|
|
116
|
+
var token = BINARY_OPERATORS[operator];
|
|
117
|
+
if (token === undefined) {
|
|
118
|
+
throw new Error("unsupported binary operator '".concat(operator, "'"));
|
|
119
|
+
}
|
|
120
|
+
return handle(typescript_1.default.factory.createBinaryExpression(expression(left), token, expression(right)));
|
|
121
|
+
},
|
|
122
|
+
not: function (value) {
|
|
123
|
+
return handle(typescript_1.default.factory.createPrefixUnaryExpression(typescript_1.default.SyntaxKind.ExclamationToken, expression(value)));
|
|
124
|
+
},
|
|
125
|
+
conditional: function (condition, whenTrue, whenFalse) {
|
|
126
|
+
return handle(typescript_1.default.factory.createConditionalExpression(expression(condition), undefined, expression(whenTrue), undefined, expression(whenFalse)));
|
|
127
|
+
},
|
|
128
|
+
arrow: function (parameters, body) {
|
|
129
|
+
return handle(typescript_1.default.factory.createArrowFunction(undefined, undefined, parameters.map(function (name) {
|
|
130
|
+
return typescript_1.default.factory.createParameterDeclaration(undefined, undefined, name, undefined, undefined);
|
|
131
|
+
}), undefined, undefined, Array.isArray(body)
|
|
132
|
+
? typescript_1.default.factory.createBlock(body.map(statement), true)
|
|
133
|
+
: expression(body)));
|
|
134
|
+
},
|
|
135
|
+
parenthesize: function (value) { return handle(typescript_1.default.factory.createParenthesizedExpression(expression(value))); },
|
|
136
|
+
},
|
|
137
|
+
stmt: {
|
|
138
|
+
variable: function (name, value) {
|
|
139
|
+
return handle(typescript_1.default.factory.createVariableStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([
|
|
140
|
+
typescript_1.default.factory.createVariableDeclaration(expression(name), undefined, undefined, expression(value)),
|
|
141
|
+
], typescript_1.default.NodeFlags.Const)));
|
|
142
|
+
},
|
|
143
|
+
expression: function (value) { return handle(typescript_1.default.factory.createExpressionStatement(expression(value))); },
|
|
144
|
+
return: function (value) {
|
|
145
|
+
return handle(typescript_1.default.factory.createReturnStatement(value ? expression(value) : undefined));
|
|
146
|
+
},
|
|
147
|
+
block: function (statements) { return handle(typescript_1.default.factory.createBlock(statements.map(statement), true)); },
|
|
148
|
+
if: function (condition, whenTrue, whenFalse) {
|
|
149
|
+
return handle(typescript_1.default.factory.createIfStatement(expression(condition), statement(whenTrue), whenFalse ? statement(whenFalse) : undefined));
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Object keys that are not valid identifiers have to be emitted as string literals.
|
|
156
|
+
*/
|
|
157
|
+
function createPropertyName(name) {
|
|
158
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? typescript_1.default.factory.createIdentifier(name) : factory_1.f.string(name);
|
|
159
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __values = (this && this.__values) || function(o) {
|
|
3
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
4
|
+
if (m) return m.call(o);
|
|
5
|
+
if (o && typeof o.length === "number") return {
|
|
6
|
+
next: function () {
|
|
7
|
+
if (o && i >= o.length) o = void 0;
|
|
8
|
+
return { value: o && o[i++], done: !o };
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
12
|
+
};
|
|
13
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
14
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
15
|
+
if (!m) return o;
|
|
16
|
+
var i = m.call(o), r, ar = [], e;
|
|
17
|
+
try {
|
|
18
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
19
|
+
}
|
|
20
|
+
catch (error) { e = { error: error }; }
|
|
21
|
+
finally {
|
|
22
|
+
try {
|
|
23
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
24
|
+
}
|
|
25
|
+
finally { if (e) throw e.error; }
|
|
26
|
+
}
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
30
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
31
|
+
if (ar || !(i in from)) {
|
|
32
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
33
|
+
ar[i] = from[i];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
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.createPluginHost = createPluginHost;
|
|
43
|
+
var path_1 = __importDefault(require("path"));
|
|
44
|
+
var typescript_1 = __importDefault(require("typescript"));
|
|
45
|
+
var diagnostics_1 = require("../../classes/diagnostics");
|
|
46
|
+
var factory_1 = require("../../util/factory");
|
|
47
|
+
var nodeFactory_1 = require("./nodeFactory");
|
|
48
|
+
var typeFacade_1 = require("./typeFacade");
|
|
49
|
+
var packages_1 = require("../../util/packages");
|
|
50
|
+
/**
|
|
51
|
+
* The callbacks each plugin module registered when it was first loaded, keyed by its resolved path.
|
|
52
|
+
*
|
|
53
|
+
* Node caches modules, so requiring a plugin a second time does not run its top level again and
|
|
54
|
+
* registers nothing. A transformer state is created for every compilation -- every rebuild in watch
|
|
55
|
+
* mode -- so the callbacks have to outlive the state that first loaded them.
|
|
56
|
+
*/
|
|
57
|
+
var LOADED_PLUGINS = new Map();
|
|
58
|
+
/**
|
|
59
|
+
* Loads and drives Flamework transformer plugins.
|
|
60
|
+
*
|
|
61
|
+
* Plugins are ordinary CommonJS modules loaded into the compiler process -- they are build-time
|
|
62
|
+
* code the project already trusts, exactly like the transformer itself. The `Type` and `Node`
|
|
63
|
+
* facades exist to give plugins an API that survives TypeScript upgrades, not to sandbox them.
|
|
64
|
+
*/
|
|
65
|
+
function createPluginHost(state) {
|
|
66
|
+
var e_1, _a;
|
|
67
|
+
var _b;
|
|
68
|
+
var pluginConfigs = state.config.plugins;
|
|
69
|
+
if (!pluginConfigs || pluginConfigs.length === 0) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
// Loaded lazily so that projects without plugins never pay for resolving the plugin module.
|
|
73
|
+
var registry = requirePluginRegistry(state);
|
|
74
|
+
var types = (0, typeFacade_1.createTypeFactory)(state);
|
|
75
|
+
var factory = (0, nodeFactory_1.createNodeFactory)();
|
|
76
|
+
var macroTypes = new Map();
|
|
77
|
+
var cache = new Map();
|
|
78
|
+
try {
|
|
79
|
+
for (var pluginConfigs_1 = __values(pluginConfigs), pluginConfigs_1_1 = pluginConfigs_1.next(); !pluginConfigs_1_1.done; pluginConfigs_1_1 = pluginConfigs_1.next()) {
|
|
80
|
+
var pluginConfig = pluginConfigs_1_1.value;
|
|
81
|
+
var normalized = typeof pluginConfig === "string" ? { path: pluginConfig } : pluginConfig;
|
|
82
|
+
loadPlugin(normalized.path, (_b = normalized.options) !== null && _b !== void 0 ? _b : {});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
86
|
+
finally {
|
|
87
|
+
try {
|
|
88
|
+
if (pluginConfigs_1_1 && !pluginConfigs_1_1.done && (_a = pluginConfigs_1.return)) _a.call(pluginConfigs_1);
|
|
89
|
+
}
|
|
90
|
+
finally { if (e_1) throw e_1.error; }
|
|
91
|
+
}
|
|
92
|
+
return { executeMacroType: executeMacroType, getRegisteredMacroTypes: function () { return __spreadArray([], __read(macroTypes.keys()), false); } };
|
|
93
|
+
function loadPlugin(pluginPath, options) {
|
|
94
|
+
var e_2, _a;
|
|
95
|
+
var resolved = resolvePluginPath(state, pluginPath);
|
|
96
|
+
var callbacks = LOADED_PLUGINS.get(resolved);
|
|
97
|
+
if (!callbacks) {
|
|
98
|
+
try {
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
100
|
+
require(resolved);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
throw new Error("Failed to load Flamework plugin '".concat(pluginPath, "': ").concat(e instanceof Error ? e.message : e));
|
|
104
|
+
}
|
|
105
|
+
callbacks = registry.drainRegisteredPlugins();
|
|
106
|
+
if (callbacks.length === 0) {
|
|
107
|
+
throw new Error("Flamework plugin '".concat(pluginPath, "' did not call registerPlugin(). ") +
|
|
108
|
+
"Plugins must be CommonJS modules that call registerPlugin at the top level.");
|
|
109
|
+
}
|
|
110
|
+
LOADED_PLUGINS.set(resolved, callbacks);
|
|
111
|
+
}
|
|
112
|
+
var api = {
|
|
113
|
+
factory: factory,
|
|
114
|
+
options: options,
|
|
115
|
+
registerMacroType: function (id, handler) {
|
|
116
|
+
var existing = macroTypes.get(id);
|
|
117
|
+
if (existing) {
|
|
118
|
+
throw new Error("Flamework plugin '".concat(pluginPath, "' registered the macro type '").concat(id, "', ") +
|
|
119
|
+
"which was already registered by '".concat(existing.pluginName, "'."));
|
|
120
|
+
}
|
|
121
|
+
macroTypes.set(id, { handler: handler, pluginName: pluginPath });
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
try {
|
|
125
|
+
for (var callbacks_1 = __values(callbacks), callbacks_1_1 = callbacks_1.next(); !callbacks_1_1.done; callbacks_1_1 = callbacks_1.next()) {
|
|
126
|
+
var plugin = callbacks_1_1.value;
|
|
127
|
+
plugin(api);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
131
|
+
finally {
|
|
132
|
+
try {
|
|
133
|
+
if (callbacks_1_1 && !callbacks_1_1.done && (_a = callbacks_1.return)) _a.call(callbacks_1);
|
|
134
|
+
}
|
|
135
|
+
finally { if (e_2) throw e_2.error; }
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function executeMacroType(name, type, node) {
|
|
139
|
+
var registered = macroTypes.get(name);
|
|
140
|
+
if (!registered) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
var file = state.getSourceFile(node);
|
|
144
|
+
var cacheKey = "".concat(name, "\0").concat(state.typeChecker.typeToString(type), "\0").concat(getTypeKey(type));
|
|
145
|
+
// Results are cached per file. Re-emitting a whole object literal at every call site is the
|
|
146
|
+
// main cost of a macro type, so the second use in a file hoists it into a shared constant.
|
|
147
|
+
var cached = cache.get(cacheKey);
|
|
148
|
+
if (cached && cached.fileName === file.fileName) {
|
|
149
|
+
return cached.expression;
|
|
150
|
+
}
|
|
151
|
+
var _a = createMacroContext(file, node), context = _a.context, hoistRaw = _a.hoistRaw;
|
|
152
|
+
var result = (0, nodeFactory_1.unwrapNode)(registered.handler(types.wrap(type), context));
|
|
153
|
+
if (!typescript_1.default.isExpression(result)) {
|
|
154
|
+
diagnostics_1.Diagnostics.error(node, "Flamework plugin macro type '".concat(name, "' returned a non-expression."));
|
|
155
|
+
}
|
|
156
|
+
var expression = isTriviallyDuplicable(result) ? result : hoistRaw(result, name);
|
|
157
|
+
cache.set(cacheKey, { fileName: file.fileName, expression: expression });
|
|
158
|
+
return expression;
|
|
159
|
+
}
|
|
160
|
+
function createMacroContext(file, node) {
|
|
161
|
+
function hoistRaw(expression, name) {
|
|
162
|
+
if (name === void 0) { name = "plugin"; }
|
|
163
|
+
var identifier = factory_1.f.identifier(name, true);
|
|
164
|
+
state.nextRootStatements.push(factory_1.f.variableStatement(identifier, expression));
|
|
165
|
+
return identifier;
|
|
166
|
+
}
|
|
167
|
+
var context = {
|
|
168
|
+
hoist: function (expression, name) {
|
|
169
|
+
var unwrapped = (0, nodeFactory_1.unwrapNode)(expression);
|
|
170
|
+
if (!typescript_1.default.isExpression(unwrapped)) {
|
|
171
|
+
diagnostics_1.Diagnostics.error(node, "hoist was called with a node that is not an expression.");
|
|
172
|
+
}
|
|
173
|
+
return (0, nodeFactory_1.createNodeHandle)(hoistRaw(unwrapped, name));
|
|
174
|
+
},
|
|
175
|
+
hoistStatement: function (statement) {
|
|
176
|
+
var unwrapped = (0, nodeFactory_1.unwrapNode)(statement);
|
|
177
|
+
if (!typescript_1.default.isStatement(unwrapped)) {
|
|
178
|
+
diagnostics_1.Diagnostics.error(node, "hoistStatement was called with a node that is not a statement.");
|
|
179
|
+
}
|
|
180
|
+
state.nextRootStatements.push(unwrapped);
|
|
181
|
+
},
|
|
182
|
+
error: function (message) {
|
|
183
|
+
return diagnostics_1.Diagnostics.error(node, message);
|
|
184
|
+
},
|
|
185
|
+
warning: function (message) {
|
|
186
|
+
diagnostics_1.Diagnostics.warning(node, message);
|
|
187
|
+
},
|
|
188
|
+
fileName: file.fileName,
|
|
189
|
+
};
|
|
190
|
+
return { context: context, hoistRaw: hoistRaw };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Literals and identifiers are cheap enough to duplicate at each call site, and duplicating them
|
|
195
|
+
* avoids emitting a constant for something like `"foo"`.
|
|
196
|
+
*/
|
|
197
|
+
function isTriviallyDuplicable(node) {
|
|
198
|
+
return (typescript_1.default.isStringLiteral(node) ||
|
|
199
|
+
typescript_1.default.isNumericLiteral(node) ||
|
|
200
|
+
typescript_1.default.isIdentifier(node) ||
|
|
201
|
+
node.kind === typescript_1.default.SyntaxKind.TrueKeyword ||
|
|
202
|
+
node.kind === typescript_1.default.SyntaxKind.FalseKeyword);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* `ts.Type` has a stable numeric id, but it is internal. Falling back to the printed type keeps the
|
|
206
|
+
* cache correct (never merging distinct types) if the id is unavailable.
|
|
207
|
+
*/
|
|
208
|
+
function getTypeKey(type) {
|
|
209
|
+
var _a;
|
|
210
|
+
return (_a = type.id) !== null && _a !== void 0 ? _a : -1;
|
|
211
|
+
}
|
|
212
|
+
function resolvePluginPath(state, pluginPath) {
|
|
213
|
+
if (pluginPath.startsWith(".")) {
|
|
214
|
+
return path_1.default.resolve(state.rootDirectory, pluginPath);
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
return require.resolve(pluginPath, { paths: [state.rootDirectory] });
|
|
218
|
+
}
|
|
219
|
+
catch (_a) {
|
|
220
|
+
throw new Error("Could not resolve Flamework plugin '".concat(pluginPath, "' from '").concat(state.rootDirectory, "'. ") +
|
|
221
|
+
"Use a relative path for local plugins, or install the plugin as a dependency.");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function requirePluginRegistry(state) {
|
|
225
|
+
var resolved;
|
|
226
|
+
try {
|
|
227
|
+
resolved = require.resolve(packages_1.PLUGIN_PACKAGE, { paths: [state.rootDirectory] });
|
|
228
|
+
}
|
|
229
|
+
catch (_a) {
|
|
230
|
+
throw new Error("Flamework plugins are configured, but '".concat(packages_1.PLUGIN_PACKAGE, "' is not installed. ") +
|
|
231
|
+
"Add it as a dev dependency of your project.");
|
|
232
|
+
}
|
|
233
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
234
|
+
return require(resolved);
|
|
235
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __values = (this && this.__values) || function(o) {
|
|
3
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
4
|
+
if (m) return m.call(o);
|
|
5
|
+
if (o && typeof o.length === "number") return {
|
|
6
|
+
next: function () {
|
|
7
|
+
if (o && i >= o.length) o = void 0;
|
|
8
|
+
return { value: o && o[i++], done: !o };
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
12
|
+
};
|
|
13
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
14
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
15
|
+
if (!m) return o;
|
|
16
|
+
var i = m.call(o), r, ar = [], e;
|
|
17
|
+
try {
|
|
18
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
19
|
+
}
|
|
20
|
+
catch (error) { e = { error: error }; }
|
|
21
|
+
finally {
|
|
22
|
+
try {
|
|
23
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
24
|
+
}
|
|
25
|
+
finally { if (e) throw e.error; }
|
|
26
|
+
}
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
30
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
31
|
+
if (ar || !(i in from)) {
|
|
32
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
33
|
+
ar[i] = from[i];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
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.createTypeFactory = createTypeFactory;
|
|
43
|
+
var typescript_1 = __importDefault(require("typescript"));
|
|
44
|
+
var isTupleType_1 = require("../../util/functions/isTupleType");
|
|
45
|
+
var tsInternals_1 = require("../../util/tsInternals");
|
|
46
|
+
/**
|
|
47
|
+
* Wraps a `ts.Type` in the stable surface plugins are allowed to see.
|
|
48
|
+
*
|
|
49
|
+
* Facades are cached per `ts.Type` so that plugins can use reference equality and so repeated
|
|
50
|
+
* traversals of the same type do not reallocate.
|
|
51
|
+
*/
|
|
52
|
+
function createTypeFactory(state) {
|
|
53
|
+
var checker = state.typeChecker;
|
|
54
|
+
var cache = new Map();
|
|
55
|
+
function wrap(type) {
|
|
56
|
+
var existing = cache.get(type);
|
|
57
|
+
if (existing) {
|
|
58
|
+
return existing;
|
|
59
|
+
}
|
|
60
|
+
var facade = new TypeFacade(type);
|
|
61
|
+
cache.set(type, facade);
|
|
62
|
+
return facade;
|
|
63
|
+
}
|
|
64
|
+
function unwrap(type) {
|
|
65
|
+
if (!(type instanceof TypeFacade)) {
|
|
66
|
+
throw new Error("received a Type that was not created by this transformer");
|
|
67
|
+
}
|
|
68
|
+
return type.type;
|
|
69
|
+
}
|
|
70
|
+
var TypeFacade = /** @class */ (function () {
|
|
71
|
+
function TypeFacade(type) {
|
|
72
|
+
this.type = type;
|
|
73
|
+
}
|
|
74
|
+
TypeFacade.prototype.isSubtypeOf = function (other) {
|
|
75
|
+
return checker.isTypeAssignableTo(this.type, unwrap(other));
|
|
76
|
+
};
|
|
77
|
+
TypeFacade.prototype.isSupertypeOf = function (other) {
|
|
78
|
+
return checker.isTypeAssignableTo(unwrap(other), this.type);
|
|
79
|
+
};
|
|
80
|
+
TypeFacade.prototype.isEquivalentTo = function (other) {
|
|
81
|
+
var otherType = unwrap(other);
|
|
82
|
+
return checker.isTypeAssignableTo(this.type, otherType) && checker.isTypeAssignableTo(otherType, this.type);
|
|
83
|
+
};
|
|
84
|
+
TypeFacade.prototype.isIntersection = function () {
|
|
85
|
+
return this.type.isIntersection();
|
|
86
|
+
};
|
|
87
|
+
TypeFacade.prototype.isUnion = function () {
|
|
88
|
+
return this.type.isUnion();
|
|
89
|
+
};
|
|
90
|
+
TypeFacade.prototype.isObjectLike = function () {
|
|
91
|
+
return (this.type.flags & typescript_1.default.TypeFlags.Object) !== 0;
|
|
92
|
+
};
|
|
93
|
+
TypeFacade.prototype.isArray = function () {
|
|
94
|
+
return (0, isTupleType_1.isArrayType)(state, this.type) || (0, isTupleType_1.isTupleType)(state, this.type);
|
|
95
|
+
};
|
|
96
|
+
TypeFacade.prototype.isTuple = function () {
|
|
97
|
+
return (0, isTupleType_1.isTupleType)(state, this.type);
|
|
98
|
+
};
|
|
99
|
+
TypeFacade.prototype.isLiteral = function (kind) {
|
|
100
|
+
if (kind === "string")
|
|
101
|
+
return this.type.isStringLiteral();
|
|
102
|
+
if (kind === "number")
|
|
103
|
+
return this.type.isNumberLiteral();
|
|
104
|
+
if (kind === "boolean")
|
|
105
|
+
return (this.type.flags & typescript_1.default.TypeFlags.BooleanLiteral) !== 0;
|
|
106
|
+
return this.type.isLiteral() || (this.type.flags & typescript_1.default.TypeFlags.BooleanLiteral) !== 0;
|
|
107
|
+
};
|
|
108
|
+
TypeFacade.prototype.isPrimitive = function (primitive) {
|
|
109
|
+
if ((this.type.flags & tsInternals_1.TYPE_FLAG_INTRINSIC) === 0) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return this.type.intrinsicName === primitive;
|
|
113
|
+
};
|
|
114
|
+
TypeFacade.prototype.getNonNullable = function () {
|
|
115
|
+
return wrap(this.type.getNonNullableType());
|
|
116
|
+
};
|
|
117
|
+
TypeFacade.prototype.isOptional = function () {
|
|
118
|
+
if (!this.type.isUnion()) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return this.type.types.some(function (v) { return (v.flags & (typescript_1.default.TypeFlags.Undefined | typescript_1.default.TypeFlags.Null)) !== 0; });
|
|
122
|
+
};
|
|
123
|
+
TypeFacade.prototype.getName = function () {
|
|
124
|
+
var _a, _b, _c;
|
|
125
|
+
return (_b = (_a = this.type.aliasSymbol) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : (_c = this.type.getSymbol()) === null || _c === void 0 ? void 0 : _c.name;
|
|
126
|
+
};
|
|
127
|
+
// UnionOrIntersectionType
|
|
128
|
+
TypeFacade.prototype.getConstituents = function () {
|
|
129
|
+
if (!this.type.isUnionOrIntersection()) {
|
|
130
|
+
throw new Error("getConstituents called on a type that is not a union or intersection");
|
|
131
|
+
}
|
|
132
|
+
return this.type.types.map(wrap);
|
|
133
|
+
};
|
|
134
|
+
// ObjectLikeType
|
|
135
|
+
TypeFacade.prototype.getFields = function () {
|
|
136
|
+
var e_1, _a;
|
|
137
|
+
var fields = new Array();
|
|
138
|
+
try {
|
|
139
|
+
for (var _b = __values(checker.getPropertiesOfType(this.type)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
140
|
+
var field = _c.value;
|
|
141
|
+
var fieldType = checker.getTypeOfPropertyOfType(this.type, field.name);
|
|
142
|
+
if (!fieldType) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
fields.push({
|
|
146
|
+
name: field.name,
|
|
147
|
+
readonly: isReadonlySymbol(field),
|
|
148
|
+
optional: (field.flags & typescript_1.default.SymbolFlags.Optional) !== 0,
|
|
149
|
+
type: wrap(fieldType),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
154
|
+
finally {
|
|
155
|
+
try {
|
|
156
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
157
|
+
}
|
|
158
|
+
finally { if (e_1) throw e_1.error; }
|
|
159
|
+
}
|
|
160
|
+
return fields;
|
|
161
|
+
};
|
|
162
|
+
TypeFacade.prototype.getIndexSignatures = function () {
|
|
163
|
+
return checker.getIndexInfosOfType(this.type).map(function (info) { return ({
|
|
164
|
+
key: wrap(info.keyType),
|
|
165
|
+
value: wrap(info.type),
|
|
166
|
+
readonly: info.isReadonly,
|
|
167
|
+
}); });
|
|
168
|
+
};
|
|
169
|
+
TypeFacade.prototype.getCallSignatures = function () {
|
|
170
|
+
return this.getSignatures(typescript_1.default.SignatureKind.Call);
|
|
171
|
+
};
|
|
172
|
+
TypeFacade.prototype.getConstructSignatures = function () {
|
|
173
|
+
return this.getSignatures(typescript_1.default.SignatureKind.Construct);
|
|
174
|
+
};
|
|
175
|
+
TypeFacade.prototype.getSignatures = function (kind) {
|
|
176
|
+
return checker.getSignaturesOfType(this.type, kind).map(function (signature) { return ({
|
|
177
|
+
inputs: signature.getParameters().map(function (v) { return wrap(checker.getTypeOfSymbol(v)); }),
|
|
178
|
+
output: wrap(signature.getReturnType()),
|
|
179
|
+
}); });
|
|
180
|
+
};
|
|
181
|
+
// TupleArrayType
|
|
182
|
+
TypeFacade.prototype.getElements = function () {
|
|
183
|
+
if (!(0, isTupleType_1.isTupleType)(state, this.type)) {
|
|
184
|
+
throw new Error("getElements called on a type that is not a tuple");
|
|
185
|
+
}
|
|
186
|
+
var target = this.type.target;
|
|
187
|
+
return checker.getTypeArguments(this.type).map(function (argument, index) {
|
|
188
|
+
var _a, _b;
|
|
189
|
+
var nameDeclaration = (_b = (_a = target.labeledElementDeclarations) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b.name;
|
|
190
|
+
var elementFlags = target.elementFlags[index];
|
|
191
|
+
return {
|
|
192
|
+
name: nameDeclaration && typescript_1.default.isIdentifier(nameDeclaration) ? nameDeclaration.text : undefined,
|
|
193
|
+
type: wrap(argument),
|
|
194
|
+
spread: (elementFlags & typescript_1.default.ElementFlags.Rest) !== 0,
|
|
195
|
+
optional: (elementFlags & typescript_1.default.ElementFlags.Optional) !== 0,
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
// ArrayType
|
|
200
|
+
TypeFacade.prototype.getElementType = function () {
|
|
201
|
+
var _a;
|
|
202
|
+
if ((0, isTupleType_1.isTupleType)(state, this.type)) {
|
|
203
|
+
var elements = checker.getTypeArguments(this.type);
|
|
204
|
+
return wrap(elements.length > 0 ? checker.getUnionType(__spreadArray([], __read(elements), false)) : checker.getNeverType());
|
|
205
|
+
}
|
|
206
|
+
if (!(0, isTupleType_1.isArrayType)(state, this.type)) {
|
|
207
|
+
throw new Error("getElementType called on a type that is not an array");
|
|
208
|
+
}
|
|
209
|
+
return wrap((_a = checker.getElementTypeOfArrayType(this.type)) !== null && _a !== void 0 ? _a : checker.getAnyType());
|
|
210
|
+
};
|
|
211
|
+
TypeFacade.prototype.isReadonly = function () {
|
|
212
|
+
var symbol = this.type.getSymbol();
|
|
213
|
+
if (!symbol) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
// `readonly T[]` and `ReadonlyArray<T>` both resolve to the global ReadonlyArray symbol.
|
|
217
|
+
var readonlyArray = checker.resolveName("ReadonlyArray", undefined, typescript_1.default.SymbolFlags.Type, false);
|
|
218
|
+
return (readonlyArray !== undefined &&
|
|
219
|
+
checker.getMergedSymbol(symbol) === checker.getMergedSymbol(readonlyArray));
|
|
220
|
+
};
|
|
221
|
+
// LiteralType
|
|
222
|
+
TypeFacade.prototype.getLiteralValue = function () {
|
|
223
|
+
if (this.type.isStringLiteral() || this.type.isNumberLiteral()) {
|
|
224
|
+
return this.type.value;
|
|
225
|
+
}
|
|
226
|
+
if (this.type === checker.getTrueType())
|
|
227
|
+
return true;
|
|
228
|
+
if (this.type === checker.getFalseType())
|
|
229
|
+
return false;
|
|
230
|
+
throw new Error("getLiteralValue called on a type that is not a literal");
|
|
231
|
+
};
|
|
232
|
+
TypeFacade.prototype.toString = function () {
|
|
233
|
+
return checker.typeToString(this.type);
|
|
234
|
+
};
|
|
235
|
+
return TypeFacade;
|
|
236
|
+
}());
|
|
237
|
+
function isReadonlySymbol(symbol) {
|
|
238
|
+
var _a, _b;
|
|
239
|
+
return (_b = (_a = symbol.declarations) === null || _a === void 0 ? void 0 : _a.some(function (v) { return typescript_1.default.isDeclarationReadonly(v); })) !== null && _b !== void 0 ? _b : false;
|
|
240
|
+
}
|
|
241
|
+
return { wrap: wrap, unwrap: unwrap };
|
|
242
|
+
}
|