@bikky/compiler 0.1.17 → 0.2.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/.idea/Compiler.iml +1 -0
- package/.idea/scopes/All_Typescript_Files.xml +3 -0
- package/Execution/generate.mjs +17 -1
- package/Execution/generate.mjs.map +1 -1
- package/Execution/generate.mts +33 -3
- package/Libraries/BiscuitLibraries.d.mts +2 -0
- package/Libraries/BiscuitLibraries.d.mts.map +1 -1
- package/Libraries/BiscuitLibraries.mjs +4 -0
- package/Libraries/BiscuitLibraries.mjs.map +1 -1
- package/Libraries/BiscuitLibraries.mts +5 -1
- package/Libraries/ClassMigration.d.mts +88 -0
- package/Libraries/ClassMigration.d.mts.map +1 -0
- package/Libraries/ClassMigration.mjs +368 -0
- package/Libraries/ClassMigration.mjs.map +1 -0
- package/Libraries/ClassMigration.mts +431 -0
- package/Libraries/RBF.d.mts +4 -0
- package/Libraries/RBF.d.mts.map +1 -0
- package/Libraries/RBF.mjs +36 -0
- package/Libraries/RBF.mjs.map +1 -0
- package/Libraries/RBF.mts +46 -0
- package/Libraries/RBFTypes.d.ts +43 -0
- package/Source/ASTInterface/Crawler.d.ts +2 -1
- package/Source/ASTInterface/Crawler.d.ts.map +1 -1
- package/Source/ASTInterface/Crawler.js +14 -2
- package/Transformers/Main.d.ts +1 -1
- package/Transformers/Main.d.ts.map +1 -1
- package/Transformers/Main.js +3 -2
- package/Transformers/RBFHelpers/Constants.d.ts +3 -0
- package/Transformers/RBFHelpers/Constants.d.ts.map +1 -0
- package/Transformers/RBFHelpers/Constants.js +7 -0
- package/Transformers/RBFHelpers/Imports.d.ts +12 -0
- package/Transformers/RBFHelpers/Imports.d.ts.map +1 -0
- package/Transformers/RBFHelpers/Imports.js +212 -0
- package/Transformers/RBFHelpers/Print.d.ts +1 -0
- package/Transformers/RBFHelpers/Print.d.ts.map +1 -0
- package/Transformers/RBFHelpers/Print.js +2 -0
- package/Transformers/RBFHelpers/PropertyConfig.d.ts +65 -0
- package/Transformers/RBFHelpers/PropertyConfig.d.ts.map +1 -0
- package/Transformers/RBFHelpers/PropertyConfig.js +420 -0
- package/Transformers/RBFTransformer.d.ts +2 -0
- package/Transformers/RBFTransformer.d.ts.map +1 -0
- package/Transformers/RBFTransformer.js +317 -0
- package/package.json +1 -1
- package/tsconfig.build.libs.tsbuildinfo +1 -1
- package/tsconfig.build.src.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/Transformers/ReplicableTransformer.d.ts +0 -2
- package/Transformers/ReplicableTransformer.d.ts.map +0 -1
- package/Transformers/ReplicableTransformer.js +0 -786
|
@@ -1,786 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const Crawler_js_1 = require("../Source/ASTInterface/Crawler.js");
|
|
4
|
-
const ts = require("../Cache/typescript");
|
|
5
|
-
const typescript_1 = require("../Cache/typescript");
|
|
6
|
-
const ASTHelper_js_1 = require("../Source/ASTHelper.js");
|
|
7
|
-
const ts_clone_node_1 = require("ts-clone-node");
|
|
8
|
-
const MiscHelpers_js_1 = require("../Source/MiscHelpers.js");
|
|
9
|
-
var printNode = ASTHelper_js_1.Printer.printNode;
|
|
10
|
-
//TODO:
|
|
11
|
-
// CustomLoad should change DataName.?
|
|
12
|
-
// Support for object types?
|
|
13
|
-
/**
|
|
14
|
-
* This transformer takes the @InlineClass, @AddressableClass and @Property decorators and constructs two files
|
|
15
|
-
* from this information; the first file is a definition file that contains the valid initialisation, replication
|
|
16
|
-
* and constructor data types for the class. The second file contains data that will be ingested by the
|
|
17
|
-
* replication library to do the necessary data transformations during load, serialisation and construction.
|
|
18
|
-
*
|
|
19
|
-
* Benefits of doing this during compile are both that some calculations can be cached (see below) and also that
|
|
20
|
-
* you can visually inspect the generated file for correctness.
|
|
21
|
-
* Ideally we can additionally check at compile time that types are correct, e.g. that types referenced within a
|
|
22
|
-
* @Property are actually classes that have been declared with @InlineClass or @AddressableClass, and that all
|
|
23
|
-
* @AddressableClasses are referenced using Pointers.
|
|
24
|
-
*
|
|
25
|
-
* We can cheat a bit here and apply the correct loading functions for child data if we already know exactly what
|
|
26
|
-
* types it can possibly be. Meaning that we can avoid the runtime having to both check what types are valid and
|
|
27
|
-
* then checking if the data matches those types. Finally, when the serialisation and deserialisation code changes
|
|
28
|
-
* to use binary instead of JSON, the functions can be easily used to directly read and write binary data.
|
|
29
|
-
*
|
|
30
|
-
* Type checking functions should be chainable so we can have:
|
|
31
|
-
* [Array, Array, InlineClass] be checked as "is this an array?" -> "is each entry an array?"
|
|
32
|
-
* -> "is each entry of the second array an InlineClass?".
|
|
33
|
-
* We also need to support arbitrarily composable unions of types, so we can have something like
|
|
34
|
-
* (InlineClassA | InlineClassB)[] or InlineClassA | (InlineClassB[]).
|
|
35
|
-
*
|
|
36
|
-
* @Properties that reference @InlineClasses will make the containing class dependant on the inline class,
|
|
37
|
-
* meaning if the inline class is hot reloaded the containing class will also be reloaded.
|
|
38
|
-
*/
|
|
39
|
-
//RBF = Replication Breakdown File.
|
|
40
|
-
const rbfExt = ".rbf.js";
|
|
41
|
-
const defExt = ".data.d.ts";
|
|
42
|
-
const Klasses = new Map;
|
|
43
|
-
let currentFile = null;
|
|
44
|
-
let allFileImports = new Map();
|
|
45
|
-
let currentFileAliases = new Map();
|
|
46
|
-
let rbfImports = new Map();
|
|
47
|
-
let defImports = new Map();
|
|
48
|
-
let rbfContents = [];
|
|
49
|
-
let defContents = new Map;
|
|
50
|
-
function resolveAliases(name) {
|
|
51
|
-
while (currentFileAliases.has(name)) {
|
|
52
|
-
name = currentFileAliases.get(name);
|
|
53
|
-
}
|
|
54
|
-
return name;
|
|
55
|
-
}
|
|
56
|
-
function makeDataName(name) {
|
|
57
|
-
return name[0].toUpperCase() + name.slice(1);
|
|
58
|
-
}
|
|
59
|
-
function printRBFClass(klass) {
|
|
60
|
-
return (`
|
|
61
|
-
Name: "${klass.Name}",
|
|
62
|
-
DataName: "${klass.DataName}",
|
|
63
|
-
Referenced: ${klass.Referenced},
|
|
64
|
-
Parents: [${klass.Parents.map(p => `${resolveAliases(p) + "RBF"}`).join(", ")}],
|
|
65
|
-
AllPropertyNames: [],
|
|
66
|
-
OwnPropertyNames: [${klass.OwnPropertyNames.sort().map((e) => `"${e}"`).join(", ")}],
|
|
67
|
-
Properties: {` +
|
|
68
|
-
Object.getOwnPropertyNames(klass.Properties).map((e) => {
|
|
69
|
-
let propNames = Object.getOwnPropertyNames(klass.Properties[e]);
|
|
70
|
-
let output = [];
|
|
71
|
-
for (let propName of propNames) {
|
|
72
|
-
let propData = klass.Properties[e][propName];
|
|
73
|
-
output.push(`\n\t\t\t["${propName}"]: {`
|
|
74
|
-
+ `\n\t\t\t\tDataName: "` + propData.DataName + `",`
|
|
75
|
-
+ `\n\t\t\t\tConfig: ` +
|
|
76
|
-
JSON.stringify(propData.Config, null, 4)
|
|
77
|
-
.replace(/\n/g, "\n\t\t\t\t")
|
|
78
|
-
.replace(/ {4}/g, "\t") + ","
|
|
79
|
-
+ `\n\t\t\t\tTypescript: ` + JSON.stringify(propData.Typescript) + ","
|
|
80
|
-
+ `\n\t\t\t\tSerialised: ` + JSON.stringify(propData.Serialised) + ","
|
|
81
|
-
+ `\n\t\t\t\tData: ` + JSON.stringify(propData.Data)
|
|
82
|
-
+ `\n\t\t\t}`);
|
|
83
|
-
}
|
|
84
|
-
return `\n\t\t[${e}]: {` + output.join(",") + `\n\t\t}`;
|
|
85
|
-
}).join(",\n")
|
|
86
|
-
+ `\n\t}`).trim() + "\n";
|
|
87
|
-
}
|
|
88
|
-
const warning = `
|
|
89
|
-
// This file is automatically generated by the bikky compiler.
|
|
90
|
-
`.trim();
|
|
91
|
-
Crawler_js_1.Crawler.OnFile((node) => {
|
|
92
|
-
allFileImports.clear();
|
|
93
|
-
currentFileAliases.clear();
|
|
94
|
-
rbfImports.clear();
|
|
95
|
-
rbfContents = [];
|
|
96
|
-
currentFile = node.ts;
|
|
97
|
-
defContents.clear();
|
|
98
|
-
});
|
|
99
|
-
Crawler_js_1.Crawler.OnFileCompleted((node => {
|
|
100
|
-
//Only emit if we have something TO emit.
|
|
101
|
-
if (currentFile && rbfContents.length > 0) {
|
|
102
|
-
let imports = Array.from(rbfImports.entries()).map(([key, value]) => {
|
|
103
|
-
value = Array.from(new Set(value));
|
|
104
|
-
return `import { ${value.join(", ")} } from "${key}";`;
|
|
105
|
-
});
|
|
106
|
-
imports.push(`import { Replicable } from "@bikky/replication";`);
|
|
107
|
-
Crawler_js_1.Crawler.writeSupplementaryFile(currentFile.fileName.slice(0, -3) + rbfExt, imports.join("\n") + "\n\n" + warning + "\n\n" +
|
|
108
|
-
rbfContents.map((e, i) => `export const ${e.Name}RBF = {\n\t${printRBFClass(e)}};\n`
|
|
109
|
-
+ (e.Parents.length > 0 ? `${e.Name}RBF.AllPropertyNames = ${e.Name}RBF.OwnPropertyNames.concat(${e.Parents.map((e) => `${e}RBF.AllPropertyNames`).join(", ")});\n` : "")
|
|
110
|
-
+ `${e.Name}RBF.AllPropertyNames = Array.from(new Set(${e.Name}RBF.AllPropertyNames)).sort();\n`
|
|
111
|
-
+ `Replicable.registerClass(${e.Name}RBF);`).join("\n\n\n"));
|
|
112
|
-
imports = Array.from(defImports.entries()).map(([key, value]) => {
|
|
113
|
-
value = Array.from(new Set(value));
|
|
114
|
-
return `import { ${value.join(", ")} } from "${key}";`;
|
|
115
|
-
});
|
|
116
|
-
Crawler_js_1.Crawler.writeSupplementaryFile(currentFile.fileName.slice(0, -3) + defExt, imports.join("\n") + "\n\n" + warning + "\n\n" +
|
|
117
|
-
rbfContents.map((e) => {
|
|
118
|
-
var _a, _b, _c, _d, _e, _f;
|
|
119
|
-
let propInfos = defContents.get(e.Name);
|
|
120
|
-
if (e.Parents.length > 0) {
|
|
121
|
-
return `export interface ${e.Name}Data extends ${e.Parents.map((e) => `Omit<${e + "Data"}, "Class">`).join(", ")} {\n` +
|
|
122
|
-
`\tClass: "${e.Name}";\n` +
|
|
123
|
-
((_a = propInfos === null || propInfos === void 0 ? void 0 : propInfos.map((p) => `\t"${p.dataName}": ${p.data};`).join("\n")) !== null && _a !== void 0 ? _a : "") +
|
|
124
|
-
`\n}\n\n` +
|
|
125
|
-
`export interface ${e.Name}Serialised extends ${e.Parents.map((e) => e + "Serialised").join(", ")} {\n` +
|
|
126
|
-
`\tversion: string;\n` +
|
|
127
|
-
((_b = propInfos === null || propInfos === void 0 ? void 0 : propInfos.map((p) => `\t"${p.propName}": ${p.serialised};`).join("\n")) !== null && _b !== void 0 ? _b : "") +
|
|
128
|
-
`\n}\n\n` +
|
|
129
|
-
`export interface ${e.Name}Construct extends ${e.Parents.map((e) => `Omit<${e + "Construct"}, "Class">`).join(", ")} {\n` +
|
|
130
|
-
`\tClass: "${e.Name}";\n` +
|
|
131
|
-
((_c = propInfos === null || propInfos === void 0 ? void 0 : propInfos.map((p) => `\t"${p.dataName}"?: ${p.construct};`).join("\n")) !== null && _c !== void 0 ? _c : "") +
|
|
132
|
-
`\n}\n\n` +
|
|
133
|
-
`export type ${e.Name}SerialisedReference = [ string, ${e.Name}Serialised ];\n\n`;
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
return `export interface ${e.Name}Data {\n` +
|
|
137
|
-
`\tClass: "${e.Name}";\n` +
|
|
138
|
-
((_d = propInfos === null || propInfos === void 0 ? void 0 : propInfos.map((p) => `\t"${p.dataName}": ${p.data};`).join("\n")) !== null && _d !== void 0 ? _d : "") +
|
|
139
|
-
`\n}\n\n` +
|
|
140
|
-
`export interface ${e.Name}Serialised {\n` +
|
|
141
|
-
`\tversion: string;\n` +
|
|
142
|
-
((_e = propInfos === null || propInfos === void 0 ? void 0 : propInfos.map((p) => `\t"${p.propName}": ${p.serialised};`).join("\n")) !== null && _e !== void 0 ? _e : "") +
|
|
143
|
-
`\n}\n\n` +
|
|
144
|
-
`export interface ${e.Name}Construct {\n` +
|
|
145
|
-
`\tClass: "${e.Name}";\n` +
|
|
146
|
-
((_f = propInfos === null || propInfos === void 0 ? void 0 : propInfos.map((p) => `\t"${p.dataName}"?: ${p.construct};`).join("\n")) !== null && _f !== void 0 ? _f : "") +
|
|
147
|
-
`\n}\n\n` +
|
|
148
|
-
`export type ${e.Name}SerialisedReference = [ string, ${e.Name}Serialised ];\n\n`;
|
|
149
|
-
}
|
|
150
|
-
}).join("\n"));
|
|
151
|
-
}
|
|
152
|
-
return node.ts;
|
|
153
|
-
}));
|
|
154
|
-
Crawler_js_1.Crawler.Register((node) => {
|
|
155
|
-
if (ts.isImportDeclaration(node) && node.importClause) {
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
return false;
|
|
159
|
-
}, (node) => {
|
|
160
|
-
let declaration = node;
|
|
161
|
-
let localPath = declaration.moduleSpecifier.getText().slice(1, -1);
|
|
162
|
-
// let rbfpath = joinPaths(getPathDir(node.getSourceFile().fileName), localPath)
|
|
163
|
-
// .replace(/\.ts$/, rbfExt);
|
|
164
|
-
let rbfpath = localPath.replace(/\.js$/, rbfExt);
|
|
165
|
-
// let defpath = localPath.replace(/\.js$/, defExt);
|
|
166
|
-
let clause = declaration.importClause;
|
|
167
|
-
if (clause.name) {
|
|
168
|
-
// import name from "module"
|
|
169
|
-
allFileImports.set(clause.name.getText() + "RBF", rbfpath);
|
|
170
|
-
allFileImports.set(clause.name.getText(), localPath);
|
|
171
|
-
}
|
|
172
|
-
else if (clause.namedBindings) {
|
|
173
|
-
if ("elements" in clause.namedBindings) {
|
|
174
|
-
for (let binding of clause.namedBindings.elements) {
|
|
175
|
-
// import { name as alias } from "module"
|
|
176
|
-
// import { name } from "module"
|
|
177
|
-
if (ts.isImportSpecifier(binding)) {
|
|
178
|
-
if (binding.propertyName) {
|
|
179
|
-
currentFileAliases.set(binding.propertyName.getText(), binding.name.getText());
|
|
180
|
-
}
|
|
181
|
-
allFileImports.set(binding.name.getText() + "RBF", rbfpath);
|
|
182
|
-
allFileImports.set(binding.name.getText(), localPath);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
// import * as name from "module"
|
|
188
|
-
allFileImports.set(clause.namedBindings.name.getText() + "RBF", rbfpath);
|
|
189
|
-
allFileImports.set(clause.namedBindings.name.getText(), localPath);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return node;
|
|
193
|
-
});
|
|
194
|
-
//Remember all classes that are marked as InlineClass or AddressableClass.
|
|
195
|
-
Crawler_js_1.Crawler.Register((node) => {
|
|
196
|
-
if (ts.isDecorator(node) && (ts.isClassDeclaration(node.parent) || ts.isClassExpression(node.parent))) {
|
|
197
|
-
let decorator = node;
|
|
198
|
-
let decoratorName = ts.isCallExpression(decorator.expression) ? decorator.expression.expression.getText() : decorator.expression.getText();
|
|
199
|
-
if (decoratorName === "InlineClass" || decoratorName === "AddressableClass") {
|
|
200
|
-
if (ts.isClassDeclaration(node.parent)) {
|
|
201
|
-
return true;
|
|
202
|
-
}
|
|
203
|
-
else if (ts.isClassExpression(node.parent) && "name" in node.parent && node.parent.name) {
|
|
204
|
-
return true;
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
(0, ASTHelper_js_1.logError)(node, `Decorator @${decoratorName} can only be applied to named classes.`);
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
213
|
-
return false;
|
|
214
|
-
}, (node) => {
|
|
215
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
216
|
-
let decorator = node;
|
|
217
|
-
let decoratorName = ts.isCallExpression(decorator.expression) ? decorator.expression.expression.getText() : decorator.expression.getText();
|
|
218
|
-
let klassNode = node.parent;
|
|
219
|
-
if (decoratorName === "InlineClass" || decoratorName === "AddressableClass") {
|
|
220
|
-
let klassName = klassNode.name.text;
|
|
221
|
-
let klassExtends = (_b = (_a = klassNode.heritageClauses) === null || _a === void 0 ? void 0 : _a.find(hc => hc.token === ts.SyntaxKind.ExtendsKeyword)) !== null && _b !== void 0 ? _b : null;
|
|
222
|
-
let klassParents = [];
|
|
223
|
-
if (klassExtends) {
|
|
224
|
-
try {
|
|
225
|
-
klassParents = (0, MiscHelpers_js_1.getAllInheritedMixinClassNames)(klassExtends);
|
|
226
|
-
//Import the RBF file for each parent - if we can find an import statement for that parent - otherwise
|
|
227
|
-
// we assume the class is declared in the same file that it's extended from.
|
|
228
|
-
for (let parent of klassParents) {
|
|
229
|
-
if (allFileImports.has(parent)) {
|
|
230
|
-
let rbfPath = allFileImports.get(parent).slice(0, -3) + rbfExt;
|
|
231
|
-
let rbfImporter = (_c = rbfImports.get(rbfPath)) !== null && _c !== void 0 ? _c : [];
|
|
232
|
-
rbfImports.set(rbfPath, rbfImporter);
|
|
233
|
-
rbfImporter.push(parent + "RBF");
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
catch (e) {
|
|
238
|
-
console.error(e.message);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
for (let value of klassParents) {
|
|
242
|
-
let impo = allFileImports.get(resolveAliases(value));
|
|
243
|
-
if (impo) {
|
|
244
|
-
//Add parents to imports for rbf file.
|
|
245
|
-
let arr = (_d = rbfImports.get(impo.slice(0, -3) + rbfExt)) !== null && _d !== void 0 ? _d : [];
|
|
246
|
-
rbfImports.set(impo.slice(0, -3) + rbfExt, arr);
|
|
247
|
-
arr.push(resolveAliases(value) + "RBF");
|
|
248
|
-
//Add parents to imports for def file.
|
|
249
|
-
arr = (_e = defImports.get(impo.slice(0, -3) + defExt)) !== null && _e !== void 0 ? _e : [];
|
|
250
|
-
defImports.set(impo.slice(0, -3) + defExt, arr);
|
|
251
|
-
arr.push(resolveAliases(value) + "Data");
|
|
252
|
-
arr.push(resolveAliases(value) + "Serialised");
|
|
253
|
-
arr.push(resolveAliases(value) + "Construct");
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
let klassGenerics = (_g = (_f = klassNode.typeParameters) === null || _f === void 0 ? void 0 : _f.map(e => e.name.getText())) !== null && _g !== void 0 ? _g : [];
|
|
257
|
-
let klassInfo = {
|
|
258
|
-
Name: klassName,
|
|
259
|
-
DataName: klassName,
|
|
260
|
-
Referenced: decoratorName === "AddressableClass",
|
|
261
|
-
Parents: klassParents,
|
|
262
|
-
Generics: klassGenerics,
|
|
263
|
-
AllPropertyNames: [],
|
|
264
|
-
OwnPropertyNames: [],
|
|
265
|
-
Properties: {},
|
|
266
|
-
ExposedFunctions: []
|
|
267
|
-
};
|
|
268
|
-
Klasses.set(klassName, klassInfo);
|
|
269
|
-
rbfContents.push(klassInfo);
|
|
270
|
-
}
|
|
271
|
-
//Don't remove the node - Replicable can use it to determine if there's an RBF to be imported.
|
|
272
|
-
return node;
|
|
273
|
-
});
|
|
274
|
-
var MakeRBFTypes;
|
|
275
|
-
(function (MakeRBFTypes) {
|
|
276
|
-
MakeRBFTypes.primitiveReaders = {
|
|
277
|
-
Array: {
|
|
278
|
-
shouldGroup: false,
|
|
279
|
-
serialisedName: "Array",
|
|
280
|
-
isThisType: (node) => {
|
|
281
|
-
if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.text === "Array") {
|
|
282
|
-
return {
|
|
283
|
-
valid: true,
|
|
284
|
-
containsTypes: [...node.typeArguments]
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
if (!ts.isArrayTypeNode(node))
|
|
288
|
-
return false;
|
|
289
|
-
return {
|
|
290
|
-
valid: true,
|
|
291
|
-
containsTypes: [node.elementType],
|
|
292
|
-
};
|
|
293
|
-
},
|
|
294
|
-
},
|
|
295
|
-
Dict: {
|
|
296
|
-
shouldGroup: false,
|
|
297
|
-
serialisedName: "Dict",
|
|
298
|
-
//{[index: first]: second}
|
|
299
|
-
isThisType: (node) => {
|
|
300
|
-
if (ts.isTypeLiteralNode(node) && node.members.length === 1 && node.members[0].kind == ts.SyntaxKind.IndexSignature) {
|
|
301
|
-
let signature = node.members[0];
|
|
302
|
-
return {
|
|
303
|
-
valid: true,
|
|
304
|
-
containsTypes: [signature.parameters[0].type, signature.type]
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
Map: {
|
|
311
|
-
shouldGroup: false,
|
|
312
|
-
serialisedName: "Map",
|
|
313
|
-
isThisType: (node) => {
|
|
314
|
-
if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.text === "Map") {
|
|
315
|
-
return {
|
|
316
|
-
valid: true,
|
|
317
|
-
containsTypes: [...node.typeArguments]
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
return false;
|
|
321
|
-
}
|
|
322
|
-
},
|
|
323
|
-
String: {
|
|
324
|
-
shouldGroup: true,
|
|
325
|
-
serialisedName: "Primitive",
|
|
326
|
-
isThisType: (node) => {
|
|
327
|
-
if (node.kind === ts.SyntaxKind.StringKeyword) {
|
|
328
|
-
return true;
|
|
329
|
-
}
|
|
330
|
-
if (ts.isLiteralTypeNode(node) && node.literal.kind === ts.SyntaxKind.StringLiteral) {
|
|
331
|
-
return {
|
|
332
|
-
valid: true,
|
|
333
|
-
values: [node.literal.text]
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
return false;
|
|
337
|
-
},
|
|
338
|
-
tryReadLiteral: (node) => {
|
|
339
|
-
return ts.isStringLiteral(node) ? node.text : null;
|
|
340
|
-
}
|
|
341
|
-
},
|
|
342
|
-
Boolean: {
|
|
343
|
-
shouldGroup: true,
|
|
344
|
-
serialisedName: "Primitive",
|
|
345
|
-
isThisType: (node) => {
|
|
346
|
-
if (node.kind == ts.SyntaxKind.BooleanKeyword) {
|
|
347
|
-
return true;
|
|
348
|
-
}
|
|
349
|
-
else if (ts.isLiteralTypeNode(node)) {
|
|
350
|
-
if (node.literal.kind === ts.SyntaxKind.TrueKeyword) {
|
|
351
|
-
return {
|
|
352
|
-
valid: true,
|
|
353
|
-
values: [true]
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
else if (node.literal.kind === ts.SyntaxKind.FalseKeyword) {
|
|
357
|
-
return {
|
|
358
|
-
valid: true,
|
|
359
|
-
values: [false]
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
return false;
|
|
364
|
-
},
|
|
365
|
-
tryReadLiteral(node) {
|
|
366
|
-
return node.kind === ts.SyntaxKind.TrueKeyword ? true : node.kind === ts.SyntaxKind.FalseKeyword ? false : null;
|
|
367
|
-
}
|
|
368
|
-
},
|
|
369
|
-
Number: {
|
|
370
|
-
shouldGroup: true,
|
|
371
|
-
serialisedName: "Primitive",
|
|
372
|
-
isThisType: (node) => {
|
|
373
|
-
if (node.kind === ts.SyntaxKind.NumberKeyword) {
|
|
374
|
-
return true;
|
|
375
|
-
}
|
|
376
|
-
if (ts.isLiteralTypeNode(node) && node.literal.kind === ts.SyntaxKind.NumericLiteral) {
|
|
377
|
-
return {
|
|
378
|
-
valid: true,
|
|
379
|
-
values: [node.literal.text.includes(".") ?
|
|
380
|
-
parseInt(node.literal.text) : parseFloat(node.literal.text),]
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
return false;
|
|
384
|
-
},
|
|
385
|
-
tryReadLiteral(node) {
|
|
386
|
-
return ts.isNumericLiteral(node) ? (node.text.includes(".") ?
|
|
387
|
-
parseInt(node.text) : parseFloat(node.text)) : null;
|
|
388
|
-
}
|
|
389
|
-
},
|
|
390
|
-
Object: {
|
|
391
|
-
shouldGroup: false,
|
|
392
|
-
serialisedName: "Object",
|
|
393
|
-
isThisType: (node) => {
|
|
394
|
-
return ts.isTypeLiteralNode(node) || node.kind === ts.SyntaxKind.AnyKeyword;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
function recurseBasicType(child, childrenTypes) {
|
|
399
|
-
for (let readerName of Object.getOwnPropertyNames(MakeRBFTypes.primitiveReaders)) {
|
|
400
|
-
let reader = MakeRBFTypes.primitiveReaders[readerName];
|
|
401
|
-
let result = reader.isThisType(child);
|
|
402
|
-
if (result === false)
|
|
403
|
-
continue;
|
|
404
|
-
if (result === true) {
|
|
405
|
-
//Empty!
|
|
406
|
-
childrenTypes[readerName] = {};
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
if (!result.valid)
|
|
410
|
-
continue;
|
|
411
|
-
if (!childrenTypes[readerName]) {
|
|
412
|
-
childrenTypes[readerName] = {};
|
|
413
|
-
}
|
|
414
|
-
if (result.values) {
|
|
415
|
-
if (!childrenTypes[readerName].values) {
|
|
416
|
-
childrenTypes[readerName].values = [];
|
|
417
|
-
}
|
|
418
|
-
childrenTypes[readerName].values.push(...result.values);
|
|
419
|
-
}
|
|
420
|
-
if (result.containsTypes) {
|
|
421
|
-
if (!childrenTypes[readerName].subTypes) {
|
|
422
|
-
childrenTypes[readerName].subTypes = [];
|
|
423
|
-
}
|
|
424
|
-
childrenTypes[readerName].subTypes.push(...result.containsTypes.map((e) => recursivelyConvertType(e)));
|
|
425
|
-
}
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
if (ts.isTypeReferenceNode(child) && ts.isIdentifier(child.typeName)) {
|
|
429
|
-
childrenTypes[child.typeName.text] = {};
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
(0, ASTHelper_js_1.logError)(child, `Unsupported type value for @Property, @Get or @Function syntax :${ts.SyntaxKind[child.kind]}`);
|
|
433
|
-
childrenTypes["Unknown"] = {};
|
|
434
|
-
}
|
|
435
|
-
MakeRBFTypes.recurseBasicType = recurseBasicType;
|
|
436
|
-
function recursivelyConvertType(typeNode) {
|
|
437
|
-
if (ts.isUnionTypeNode(typeNode)) {
|
|
438
|
-
let childrenTypes = {};
|
|
439
|
-
loopUnionContents: for (let child of typeNode.types) {
|
|
440
|
-
recurseBasicType(child, childrenTypes);
|
|
441
|
-
}
|
|
442
|
-
let names = Object.getOwnPropertyNames(childrenTypes);
|
|
443
|
-
if (names.length === 1) {
|
|
444
|
-
let name = names[0];
|
|
445
|
-
let type = childrenTypes[name];
|
|
446
|
-
return {
|
|
447
|
-
Is: name,
|
|
448
|
-
RestrictedTo: type.values,
|
|
449
|
-
Containing: type.subTypes,
|
|
450
|
-
};
|
|
451
|
-
;
|
|
452
|
-
}
|
|
453
|
-
return {
|
|
454
|
-
OR: Object.getOwnPropertyNames(childrenTypes).map((name) => {
|
|
455
|
-
return {
|
|
456
|
-
Is: name,
|
|
457
|
-
RestrictedTo: childrenTypes[name].values,
|
|
458
|
-
Containing: childrenTypes[name].subTypes,
|
|
459
|
-
};
|
|
460
|
-
})
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
let childrenTypes = {};
|
|
464
|
-
recurseBasicType(typeNode, childrenTypes);
|
|
465
|
-
let name = Object.getOwnPropertyNames(childrenTypes)[0];
|
|
466
|
-
let type = childrenTypes[name];
|
|
467
|
-
return {
|
|
468
|
-
Is: name,
|
|
469
|
-
RestrictedTo: type.values,
|
|
470
|
-
Containing: type.subTypes,
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
MakeRBFTypes.recursivelyConvertType = recursivelyConvertType;
|
|
474
|
-
function extractConfigData(arg) {
|
|
475
|
-
let result = {};
|
|
476
|
-
//iterate each property.
|
|
477
|
-
for (let pa of arg.properties) {
|
|
478
|
-
if (!ts.isPropertyAssignment(pa)) {
|
|
479
|
-
(0, ASTHelper_js_1.logError)(pa, `@Property preprocessor command only accepts literal property assignments.`);
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
let name = pa.name.getText();
|
|
483
|
-
switch (name) {
|
|
484
|
-
case "computed": {
|
|
485
|
-
let value = MakeRBFTypes.primitiveReaders.Boolean.tryReadLiteral(pa.initializer);
|
|
486
|
-
if (value === null) {
|
|
487
|
-
value = MakeRBFTypes.primitiveReaders.String.tryReadLiteral(pa.initializer);
|
|
488
|
-
}
|
|
489
|
-
if (value === null || (typeof value === "string" && value !== "manualLoad")) {
|
|
490
|
-
(0, ASTHelper_js_1.logError)(pa, `@Property's ${name} value can only be "manualLoad" or boolean literal.`);
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
493
|
-
result[name] = value;
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
case "dataName": {
|
|
497
|
-
let value = MakeRBFTypes.primitiveReaders.String.tryReadLiteral(pa.initializer);
|
|
498
|
-
if (value === null) {
|
|
499
|
-
(0, ASTHelper_js_1.logError)(pa, `@Property's ${name} value must be a string.`);
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
result[name] = value;
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
case "customLoad":
|
|
506
|
-
case "readonly":
|
|
507
|
-
case "manualRestore":
|
|
508
|
-
case "expression":
|
|
509
|
-
case "setter":
|
|
510
|
-
case "inline":
|
|
511
|
-
case "optional":
|
|
512
|
-
case "id": {
|
|
513
|
-
let value = MakeRBFTypes.primitiveReaders.Boolean.tryReadLiteral(pa.initializer);
|
|
514
|
-
if (value === null) {
|
|
515
|
-
(0, ASTHelper_js_1.logError)(pa, `@Property's ${name} value must be a boolean.`);
|
|
516
|
-
continue;
|
|
517
|
-
}
|
|
518
|
-
result[name] = value;
|
|
519
|
-
continue;
|
|
520
|
-
}
|
|
521
|
-
case "default": {
|
|
522
|
-
result[name] = printNode(pa, Crawler_js_1.Crawler.GetFile().ts, typescript_1.EmitHint.Unspecified);
|
|
523
|
-
continue;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
(0, ASTHelper_js_1.logError)(pa, `Invalid value for @Property configuration, ${name}`);
|
|
527
|
-
}
|
|
528
|
-
return result;
|
|
529
|
-
}
|
|
530
|
-
MakeRBFTypes.extractConfigData = extractConfigData;
|
|
531
|
-
})(MakeRBFTypes || (MakeRBFTypes = {}));
|
|
532
|
-
const PlainTypes = [
|
|
533
|
-
ts.SyntaxKind.AnyKeyword,
|
|
534
|
-
ts.SyntaxKind.UnknownKeyword,
|
|
535
|
-
ts.SyntaxKind.StringKeyword,
|
|
536
|
-
ts.SyntaxKind.NumberKeyword,
|
|
537
|
-
ts.SyntaxKind.BigIntKeyword,
|
|
538
|
-
ts.SyntaxKind.BooleanKeyword,
|
|
539
|
-
ts.SyntaxKind.SymbolKeyword,
|
|
540
|
-
ts.SyntaxKind.VoidKeyword,
|
|
541
|
-
ts.SyntaxKind.UndefinedKeyword,
|
|
542
|
-
ts.SyntaxKind.NullKeyword,
|
|
543
|
-
ts.SyntaxKind.ThisKeyword,
|
|
544
|
-
ts.SyntaxKind.NeverKeyword,
|
|
545
|
-
];
|
|
546
|
-
function convertTypeToDeclarationFormats(postfixes, node) {
|
|
547
|
-
node = (0, ts_clone_node_1.cloneNode)(node, { factory: Crawler_js_1.Crawler.getContext().factory });
|
|
548
|
-
/**
|
|
549
|
-
* Update the provided type reference's identifiers to use the provided postfixes.
|
|
550
|
-
*/
|
|
551
|
-
function importAndConvertIdentifiers(typeNode, typeArgs) {
|
|
552
|
-
var _a, _b;
|
|
553
|
-
let className = ts.isQualifiedName(typeNode.typeName) ? typeNode.typeName.right.text : typeNode.typeName.text;
|
|
554
|
-
//Handle edge-cases for built-in types. We don't map them to serialised classes we treat them as primitives.
|
|
555
|
-
if (ts.isIdentifier(typeNode.typeName) && (className === "Array" || className === "Map" || className === "Set")) {
|
|
556
|
-
let results = [ts.factory.updateTypeReferenceNode(typeNode, typeNode.typeName, typeArgs)];
|
|
557
|
-
if (postfixes.includes("SerialisedReference")) {
|
|
558
|
-
let serialised = ts.factory.createTupleTypeNode([
|
|
559
|
-
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(className)),
|
|
560
|
-
ts.factory.updateTypeReferenceNode(typeNode, typeNode.typeName, typeArgs)
|
|
561
|
-
]);
|
|
562
|
-
if (postfixes.length > 1) {
|
|
563
|
-
results.push(serialised);
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
results[0] = serialised;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
if (results.length === 1)
|
|
570
|
-
return results[0];
|
|
571
|
-
return ts.factory.createUnionTypeNode(results);
|
|
572
|
-
}
|
|
573
|
-
let importedNode = typeNode.typeName;
|
|
574
|
-
while (ts.isQualifiedName(importedNode)) {
|
|
575
|
-
importedNode = importedNode.left;
|
|
576
|
-
}
|
|
577
|
-
if (!ts.isIdentifier(importedNode)) {
|
|
578
|
-
(0, ASTHelper_js_1.logError)(typeNode, `Left-most value in a reference type is not an identifier, abandoning attempt to import.`);
|
|
579
|
-
importedNode = null;
|
|
580
|
-
}
|
|
581
|
-
let results = [];
|
|
582
|
-
for (let postfix of postfixes) {
|
|
583
|
-
let renamedNode = (0, ts_clone_node_1.cloneNode)(typeNode.typeName);
|
|
584
|
-
//Update the name.
|
|
585
|
-
{
|
|
586
|
-
let newNameNode = ts.factory.createIdentifier(className + postfix);
|
|
587
|
-
if (ts.isQualifiedName(renamedNode)) {
|
|
588
|
-
ts.factory.updateQualifiedName(renamedNode, renamedNode.left, newNameNode);
|
|
589
|
-
}
|
|
590
|
-
else {
|
|
591
|
-
renamedNode = newNameNode;
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
let finalType = ts.factory.createTypeReferenceNode(renamedNode, typeArgs ? ts.factory.createNodeArray(typeArgs.map((e) => (0, ts_clone_node_1.cloneNode)(e))) : undefined);
|
|
595
|
-
//Add necessary imports to file.
|
|
596
|
-
if (importedNode) {
|
|
597
|
-
let impo = allFileImports.get(importedNode.text);
|
|
598
|
-
if (!impo && postfix === "") {
|
|
599
|
-
//create a local import.
|
|
600
|
-
impo = "./" + Crawler_js_1.Crawler.GetFile().ts.fileName.replace(/.*[\/\\]([^\/\\]*)$/, "$1");
|
|
601
|
-
}
|
|
602
|
-
if (impo) {
|
|
603
|
-
if (postfix === "") {
|
|
604
|
-
//If no modification to the type then we're importing the original file.
|
|
605
|
-
let arr = (_a = defImports.get(impo)) !== null && _a !== void 0 ? _a : [];
|
|
606
|
-
defImports.set(impo, arr);
|
|
607
|
-
arr.push(importedNode.text);
|
|
608
|
-
}
|
|
609
|
-
else {
|
|
610
|
-
let defImpo = impo.slice(0, -3) + defExt;
|
|
611
|
-
let arr = (_b = defImports.get(defImpo)) !== null && _b !== void 0 ? _b : [];
|
|
612
|
-
defImports.set(defImpo, arr);
|
|
613
|
-
arr.push(importedNode.text + postfix);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
results.push(finalType);
|
|
618
|
-
}
|
|
619
|
-
if (results.length === 1)
|
|
620
|
-
return results[0];
|
|
621
|
-
return ts.factory.createUnionTypeNode(results);
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* Recursively search through the typing nodes and convert any discovered identifiers to have
|
|
625
|
-
* the supplied postfixes.
|
|
626
|
-
*/
|
|
627
|
-
function findIdentifiers(typeNode) {
|
|
628
|
-
var _a;
|
|
629
|
-
//TODO: Throw a hissy fit if the `this` type keyword is used - or just replace it with whatever the current
|
|
630
|
-
// class is.
|
|
631
|
-
if (ts.isUnionTypeNode(typeNode)) {
|
|
632
|
-
return ts.visitEachChild(typeNode, findIdentifiers, Crawler_js_1.Crawler.getContext());
|
|
633
|
-
}
|
|
634
|
-
//Handle {[name: string]: MyThing}
|
|
635
|
-
else if (ts.isTypeLiteralNode(typeNode) && typeNode.members.length === 1 && ts.isIndexSignatureDeclaration(typeNode.members[0])) {
|
|
636
|
-
//Change MyThing to MyThingSerialisedReference or MyThingData or whatever's good.
|
|
637
|
-
typeNode = ts.factory.updateTypeLiteralNode(typeNode, ts.factory.createNodeArray(typeNode.members.map((e) => {
|
|
638
|
-
let decl = e;
|
|
639
|
-
return ts.factory.updateIndexSignature(decl, decl.modifiers, decl.parameters, ts.visitNode(decl.type, findIdentifiers));
|
|
640
|
-
})));
|
|
641
|
-
//If this is serialised we need to make it ["Dict", {[name: string]: MyThing}] (and union it if we're
|
|
642
|
-
// trying for more than one type.
|
|
643
|
-
if (postfixes.includes("SerialisedReference")) {
|
|
644
|
-
if (postfixes.length > 1) {
|
|
645
|
-
return ts.factory.createUnionTypeNode([ts.factory.createTupleTypeNode([ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("Dict")), typeNode]),
|
|
646
|
-
(0, ts_clone_node_1.cloneNode)(typeNode)]);
|
|
647
|
-
}
|
|
648
|
-
return ts.factory.createTupleTypeNode([ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("Dict")), typeNode]);
|
|
649
|
-
}
|
|
650
|
-
// return the result!
|
|
651
|
-
return typeNode;
|
|
652
|
-
}
|
|
653
|
-
else if (ts.isTypeReferenceNode(typeNode)) {
|
|
654
|
-
let typeArgs = (_a = typeNode.typeArguments) === null || _a === void 0 ? void 0 : _a.map((e) => {
|
|
655
|
-
return (PlainTypes.includes(e.kind) || ts.isTypeLiteralNode(e)) ? e : ts.visitNode(e, findIdentifiers);
|
|
656
|
-
});
|
|
657
|
-
let result = importAndConvertIdentifiers(typeNode, typeArgs ? ts.factory.createNodeArray(typeArgs) : undefined);
|
|
658
|
-
return result;
|
|
659
|
-
}
|
|
660
|
-
else {
|
|
661
|
-
if (postfixes.includes("SerialisedReference")) {
|
|
662
|
-
if (postfixes.length > 1) {
|
|
663
|
-
return ts.factory.createUnionTypeNode([ts.factory.createTupleTypeNode([ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("Primitive")), typeNode]),
|
|
664
|
-
(0, ts_clone_node_1.cloneNode)(typeNode)]);
|
|
665
|
-
}
|
|
666
|
-
return ts.factory.createTupleTypeNode([ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("Primitive")), typeNode]);
|
|
667
|
-
}
|
|
668
|
-
return typeNode;
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
let resultType = ts.visitNode(node, findIdentifiers);
|
|
672
|
-
let resultString = printNode(resultType, Crawler_js_1.Crawler.GetFile().ts, ts.EmitHint.Unspecified);
|
|
673
|
-
return resultString.replace(/(?:\n|\t| {4})/g, "");
|
|
674
|
-
}
|
|
675
|
-
// Handle @Property, @Setter and @Getter decorators.
|
|
676
|
-
Crawler_js_1.Crawler.Register((node) => {
|
|
677
|
-
if (ts.isDecorator(node) && ts.isPropertyDeclaration(node.parent) && ts.isCallExpression(node.expression) && node.expression.expression.getText() === "Property") {
|
|
678
|
-
return true;
|
|
679
|
-
}
|
|
680
|
-
return false;
|
|
681
|
-
}, (node) => {
|
|
682
|
-
let decorator = node;
|
|
683
|
-
if (!ts.isCallExpression(decorator.expression) || decorator.expression.arguments.length < 1) {
|
|
684
|
-
(0, ASTHelper_js_1.logError)(decorator.expression, `@Property requires a version as the first argument.`);
|
|
685
|
-
return [];
|
|
686
|
-
}
|
|
687
|
-
if (!ts.isCallExpression(decorator.expression) || decorator.expression.arguments.length > 2) {
|
|
688
|
-
(0, ASTHelper_js_1.logError)(decorator.expression, `@Property only takes two arguments.`);
|
|
689
|
-
return [];
|
|
690
|
-
}
|
|
691
|
-
//Setup version - add imports to RBF file.
|
|
692
|
-
let version = decorator.expression.arguments[0].getText();
|
|
693
|
-
{
|
|
694
|
-
let current = decorator.expression.arguments[0];
|
|
695
|
-
while (ts.isPropertyAccessExpression(current)) {
|
|
696
|
-
if (!ts.isIdentifier(current.name)) {
|
|
697
|
-
(0, ASTHelper_js_1.logError)(decorator.expression, `@Property's version must be a constant value, not an expression.`);
|
|
698
|
-
return [];
|
|
699
|
-
}
|
|
700
|
-
current = current.expression;
|
|
701
|
-
}
|
|
702
|
-
if (!ts.isIdentifier(current)) {
|
|
703
|
-
(0, ASTHelper_js_1.logError)(decorator.expression, `@Property's version must be a constant value, not an expression.`);
|
|
704
|
-
return [];
|
|
705
|
-
}
|
|
706
|
-
let versionImportName = current.getText();
|
|
707
|
-
let importLocation = allFileImports.get(versionImportName);
|
|
708
|
-
if (!importLocation) {
|
|
709
|
-
(0, ASTHelper_js_1.logError)(decorator.expression.arguments[0], `Values used for @Property's version must be imported from another file (as the RBF file needs to import it too).`);
|
|
710
|
-
return [];
|
|
711
|
-
}
|
|
712
|
-
if (decorator.expression.arguments.length > 1 && !ts.isObjectLiteralExpression(decorator.expression.arguments[1])) {
|
|
713
|
-
(0, ASTHelper_js_1.logError)(decorator.expression, `@Property must have a config object as the second argument.`);
|
|
714
|
-
return [];
|
|
715
|
-
}
|
|
716
|
-
let importArr = rbfImports.get(importLocation);
|
|
717
|
-
if (!importArr) {
|
|
718
|
-
rbfImports.set(importLocation, importArr = []);
|
|
719
|
-
}
|
|
720
|
-
importArr.push(versionImportName);
|
|
721
|
-
}
|
|
722
|
-
let propertyNode = node.parent;
|
|
723
|
-
let klassNode = propertyNode.parent;
|
|
724
|
-
let klassName = klassNode.name.text;
|
|
725
|
-
let klassInfo = Klasses.get(klassName);
|
|
726
|
-
if (!klassInfo) {
|
|
727
|
-
console.error((0, ASTHelper_js_1.logError)(klassNode, `Class ${klassName} is not marked as @InlineClass or @AddressableClass but has a @Property decorator.`));
|
|
728
|
-
return [];
|
|
729
|
-
}
|
|
730
|
-
let propertyName = propertyNode.name.getText();
|
|
731
|
-
let dataName = makeDataName(propertyName);
|
|
732
|
-
let typeChecker = Crawler_js_1.Crawler.GetProgram().ts.getTypeChecker();
|
|
733
|
-
//Use static type if provided, otherwise dynamic type if initialiser is provided, otherwise unknown.
|
|
734
|
-
let valueType;
|
|
735
|
-
if (propertyNode.type) {
|
|
736
|
-
valueType = propertyNode.type;
|
|
737
|
-
}
|
|
738
|
-
else if (propertyNode.initializer) {
|
|
739
|
-
let newType = typeChecker.typeToTypeNode(typeChecker.getTypeAtLocation(propertyNode.initializer), propertyNode, 0);
|
|
740
|
-
if (!newType) {
|
|
741
|
-
(0, ASTHelper_js_1.logError)(propertyNode, `Replicated properties must have a type specified or be initialised to a replicable type.`);
|
|
742
|
-
newType = ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
743
|
-
}
|
|
744
|
-
valueType = newType;
|
|
745
|
-
}
|
|
746
|
-
else {
|
|
747
|
-
(0, ASTHelper_js_1.logError)(propertyNode, `Replicated properties must have a type specified or be initialised to a replicable type.`);
|
|
748
|
-
valueType = ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
749
|
-
}
|
|
750
|
-
let dataType = valueType;
|
|
751
|
-
let configData;
|
|
752
|
-
if (decorator.expression.arguments.length > 1) {
|
|
753
|
-
configData = MakeRBFTypes.extractConfigData(decorator.expression.arguments[1]);
|
|
754
|
-
}
|
|
755
|
-
if (ts.isCallExpression(decorator.expression) && decorator.expression.typeArguments && decorator.expression.typeArguments.length === 1) {
|
|
756
|
-
dataType = decorator.expression.typeArguments[0];
|
|
757
|
-
}
|
|
758
|
-
klassInfo.OwnPropertyNames.push(propertyName);
|
|
759
|
-
klassInfo.OwnPropertyNames.sort();
|
|
760
|
-
let klassDef = defContents.get(klassInfo.Name);
|
|
761
|
-
if (!klassDef) {
|
|
762
|
-
defContents.set(klassInfo.Name, klassDef = []);
|
|
763
|
-
}
|
|
764
|
-
if (!klassInfo.Properties[version]) {
|
|
765
|
-
klassInfo.Properties[version] = {};
|
|
766
|
-
}
|
|
767
|
-
klassInfo.Properties[version][propertyName] = {
|
|
768
|
-
Config: configData !== null && configData !== void 0 ? configData : {},
|
|
769
|
-
DataName: dataName,
|
|
770
|
-
Typescript: MakeRBFTypes.recursivelyConvertType(valueType),
|
|
771
|
-
Serialised: MakeRBFTypes.recursivelyConvertType(valueType),
|
|
772
|
-
Data: MakeRBFTypes.recursivelyConvertType(dataType)
|
|
773
|
-
};
|
|
774
|
-
klassDef.push({
|
|
775
|
-
propName: propertyName,
|
|
776
|
-
dataName: dataName,
|
|
777
|
-
construct: convertTypeToDeclarationFormats(["", "Construct", "Data"], valueType),
|
|
778
|
-
serialised: convertTypeToDeclarationFormats(["SerialisedReference"], valueType),
|
|
779
|
-
data: convertTypeToDeclarationFormats(["Data"], dataType),
|
|
780
|
-
});
|
|
781
|
-
//Remove the decorator.
|
|
782
|
-
return [];
|
|
783
|
-
});
|
|
784
|
-
// Handle @Function decorators.
|
|
785
|
-
// Handle Migration function calls - which allow specifying custom migration logic for old properties/values.
|
|
786
|
-
//# sourceMappingURL=ReplicableTransformer.js.map
|