@needle-tools/needle-component-compiler 1.11.2 → 1.12.0-da2e0be
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/Changelog.md +101 -101
- package/Readme.md +17 -17
- package/package.json +46 -42
- package/src/component-compiler.js +788 -784
- package/src/types.js +58 -58
- package/tsconfig.json +7 -7
- package/workspace.code-workspace +14 -11
- package/src/component-compiler.ts +0 -822
|
@@ -1,784 +1,788 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
exports.__esModule = true;
|
|
3
|
-
exports.run = exports.compile = void 0;
|
|
4
|
-
var fs_1 = require("fs");
|
|
5
|
-
var ts = require("typescript");
|
|
6
|
-
var fs = require("fs");
|
|
7
|
-
var path = require("path");
|
|
8
|
-
var types = require("./types");
|
|
9
|
-
var dict = types.dict;
|
|
10
|
-
// add either of these two comments above a class to enforce code gen or disable it for the next class
|
|
11
|
-
var exportNextClassCommand = "@generate-component";
|
|
12
|
-
var dontExportNextClassCommand = "@dont-generate-component";
|
|
13
|
-
// add above field to add [SerializeField] attribute
|
|
14
|
-
var serializeCommand = "@serializeField";
|
|
15
|
-
var dontSerializeCommand = "@nonSerialized";
|
|
16
|
-
// https://regex101.com/r/ltpcKT/2
|
|
17
|
-
var typePattern = new RegExp("@type ?(?<type>.+)");
|
|
18
|
-
var ifdefPattern = new RegExp("@ifdef ?(?<ifdef>.+)");
|
|
19
|
-
var CODEGEN_MARKER_START = "// NEEDLE_CODEGEN_START";
|
|
20
|
-
var CODEGEN_MARKER_END = "// NEEDLE_CODEGEN_END";
|
|
21
|
-
var allowDebugLogs = true;
|
|
22
|
-
// will be set to true when e.g. a comment for export is found
|
|
23
|
-
var exportNextClass = false;
|
|
24
|
-
var dontExportNextClass = false;
|
|
25
|
-
var serializeField = false;
|
|
26
|
-
var dontSerialize = false;
|
|
27
|
-
var typesFileContent = undefined;
|
|
28
|
-
// const exportDir = "../dist";
|
|
29
|
-
var commentStarts = [];
|
|
30
|
-
var contexts = [];
|
|
31
|
-
var lastTypeFound = null;
|
|
32
|
-
var ifdefSections = [];
|
|
33
|
-
function resetAllState() {
|
|
34
|
-
exportNextClass = false;
|
|
35
|
-
dontExportNextClass = false;
|
|
36
|
-
serializeField = false;
|
|
37
|
-
dontSerialize = false;
|
|
38
|
-
typesFileContent = undefined;
|
|
39
|
-
commentStarts.length = 0;
|
|
40
|
-
contexts.length = 0;
|
|
41
|
-
lastTypeFound = null;
|
|
42
|
-
ifdefSections.length = 0;
|
|
43
|
-
}
|
|
44
|
-
function resetExportNextClass() {
|
|
45
|
-
dontExportNextClass = false;
|
|
46
|
-
exportNextClass = false;
|
|
47
|
-
}
|
|
48
|
-
function tryGetKnownType(str) {
|
|
49
|
-
if (typesFileContent === undefined) {
|
|
50
|
-
typesFileContent = null;
|
|
51
|
-
var filePath = path.dirname(__dirname) + "/src/types.json";
|
|
52
|
-
if (fs.existsSync(filePath)) {
|
|
53
|
-
if (allowDebugLogs)
|
|
54
|
-
console.log("Reading types file");
|
|
55
|
-
var content = fs.readFileSync(filePath, "utf8");
|
|
56
|
-
typesFileContent = JSON.parse(content);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (typesFileContent) {
|
|
60
|
-
var fullType = typesFileContent[str];
|
|
61
|
-
if (fullType && allowDebugLogs)
|
|
62
|
-
console.log(fullType);
|
|
63
|
-
return fullType;
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
// https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API
|
|
68
|
-
var ExportContext = /** @class */ (function () {
|
|
69
|
-
function ExportContext(outputDir, fileName) {
|
|
70
|
-
this.classEnd = -1;
|
|
71
|
-
this.indentLevel = 0;
|
|
72
|
-
this.emitMethodContextMenu = null;
|
|
73
|
-
this.emitTooltip = null;
|
|
74
|
-
this.outputDir = outputDir;
|
|
75
|
-
this.fileName = fileName;
|
|
76
|
-
this.reset();
|
|
77
|
-
}
|
|
78
|
-
ExportContext.prototype.onBeforeField = function (name) {
|
|
79
|
-
if (this.emitTooltip) {
|
|
80
|
-
this.appendLine("[UnityEngine.Tooltip(\"" + this.emitTooltip.trim().replace("\"", "'") + "\")]");
|
|
81
|
-
this.emitTooltip = undefined;
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
ExportContext.prototype.onBeforeMethod = function (name) {
|
|
85
|
-
if (this.emitMethodContextMenu !== undefined) {
|
|
86
|
-
var contextMenuText = this.emitMethodContextMenu === null ? name : this.emitMethodContextMenu;
|
|
87
|
-
this.appendLine("[UnityEngine.ContextMenu(\"" + contextMenuText + "\")]");
|
|
88
|
-
this.emitMethodContextMenu = undefined;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
ExportContext.prototype.append = function (text) {
|
|
92
|
-
for (var i = 0; i < this.indentLevel; i++)
|
|
93
|
-
text = "\t" + text;
|
|
94
|
-
this.textBuffer += text;
|
|
95
|
-
this.emitMethodContextMenu = undefined;
|
|
96
|
-
};
|
|
97
|
-
ExportContext.prototype.appendLine = function (text) {
|
|
98
|
-
this.append(text + "\n");
|
|
99
|
-
};
|
|
100
|
-
ExportContext.prototype.flush = function () {
|
|
101
|
-
if (this.textBuffer.length <= 0) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
this.textBuffer = CODEGEN_MARKER_START + "\n" + this.textBuffer + "\n" + CODEGEN_MARKER_END;
|
|
105
|
-
var code = this.textBuffer;
|
|
106
|
-
if (this.outputDir !== null) {
|
|
107
|
-
if (!fs.existsSync(this.outputDir))
|
|
108
|
-
fs.mkdirSync(this.outputDir);
|
|
109
|
-
var dir = this.outputDir + "/";
|
|
110
|
-
var path_1 = dir + this.fileName;
|
|
111
|
-
code = this.replaceGeneratedCodeSection(path_1, code);
|
|
112
|
-
if (allowDebugLogs)
|
|
113
|
-
console.log("Write to " + path_1);
|
|
114
|
-
fs.writeFileSync(path_1, code);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
console.log("No output dir specified");
|
|
118
|
-
}
|
|
119
|
-
this.reset();
|
|
120
|
-
return code;
|
|
121
|
-
};
|
|
122
|
-
ExportContext.prototype.reset = function () {
|
|
123
|
-
this.textBuffer = "";
|
|
124
|
-
this.classEnd = -1;
|
|
125
|
-
};
|
|
126
|
-
ExportContext.prototype.replaceGeneratedCodeSection = function (path, code) {
|
|
127
|
-
if (fs.existsSync(path)) {
|
|
128
|
-
var existing = fs.readFileSync(path, "utf8");
|
|
129
|
-
var regex = new RegExp("(?<before>.*?)\/\/ ?NEEDLE_CODEGEN_START.+\/\/ ?NEEDLE_CODEGEN_END(?<after>.*)", "s");
|
|
130
|
-
var matches = regex.exec(existing);
|
|
131
|
-
if (matches === null || matches === void 0 ? void 0 : matches.groups) {
|
|
132
|
-
if (allowDebugLogs)
|
|
133
|
-
console.log("Found codegen sections");
|
|
134
|
-
var before_1 = matches.groups.before;
|
|
135
|
-
var after_1 = matches.groups.after;
|
|
136
|
-
return before_1 + code + after_1;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return code;
|
|
140
|
-
};
|
|
141
|
-
return ExportContext;
|
|
142
|
-
}());
|
|
143
|
-
function compile(code, fileName, outputDir, debugLogs) {
|
|
144
|
-
if (debugLogs === void 0) { debugLogs = true; }
|
|
145
|
-
resetAllState();
|
|
146
|
-
allowDebugLogs = debugLogs;
|
|
147
|
-
// Parse a file
|
|
148
|
-
var sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.ES2015, true);
|
|
149
|
-
var prog = ts.createProgram([fileName], {});
|
|
150
|
-
// delint it
|
|
151
|
-
return run(prog, outputDir, sourceFile);
|
|
152
|
-
}
|
|
153
|
-
exports.compile = compile;
|
|
154
|
-
function run(program, outputDir, sourceFile) {
|
|
155
|
-
if (outputDir !== null && !fs.existsSync(outputDir)) {
|
|
156
|
-
console.error("Output directory does not exist: \"" + outputDir + "\"");
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
var results = [];
|
|
160
|
-
traverseFile(sourceFile);
|
|
161
|
-
function traverseFile(node) {
|
|
162
|
-
visit(node);
|
|
163
|
-
ts.forEachChild(node, traverseFile);
|
|
164
|
-
}
|
|
165
|
-
return results;
|
|
166
|
-
function visit(node) {
|
|
167
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
168
|
-
var context = contexts.length > 0 ? contexts[contexts.length - 1] : null;
|
|
169
|
-
if (context) {
|
|
170
|
-
if ((context === null || context === void 0 ? void 0 : context.classEnd) > 0 && node.pos >= (context === null || context === void 0 ? void 0 : context.classEnd)) {
|
|
171
|
-
while (context.indentLevel > 0) {
|
|
172
|
-
context.indentLevel -= 1;
|
|
173
|
-
context.append("}\n");
|
|
174
|
-
}
|
|
175
|
-
var code = context.flush();
|
|
176
|
-
results.push(code);
|
|
177
|
-
context = null;
|
|
178
|
-
contexts.pop();
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (allowDebugLogs)
|
|
182
|
-
console.log("\t", ts.SyntaxKind[node.kind]);
|
|
183
|
-
var commentRanges = ts.getLeadingCommentRanges(sourceFile.getFullText(), node.getFullStart());
|
|
184
|
-
if (commentRanges === null || commentRanges === void 0 ? void 0 : commentRanges.length) {
|
|
185
|
-
for (var _i = 0, commentRanges_1 = commentRanges; _i < commentRanges_1.length; _i++) {
|
|
186
|
-
var r = commentRanges_1[_i];
|
|
187
|
-
// avoid emitting comments multiple times
|
|
188
|
-
if (commentStarts.includes(r.pos))
|
|
189
|
-
continue;
|
|
190
|
-
commentStarts.push(r.pos);
|
|
191
|
-
var comment = node.getSourceFile().getFullText().slice(r.pos, r.end);
|
|
192
|
-
console.log(comment);
|
|
193
|
-
if (context) {
|
|
194
|
-
// https://regex101.com/r/ud4oev/1
|
|
195
|
-
var emitContextMenu = comment.match("(\/{2,}|\/\*) {0,}@contextmenu {1,}(?<text>[a-zA-Z 0-9]+)?");
|
|
196
|
-
if (emitContextMenu) {
|
|
197
|
-
context.emitMethodContextMenu = (_b = (_a = emitContextMenu.groups) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : null;
|
|
198
|
-
}
|
|
199
|
-
// https://regex101.com/r/Sa6Q8T/3
|
|
200
|
-
var emitTooltip = comment.match("\/{2,} {0,}(@tooltip) *?(?<text>.+)");
|
|
201
|
-
if (emitTooltip) {
|
|
202
|
-
console.log((_c = emitTooltip.groups) === null || _c === void 0 ? void 0 : _c.text);
|
|
203
|
-
context.emitTooltip = (_e = (_d = emitTooltip.groups) === null || _d === void 0 ? void 0 : _d.text) !== null && _e !== void 0 ? _e : null;
|
|
204
|
-
}
|
|
205
|
-
else if (comment.includes(serializeCommand))
|
|
206
|
-
serializeField = true;
|
|
207
|
-
else if (comment.includes(dontSerializeCommand))
|
|
208
|
-
dontSerialize = true;
|
|
209
|
-
}
|
|
210
|
-
if (comment.includes(exportNextClassCommand))
|
|
211
|
-
exportNextClass = true;
|
|
212
|
-
if (comment.includes(dontExportNextClassCommand))
|
|
213
|
-
dontExportNextClass = true;
|
|
214
|
-
var typeMatch = typePattern.exec(comment);
|
|
215
|
-
if (typeMatch && typeMatch.groups) {
|
|
216
|
-
// for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
|
|
217
|
-
// so we remove them
|
|
218
|
-
var type = typeMatch.groups["type"];
|
|
219
|
-
type = type.replace(/\(/, "").replace(/\)/, "");
|
|
220
|
-
if (allowDebugLogs)
|
|
221
|
-
console.log("Found type: ", type);
|
|
222
|
-
lastTypeFound = type;
|
|
223
|
-
}
|
|
224
|
-
var ifdefMatch = ifdefPattern.exec(comment);
|
|
225
|
-
if (ifdefMatch && ifdefMatch.groups) {
|
|
226
|
-
var ifdef = ifdefMatch.groups["ifdef"];
|
|
227
|
-
if (ifdef)
|
|
228
|
-
ifdefSections.push(ifdef);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
var skip = dontSerialize;
|
|
233
|
-
switch (node.kind) {
|
|
234
|
-
// Namespace
|
|
235
|
-
// case ts.SyntaxKind.ModuleDeclaration:
|
|
236
|
-
// const mod = node as ts.ModuleDeclaration;
|
|
237
|
-
// console.log(ts.SyntaxKind[mod.getChildAt(1).kind])
|
|
238
|
-
// const type = mod.getChildAt(1) as ts.Identifier;
|
|
239
|
-
// console.log("MODULE", type.text)
|
|
240
|
-
// break;
|
|
241
|
-
// case ts.SyntaxKind.Identifier:
|
|
242
|
-
// break;
|
|
243
|
-
// case ts.SyntaxKind.ClassDeclaration:
|
|
244
|
-
// case ts.SyntaxKind.SingleLineCommentTrivia:
|
|
245
|
-
// console.log("comment: " + node.getText())
|
|
246
|
-
// break;
|
|
247
|
-
case ts.SyntaxKind.Decorator:
|
|
248
|
-
break;
|
|
249
|
-
case ts.SyntaxKind.MethodDeclaration:
|
|
250
|
-
lastTypeFound = null;
|
|
251
|
-
serializeField = false;
|
|
252
|
-
dontSerialize = false;
|
|
253
|
-
resetExportNextClass();
|
|
254
|
-
if (!context)
|
|
255
|
-
break;
|
|
256
|
-
// TODO: always emit at least OnEnable method per class so generated components have toggle in editor
|
|
257
|
-
var meth = node;
|
|
258
|
-
// const isCoroutine = func.asteriskToken;
|
|
259
|
-
if (!skip && meth.name) {
|
|
260
|
-
var pub_1 = shouldEmitMethod(meth);
|
|
261
|
-
if (!pub_1)
|
|
262
|
-
return;
|
|
263
|
-
var paramsStr = "";
|
|
264
|
-
for (var _k = 0, _l = meth.parameters; _k < _l.length; _k++) {
|
|
265
|
-
var param = _l[_k];
|
|
266
|
-
if (!param || !param.name)
|
|
267
|
-
continue;
|
|
268
|
-
if (paramsStr.length > 0)
|
|
269
|
-
paramsStr += ", ";
|
|
270
|
-
var type = tryResolveTypeRecursive(param);
|
|
271
|
-
if (type === undefined)
|
|
272
|
-
type = "object";
|
|
273
|
-
var paramName = "";
|
|
274
|
-
var paramNameKind = param.name.kind;
|
|
275
|
-
switch (paramNameKind) {
|
|
276
|
-
case ts.SyntaxKind.ObjectBindingPattern:
|
|
277
|
-
paramName = "obj";
|
|
278
|
-
break;
|
|
279
|
-
default:
|
|
280
|
-
paramName = param.name.getText();
|
|
281
|
-
break;
|
|
282
|
-
}
|
|
283
|
-
paramsStr += type + " @" + paramName;
|
|
284
|
-
}
|
|
285
|
-
var methodName = meth.name.getText();
|
|
286
|
-
switch (methodName) {
|
|
287
|
-
case "onEnable":
|
|
288
|
-
methodName = "OnEnable";
|
|
289
|
-
break;
|
|
290
|
-
case "onDisable":
|
|
291
|
-
methodName = "OnDisable";
|
|
292
|
-
break;
|
|
293
|
-
}
|
|
294
|
-
context.onBeforeMethod(methodName);
|
|
295
|
-
// let visibility = pub ? "public" : "private";
|
|
296
|
-
context.append("public void " + methodName + "(" + paramsStr + "){}\n");
|
|
297
|
-
}
|
|
298
|
-
break;
|
|
299
|
-
case ts.SyntaxKind.SetAccessor:
|
|
300
|
-
case ts.SyntaxKind.PropertyDeclaration:
|
|
301
|
-
resetExportNextClass();
|
|
302
|
-
if (!context)
|
|
303
|
-
break;
|
|
304
|
-
if (allowDebugLogs)
|
|
305
|
-
console.log("Found variable", ts.SyntaxKind[node.kind], "\n", node.getText());
|
|
306
|
-
var vardec = node;
|
|
307
|
-
var varName = "@" + vardec.name.getText();
|
|
308
|
-
var pub = shouldEmitMethod(vardec);
|
|
309
|
-
var visibility = pub ? "public" : "private";
|
|
310
|
-
var isAccessible = pub;
|
|
311
|
-
dontSerialize = false;
|
|
312
|
-
if (serializeField) {
|
|
313
|
-
if (allowDebugLogs)
|
|
314
|
-
console.log("[SerializeField]");
|
|
315
|
-
context.appendLine("[UnityEngine.SerializeField]");
|
|
316
|
-
isAccessible = true;
|
|
317
|
-
}
|
|
318
|
-
else if (skip)
|
|
319
|
-
isAccessible = false;
|
|
320
|
-
if (!isAccessible) {
|
|
321
|
-
if (allowDebugLogs)
|
|
322
|
-
console.log("Skip because not public or serializeable");
|
|
323
|
-
break;
|
|
324
|
-
}
|
|
325
|
-
var name_1 = vardec.name.getText();
|
|
326
|
-
if (allowDebugLogs)
|
|
327
|
-
console.log("Variable:", name_1);
|
|
328
|
-
if (name_1.startsWith("\"@") || name_1.startsWith("\"$") || name_1.startsWith("$"))
|
|
329
|
-
break;
|
|
330
|
-
var typeString = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : tryResolveTypeRecursive(node);
|
|
331
|
-
var postFix = "";
|
|
332
|
-
var typeName = (_f = vardec.type) === null || _f === void 0 ? void 0 : _f.getText();
|
|
333
|
-
var shouldCommentTheLine = typeString === undefined;
|
|
334
|
-
if (typeString === undefined) {
|
|
335
|
-
postFix = " → Could not resolve C# type";
|
|
336
|
-
}
|
|
337
|
-
var assignment = "";
|
|
338
|
-
if (typeString !== undefined) {
|
|
339
|
-
for (var _m = 0, _o = node.getChildren(); _m < _o.length; _m++) {
|
|
340
|
-
var ch = _o[_m];
|
|
341
|
-
switch (ch.kind) {
|
|
342
|
-
default:
|
|
343
|
-
// console.log("Unknown assignment:", ts.SyntaxKind[ch.kind]);
|
|
344
|
-
break;
|
|
345
|
-
case ts.SyntaxKind.NewExpression:
|
|
346
|
-
assignment = " = " + getTypeForAssignment(ch, typeString);
|
|
347
|
-
break;
|
|
348
|
-
case ts.SyntaxKind.FalseKeyword:
|
|
349
|
-
case ts.SyntaxKind.TrueKeyword:
|
|
350
|
-
assignment = " = " + ch.getText();
|
|
351
|
-
break;
|
|
352
|
-
case ts.SyntaxKind.StringLiteral:
|
|
353
|
-
var str = ch;
|
|
354
|
-
assignment = " = \"" + str.text + "\"";
|
|
355
|
-
break;
|
|
356
|
-
case ts.SyntaxKind.FirstLiteralToken:
|
|
357
|
-
var lit = ch;
|
|
358
|
-
assignment = " = " + lit.text;
|
|
359
|
-
if (ts.isNumericLiteral(lit))
|
|
360
|
-
assignment += "f";
|
|
361
|
-
break;
|
|
362
|
-
case ts.SyntaxKind.ArrayLiteralExpression:
|
|
363
|
-
var arr = ch;
|
|
364
|
-
assignment = " = new " + typeString;
|
|
365
|
-
// if (arr.elements.length > 0) {
|
|
366
|
-
assignment += "{" + arr.elements.map(function (e) { return " " + getTypeForAssignment(e); }) + " }";
|
|
367
|
-
// }
|
|
368
|
-
break;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
var requireEndIf = false;
|
|
373
|
-
if (ifdefSections.length > 0) {
|
|
374
|
-
requireEndIf = true;
|
|
375
|
-
context.appendLine("#ifdef " + ifdefSections.pop());
|
|
376
|
-
}
|
|
377
|
-
if (typeString === undefined)
|
|
378
|
-
typeString = typeName;
|
|
379
|
-
if (typeString === "[]") {
|
|
380
|
-
if (allowDebugLogs)
|
|
381
|
-
console.log("Unknown array type for \"" + varName + " " + typeName + "\" - your type is probably not known (did you just create it this session?) and you might need to regenerate the Typemap in Unity. Go to \"Needle Engine/Internal/Generate Type Map for component compiler");
|
|
382
|
-
// typeString = "object[]";
|
|
383
|
-
// assignment = " = new object[0]";
|
|
384
|
-
shouldCommentTheLine = true;
|
|
385
|
-
}
|
|
386
|
-
context.onBeforeField(varName);
|
|
387
|
-
if (allowDebugLogs)
|
|
388
|
-
console.log("EMIT member: \"" + typeString + "\" " + varName, assignment, "Last type found:", lastTypeFound);
|
|
389
|
-
var prefix = shouldCommentTheLine ? "// " : "";
|
|
390
|
-
var isUnityEditorType = typeString === null || typeString === void 0 ? void 0 : typeString.includes("UnityEditor");
|
|
391
|
-
if (isUnityEditorType) {
|
|
392
|
-
context.appendLine("#if UNITY_EDITOR");
|
|
393
|
-
}
|
|
394
|
-
context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";" + postFix + "\n");
|
|
395
|
-
if (isUnityEditorType) {
|
|
396
|
-
context.appendLine("#endif");
|
|
397
|
-
}
|
|
398
|
-
lastTypeFound = null;
|
|
399
|
-
if (requireEndIf) {
|
|
400
|
-
context.appendLine("#endif");
|
|
401
|
-
}
|
|
402
|
-
break;
|
|
403
|
-
case ts.SyntaxKind.ClassDeclaration:
|
|
404
|
-
serializeField = false;
|
|
405
|
-
var dec = node;
|
|
406
|
-
// a class must inherit a component
|
|
407
|
-
var inheritsComponent = testInheritsComponent(node);
|
|
408
|
-
if (!dontExportNextClass && (lastTypeFound || exportNextClass || inheritsComponent)) {
|
|
409
|
-
resetExportNextClass();
|
|
410
|
-
var name_2 = (_g = dec.name) === null || _g === void 0 ? void 0 : _g.escapedText;
|
|
411
|
-
if (allowDebugLogs)
|
|
412
|
-
console.log("Found class: ", name_2);
|
|
413
|
-
var namespace = (_h = tryParseNamespace(node)) !== null && _h !== void 0 ? _h : "Needle.Typescript.GeneratedComponents";
|
|
414
|
-
if (allowDebugLogs)
|
|
415
|
-
console.log("NAMESPACE", namespace);
|
|
416
|
-
var newContext = new ExportContext(outputDir, name_2 + ".cs");
|
|
417
|
-
newContext.appendLine("// auto generated code - do not edit directly");
|
|
418
|
-
newContext.appendLine("");
|
|
419
|
-
newContext.appendLine("#pragma warning disable");
|
|
420
|
-
newContext.appendLine("");
|
|
421
|
-
newContext.appendLine("namespace " + namespace);
|
|
422
|
-
newContext.appendLine("{");
|
|
423
|
-
newContext.indentLevel += 1;
|
|
424
|
-
// newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
|
|
425
|
-
var typeName_1 = "UnityEngine.MonoBehaviour";
|
|
426
|
-
if (typeof inheritsComponent === "string")
|
|
427
|
-
typeName_1 = inheritsComponent;
|
|
428
|
-
if (lastTypeFound)
|
|
429
|
-
typeName_1 = lastTypeFound;
|
|
430
|
-
if (allowDebugLogs)
|
|
431
|
-
console.log(name_2 + " inherits " + typeName_1);
|
|
432
|
-
var modifiers = "";
|
|
433
|
-
if (dec.modifiers) {
|
|
434
|
-
for (var _p = 0, _q = dec.modifiers; _p < _q.length; _p++) {
|
|
435
|
-
var mod = _q[_p];
|
|
436
|
-
switch (mod.getText()) {
|
|
437
|
-
case "abstract":
|
|
438
|
-
modifiers += " abstract";
|
|
439
|
-
if (allowDebugLogs)
|
|
440
|
-
console.log(name_2 + " is abstract");
|
|
441
|
-
break;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
modifiers += " partial";
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
case ts.SyntaxKind.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
if (
|
|
512
|
-
args
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
else if (node.kind === ts.SyntaxKind.
|
|
549
|
-
return false;
|
|
550
|
-
}
|
|
551
|
-
// check if its
|
|
552
|
-
else if (node.kind === ts.SyntaxKind.
|
|
553
|
-
return false;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
break;
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
if (
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
var
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
//
|
|
652
|
-
//
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
break;
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
isInGenericDeclaration =
|
|
725
|
-
|
|
726
|
-
break;
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
//
|
|
740
|
-
|
|
741
|
-
res
|
|
742
|
-
}
|
|
743
|
-
//
|
|
744
|
-
else
|
|
745
|
-
res
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
//
|
|
753
|
-
//
|
|
754
|
-
//
|
|
755
|
-
//
|
|
756
|
-
//
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
exports.run = exports.compile = void 0;
|
|
4
|
+
var fs_1 = require("fs");
|
|
5
|
+
var ts = require("typescript");
|
|
6
|
+
var fs = require("fs");
|
|
7
|
+
var path = require("path");
|
|
8
|
+
var types = require("./types");
|
|
9
|
+
var dict = types.dict;
|
|
10
|
+
// add either of these two comments above a class to enforce code gen or disable it for the next class
|
|
11
|
+
var exportNextClassCommand = "@generate-component";
|
|
12
|
+
var dontExportNextClassCommand = "@dont-generate-component";
|
|
13
|
+
// add above field to add [SerializeField] attribute
|
|
14
|
+
var serializeCommand = "@serializeField";
|
|
15
|
+
var dontSerializeCommand = "@nonSerialized";
|
|
16
|
+
// https://regex101.com/r/ltpcKT/2
|
|
17
|
+
var typePattern = new RegExp("@type ?(?<type>.+)");
|
|
18
|
+
var ifdefPattern = new RegExp("@ifdef ?(?<ifdef>.+)");
|
|
19
|
+
var CODEGEN_MARKER_START = "// NEEDLE_CODEGEN_START";
|
|
20
|
+
var CODEGEN_MARKER_END = "// NEEDLE_CODEGEN_END";
|
|
21
|
+
var allowDebugLogs = true;
|
|
22
|
+
// will be set to true when e.g. a comment for export is found
|
|
23
|
+
var exportNextClass = false;
|
|
24
|
+
var dontExportNextClass = false;
|
|
25
|
+
var serializeField = false;
|
|
26
|
+
var dontSerialize = false;
|
|
27
|
+
var typesFileContent = undefined;
|
|
28
|
+
// const exportDir = "../dist";
|
|
29
|
+
var commentStarts = [];
|
|
30
|
+
var contexts = [];
|
|
31
|
+
var lastTypeFound = null;
|
|
32
|
+
var ifdefSections = [];
|
|
33
|
+
function resetAllState() {
|
|
34
|
+
exportNextClass = false;
|
|
35
|
+
dontExportNextClass = false;
|
|
36
|
+
serializeField = false;
|
|
37
|
+
dontSerialize = false;
|
|
38
|
+
typesFileContent = undefined;
|
|
39
|
+
commentStarts.length = 0;
|
|
40
|
+
contexts.length = 0;
|
|
41
|
+
lastTypeFound = null;
|
|
42
|
+
ifdefSections.length = 0;
|
|
43
|
+
}
|
|
44
|
+
function resetExportNextClass() {
|
|
45
|
+
dontExportNextClass = false;
|
|
46
|
+
exportNextClass = false;
|
|
47
|
+
}
|
|
48
|
+
function tryGetKnownType(str) {
|
|
49
|
+
if (typesFileContent === undefined) {
|
|
50
|
+
typesFileContent = null;
|
|
51
|
+
var filePath = path.dirname(__dirname) + "/src/types.json";
|
|
52
|
+
if (fs.existsSync(filePath)) {
|
|
53
|
+
if (allowDebugLogs)
|
|
54
|
+
console.log("Reading types file");
|
|
55
|
+
var content = fs.readFileSync(filePath, "utf8");
|
|
56
|
+
typesFileContent = JSON.parse(content);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (typesFileContent) {
|
|
60
|
+
var fullType = typesFileContent[str];
|
|
61
|
+
if (fullType && allowDebugLogs)
|
|
62
|
+
console.log(fullType);
|
|
63
|
+
return fullType;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
// https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API
|
|
68
|
+
var ExportContext = /** @class */ (function () {
|
|
69
|
+
function ExportContext(outputDir, fileName) {
|
|
70
|
+
this.classEnd = -1;
|
|
71
|
+
this.indentLevel = 0;
|
|
72
|
+
this.emitMethodContextMenu = null;
|
|
73
|
+
this.emitTooltip = null;
|
|
74
|
+
this.outputDir = outputDir;
|
|
75
|
+
this.fileName = fileName;
|
|
76
|
+
this.reset();
|
|
77
|
+
}
|
|
78
|
+
ExportContext.prototype.onBeforeField = function (name) {
|
|
79
|
+
if (this.emitTooltip) {
|
|
80
|
+
this.appendLine("[UnityEngine.Tooltip(\"" + this.emitTooltip.trim().replace("\"", "'") + "\")]");
|
|
81
|
+
this.emitTooltip = undefined;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
ExportContext.prototype.onBeforeMethod = function (name) {
|
|
85
|
+
if (this.emitMethodContextMenu !== undefined) {
|
|
86
|
+
var contextMenuText = this.emitMethodContextMenu === null ? name : this.emitMethodContextMenu;
|
|
87
|
+
this.appendLine("[UnityEngine.ContextMenu(\"" + contextMenuText + "\")]");
|
|
88
|
+
this.emitMethodContextMenu = undefined;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
ExportContext.prototype.append = function (text) {
|
|
92
|
+
for (var i = 0; i < this.indentLevel; i++)
|
|
93
|
+
text = "\t" + text;
|
|
94
|
+
this.textBuffer += text;
|
|
95
|
+
this.emitMethodContextMenu = undefined;
|
|
96
|
+
};
|
|
97
|
+
ExportContext.prototype.appendLine = function (text) {
|
|
98
|
+
this.append(text + "\n");
|
|
99
|
+
};
|
|
100
|
+
ExportContext.prototype.flush = function () {
|
|
101
|
+
if (this.textBuffer.length <= 0) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
this.textBuffer = CODEGEN_MARKER_START + "\n" + this.textBuffer + "\n" + CODEGEN_MARKER_END;
|
|
105
|
+
var code = this.textBuffer;
|
|
106
|
+
if (this.outputDir !== null) {
|
|
107
|
+
if (!fs.existsSync(this.outputDir))
|
|
108
|
+
fs.mkdirSync(this.outputDir);
|
|
109
|
+
var dir = this.outputDir + "/";
|
|
110
|
+
var path_1 = dir + this.fileName;
|
|
111
|
+
code = this.replaceGeneratedCodeSection(path_1, code);
|
|
112
|
+
if (allowDebugLogs)
|
|
113
|
+
console.log("Write to " + path_1);
|
|
114
|
+
fs.writeFileSync(path_1, code);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log("No output dir specified");
|
|
118
|
+
}
|
|
119
|
+
this.reset();
|
|
120
|
+
return code;
|
|
121
|
+
};
|
|
122
|
+
ExportContext.prototype.reset = function () {
|
|
123
|
+
this.textBuffer = "";
|
|
124
|
+
this.classEnd = -1;
|
|
125
|
+
};
|
|
126
|
+
ExportContext.prototype.replaceGeneratedCodeSection = function (path, code) {
|
|
127
|
+
if (fs.existsSync(path)) {
|
|
128
|
+
var existing = fs.readFileSync(path, "utf8");
|
|
129
|
+
var regex = new RegExp("(?<before>.*?)\/\/ ?NEEDLE_CODEGEN_START.+\/\/ ?NEEDLE_CODEGEN_END(?<after>.*)", "s");
|
|
130
|
+
var matches = regex.exec(existing);
|
|
131
|
+
if (matches === null || matches === void 0 ? void 0 : matches.groups) {
|
|
132
|
+
if (allowDebugLogs)
|
|
133
|
+
console.log("Found codegen sections");
|
|
134
|
+
var before_1 = matches.groups.before;
|
|
135
|
+
var after_1 = matches.groups.after;
|
|
136
|
+
return before_1 + code + after_1;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return code;
|
|
140
|
+
};
|
|
141
|
+
return ExportContext;
|
|
142
|
+
}());
|
|
143
|
+
function compile(code, fileName, outputDir, debugLogs) {
|
|
144
|
+
if (debugLogs === void 0) { debugLogs = true; }
|
|
145
|
+
resetAllState();
|
|
146
|
+
allowDebugLogs = debugLogs;
|
|
147
|
+
// Parse a file
|
|
148
|
+
var sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.ES2015, true);
|
|
149
|
+
var prog = ts.createProgram([fileName], {});
|
|
150
|
+
// delint it
|
|
151
|
+
return run(prog, outputDir, sourceFile);
|
|
152
|
+
}
|
|
153
|
+
exports.compile = compile;
|
|
154
|
+
function run(program, outputDir, sourceFile) {
|
|
155
|
+
if (outputDir !== null && !fs.existsSync(outputDir)) {
|
|
156
|
+
console.error("Output directory does not exist: \"" + outputDir + "\"");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
var results = [];
|
|
160
|
+
traverseFile(sourceFile);
|
|
161
|
+
function traverseFile(node) {
|
|
162
|
+
visit(node);
|
|
163
|
+
ts.forEachChild(node, traverseFile);
|
|
164
|
+
}
|
|
165
|
+
return results;
|
|
166
|
+
function visit(node) {
|
|
167
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
168
|
+
var context = contexts.length > 0 ? contexts[contexts.length - 1] : null;
|
|
169
|
+
if (context) {
|
|
170
|
+
if ((context === null || context === void 0 ? void 0 : context.classEnd) > 0 && node.pos >= (context === null || context === void 0 ? void 0 : context.classEnd)) {
|
|
171
|
+
while (context.indentLevel > 0) {
|
|
172
|
+
context.indentLevel -= 1;
|
|
173
|
+
context.append("}\n");
|
|
174
|
+
}
|
|
175
|
+
var code = context.flush();
|
|
176
|
+
results.push(code);
|
|
177
|
+
context = null;
|
|
178
|
+
contexts.pop();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (allowDebugLogs)
|
|
182
|
+
console.log("\t", ts.SyntaxKind[node.kind]);
|
|
183
|
+
var commentRanges = ts.getLeadingCommentRanges(sourceFile.getFullText(), node.getFullStart());
|
|
184
|
+
if (commentRanges === null || commentRanges === void 0 ? void 0 : commentRanges.length) {
|
|
185
|
+
for (var _i = 0, commentRanges_1 = commentRanges; _i < commentRanges_1.length; _i++) {
|
|
186
|
+
var r = commentRanges_1[_i];
|
|
187
|
+
// avoid emitting comments multiple times
|
|
188
|
+
if (commentStarts.includes(r.pos))
|
|
189
|
+
continue;
|
|
190
|
+
commentStarts.push(r.pos);
|
|
191
|
+
var comment = node.getSourceFile().getFullText().slice(r.pos, r.end);
|
|
192
|
+
console.log(comment);
|
|
193
|
+
if (context) {
|
|
194
|
+
// https://regex101.com/r/ud4oev/1
|
|
195
|
+
var emitContextMenu = comment.match("(\/{2,}|\/\*) {0,}@contextmenu {1,}(?<text>[a-zA-Z 0-9]+)?");
|
|
196
|
+
if (emitContextMenu) {
|
|
197
|
+
context.emitMethodContextMenu = (_b = (_a = emitContextMenu.groups) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : null;
|
|
198
|
+
}
|
|
199
|
+
// https://regex101.com/r/Sa6Q8T/3
|
|
200
|
+
var emitTooltip = comment.match("\/{2,} {0,}(@tooltip) *?(?<text>.+)");
|
|
201
|
+
if (emitTooltip) {
|
|
202
|
+
console.log((_c = emitTooltip.groups) === null || _c === void 0 ? void 0 : _c.text);
|
|
203
|
+
context.emitTooltip = (_e = (_d = emitTooltip.groups) === null || _d === void 0 ? void 0 : _d.text) !== null && _e !== void 0 ? _e : null;
|
|
204
|
+
}
|
|
205
|
+
else if (comment.includes(serializeCommand))
|
|
206
|
+
serializeField = true;
|
|
207
|
+
else if (comment.includes(dontSerializeCommand))
|
|
208
|
+
dontSerialize = true;
|
|
209
|
+
}
|
|
210
|
+
if (comment.includes(exportNextClassCommand))
|
|
211
|
+
exportNextClass = true;
|
|
212
|
+
if (comment.includes(dontExportNextClassCommand))
|
|
213
|
+
dontExportNextClass = true;
|
|
214
|
+
var typeMatch = typePattern.exec(comment);
|
|
215
|
+
if (typeMatch && typeMatch.groups) {
|
|
216
|
+
// for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
|
|
217
|
+
// so we remove them
|
|
218
|
+
var type = typeMatch.groups["type"];
|
|
219
|
+
type = type.replace(/\(/, "").replace(/\)/, "");
|
|
220
|
+
if (allowDebugLogs)
|
|
221
|
+
console.log("Found type: ", type);
|
|
222
|
+
lastTypeFound = type;
|
|
223
|
+
}
|
|
224
|
+
var ifdefMatch = ifdefPattern.exec(comment);
|
|
225
|
+
if (ifdefMatch && ifdefMatch.groups) {
|
|
226
|
+
var ifdef = ifdefMatch.groups["ifdef"];
|
|
227
|
+
if (ifdef)
|
|
228
|
+
ifdefSections.push(ifdef);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
var skip = dontSerialize;
|
|
233
|
+
switch (node.kind) {
|
|
234
|
+
// Namespace
|
|
235
|
+
// case ts.SyntaxKind.ModuleDeclaration:
|
|
236
|
+
// const mod = node as ts.ModuleDeclaration;
|
|
237
|
+
// console.log(ts.SyntaxKind[mod.getChildAt(1).kind])
|
|
238
|
+
// const type = mod.getChildAt(1) as ts.Identifier;
|
|
239
|
+
// console.log("MODULE", type.text)
|
|
240
|
+
// break;
|
|
241
|
+
// case ts.SyntaxKind.Identifier:
|
|
242
|
+
// break;
|
|
243
|
+
// case ts.SyntaxKind.ClassDeclaration:
|
|
244
|
+
// case ts.SyntaxKind.SingleLineCommentTrivia:
|
|
245
|
+
// console.log("comment: " + node.getText())
|
|
246
|
+
// break;
|
|
247
|
+
case ts.SyntaxKind.Decorator:
|
|
248
|
+
break;
|
|
249
|
+
case ts.SyntaxKind.MethodDeclaration:
|
|
250
|
+
lastTypeFound = null;
|
|
251
|
+
serializeField = false;
|
|
252
|
+
dontSerialize = false;
|
|
253
|
+
resetExportNextClass();
|
|
254
|
+
if (!context)
|
|
255
|
+
break;
|
|
256
|
+
// TODO: always emit at least OnEnable method per class so generated components have toggle in editor
|
|
257
|
+
var meth = node;
|
|
258
|
+
// const isCoroutine = func.asteriskToken;
|
|
259
|
+
if (!skip && meth.name) {
|
|
260
|
+
var pub_1 = shouldEmitMethod(meth);
|
|
261
|
+
if (!pub_1)
|
|
262
|
+
return;
|
|
263
|
+
var paramsStr = "";
|
|
264
|
+
for (var _k = 0, _l = meth.parameters; _k < _l.length; _k++) {
|
|
265
|
+
var param = _l[_k];
|
|
266
|
+
if (!param || !param.name)
|
|
267
|
+
continue;
|
|
268
|
+
if (paramsStr.length > 0)
|
|
269
|
+
paramsStr += ", ";
|
|
270
|
+
var type = tryResolveTypeRecursive(param);
|
|
271
|
+
if (type === undefined)
|
|
272
|
+
type = "object";
|
|
273
|
+
var paramName = "";
|
|
274
|
+
var paramNameKind = param.name.kind;
|
|
275
|
+
switch (paramNameKind) {
|
|
276
|
+
case ts.SyntaxKind.ObjectBindingPattern:
|
|
277
|
+
paramName = "obj";
|
|
278
|
+
break;
|
|
279
|
+
default:
|
|
280
|
+
paramName = param.name.getText();
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
paramsStr += type + " @" + paramName;
|
|
284
|
+
}
|
|
285
|
+
var methodName = meth.name.getText();
|
|
286
|
+
switch (methodName) {
|
|
287
|
+
case "onEnable":
|
|
288
|
+
methodName = "OnEnable";
|
|
289
|
+
break;
|
|
290
|
+
case "onDisable":
|
|
291
|
+
methodName = "OnDisable";
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
context.onBeforeMethod(methodName);
|
|
295
|
+
// let visibility = pub ? "public" : "private";
|
|
296
|
+
context.append("public void " + methodName + "(" + paramsStr + "){}\n");
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
case ts.SyntaxKind.SetAccessor:
|
|
300
|
+
case ts.SyntaxKind.PropertyDeclaration:
|
|
301
|
+
resetExportNextClass();
|
|
302
|
+
if (!context)
|
|
303
|
+
break;
|
|
304
|
+
if (allowDebugLogs)
|
|
305
|
+
console.log("Found variable", ts.SyntaxKind[node.kind], "\n", node.getText());
|
|
306
|
+
var vardec = node;
|
|
307
|
+
var varName = "@" + vardec.name.getText();
|
|
308
|
+
var pub = shouldEmitMethod(vardec);
|
|
309
|
+
var visibility = pub ? "public" : "private";
|
|
310
|
+
var isAccessible = pub;
|
|
311
|
+
dontSerialize = false;
|
|
312
|
+
if (serializeField) {
|
|
313
|
+
if (allowDebugLogs)
|
|
314
|
+
console.log("[SerializeField]");
|
|
315
|
+
context.appendLine("[UnityEngine.SerializeField]");
|
|
316
|
+
isAccessible = true;
|
|
317
|
+
}
|
|
318
|
+
else if (skip)
|
|
319
|
+
isAccessible = false;
|
|
320
|
+
if (!isAccessible) {
|
|
321
|
+
if (allowDebugLogs)
|
|
322
|
+
console.log("Skip because not public or serializeable");
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
var name_1 = vardec.name.getText();
|
|
326
|
+
if (allowDebugLogs)
|
|
327
|
+
console.log("Variable:", name_1);
|
|
328
|
+
if (name_1.startsWith("\"@") || name_1.startsWith("\"$") || name_1.startsWith("$"))
|
|
329
|
+
break;
|
|
330
|
+
var typeString = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : tryResolveTypeRecursive(node);
|
|
331
|
+
var postFix = "";
|
|
332
|
+
var typeName = (_f = vardec.type) === null || _f === void 0 ? void 0 : _f.getText();
|
|
333
|
+
var shouldCommentTheLine = typeString === undefined;
|
|
334
|
+
if (typeString === undefined) {
|
|
335
|
+
postFix = " → Could not resolve C# type";
|
|
336
|
+
}
|
|
337
|
+
var assignment = "";
|
|
338
|
+
if (typeString !== undefined) {
|
|
339
|
+
for (var _m = 0, _o = node.getChildren(); _m < _o.length; _m++) {
|
|
340
|
+
var ch = _o[_m];
|
|
341
|
+
switch (ch.kind) {
|
|
342
|
+
default:
|
|
343
|
+
// console.log("Unknown assignment:", ts.SyntaxKind[ch.kind]);
|
|
344
|
+
break;
|
|
345
|
+
case ts.SyntaxKind.NewExpression:
|
|
346
|
+
assignment = " = " + getTypeForAssignment(ch, typeString);
|
|
347
|
+
break;
|
|
348
|
+
case ts.SyntaxKind.FalseKeyword:
|
|
349
|
+
case ts.SyntaxKind.TrueKeyword:
|
|
350
|
+
assignment = " = " + ch.getText();
|
|
351
|
+
break;
|
|
352
|
+
case ts.SyntaxKind.StringLiteral:
|
|
353
|
+
var str = ch;
|
|
354
|
+
assignment = " = \"" + str.text + "\"";
|
|
355
|
+
break;
|
|
356
|
+
case ts.SyntaxKind.FirstLiteralToken:
|
|
357
|
+
var lit = ch;
|
|
358
|
+
assignment = " = " + lit.text;
|
|
359
|
+
if (ts.isNumericLiteral(lit))
|
|
360
|
+
assignment += "f";
|
|
361
|
+
break;
|
|
362
|
+
case ts.SyntaxKind.ArrayLiteralExpression:
|
|
363
|
+
var arr = ch;
|
|
364
|
+
assignment = " = new " + typeString;
|
|
365
|
+
// if (arr.elements.length > 0) {
|
|
366
|
+
assignment += "{" + arr.elements.map(function (e) { return " " + getTypeForAssignment(e); }) + " }";
|
|
367
|
+
// }
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
var requireEndIf = false;
|
|
373
|
+
if (ifdefSections.length > 0) {
|
|
374
|
+
requireEndIf = true;
|
|
375
|
+
context.appendLine("#ifdef " + ifdefSections.pop());
|
|
376
|
+
}
|
|
377
|
+
if (typeString === undefined)
|
|
378
|
+
typeString = typeName;
|
|
379
|
+
if (typeString === "[]") {
|
|
380
|
+
if (allowDebugLogs)
|
|
381
|
+
console.log("Unknown array type for \"" + varName + " " + typeName + "\" - your type is probably not known (did you just create it this session?) and you might need to regenerate the Typemap in Unity. Go to \"Needle Engine/Internal/Generate Type Map for component compiler");
|
|
382
|
+
// typeString = "object[]";
|
|
383
|
+
// assignment = " = new object[0]";
|
|
384
|
+
shouldCommentTheLine = true;
|
|
385
|
+
}
|
|
386
|
+
context.onBeforeField(varName);
|
|
387
|
+
if (allowDebugLogs)
|
|
388
|
+
console.log("EMIT member: \"" + typeString + "\" " + varName, assignment, "Last type found:", lastTypeFound);
|
|
389
|
+
var prefix = shouldCommentTheLine ? "// " : "";
|
|
390
|
+
var isUnityEditorType = typeString === null || typeString === void 0 ? void 0 : typeString.includes("UnityEditor");
|
|
391
|
+
if (isUnityEditorType) {
|
|
392
|
+
context.appendLine("#if UNITY_EDITOR");
|
|
393
|
+
}
|
|
394
|
+
context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";" + postFix + "\n");
|
|
395
|
+
if (isUnityEditorType) {
|
|
396
|
+
context.appendLine("#endif");
|
|
397
|
+
}
|
|
398
|
+
lastTypeFound = null;
|
|
399
|
+
if (requireEndIf) {
|
|
400
|
+
context.appendLine("#endif");
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
case ts.SyntaxKind.ClassDeclaration:
|
|
404
|
+
serializeField = false;
|
|
405
|
+
var dec = node;
|
|
406
|
+
// a class must inherit a component
|
|
407
|
+
var inheritsComponent = testInheritsComponent(node);
|
|
408
|
+
if (!dontExportNextClass && (lastTypeFound || exportNextClass || inheritsComponent)) {
|
|
409
|
+
resetExportNextClass();
|
|
410
|
+
var name_2 = (_g = dec.name) === null || _g === void 0 ? void 0 : _g.escapedText;
|
|
411
|
+
if (allowDebugLogs)
|
|
412
|
+
console.log("Found class: ", name_2);
|
|
413
|
+
var namespace = (_h = tryParseNamespace(node)) !== null && _h !== void 0 ? _h : "Needle.Typescript.GeneratedComponents";
|
|
414
|
+
if (allowDebugLogs)
|
|
415
|
+
console.log("NAMESPACE", namespace);
|
|
416
|
+
var newContext = new ExportContext(outputDir, name_2 + ".cs");
|
|
417
|
+
newContext.appendLine("// auto generated code - do not edit directly");
|
|
418
|
+
newContext.appendLine("");
|
|
419
|
+
newContext.appendLine("#pragma warning disable");
|
|
420
|
+
newContext.appendLine("");
|
|
421
|
+
newContext.appendLine("namespace " + namespace);
|
|
422
|
+
newContext.appendLine("{");
|
|
423
|
+
newContext.indentLevel += 1;
|
|
424
|
+
// newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
|
|
425
|
+
var typeName_1 = "UnityEngine.MonoBehaviour";
|
|
426
|
+
if (typeof inheritsComponent === "string")
|
|
427
|
+
typeName_1 = inheritsComponent;
|
|
428
|
+
if (lastTypeFound)
|
|
429
|
+
typeName_1 = lastTypeFound;
|
|
430
|
+
if (allowDebugLogs)
|
|
431
|
+
console.log(name_2 + " inherits " + typeName_1);
|
|
432
|
+
var modifiers = "";
|
|
433
|
+
if (dec.modifiers) {
|
|
434
|
+
for (var _p = 0, _q = dec.modifiers; _p < _q.length; _p++) {
|
|
435
|
+
var mod = _q[_p];
|
|
436
|
+
switch (mod.getText()) {
|
|
437
|
+
case "abstract":
|
|
438
|
+
modifiers += " abstract";
|
|
439
|
+
if (allowDebugLogs)
|
|
440
|
+
console.log(name_2 + " is abstract");
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
modifiers += " partial";
|
|
446
|
+
// If it's a custom class and decorated with @type object then we want to make it serializable
|
|
447
|
+
if (typeName_1 === "object") {
|
|
448
|
+
newContext.appendLine("[System.Serializable]");
|
|
449
|
+
}
|
|
450
|
+
newContext.appendLine("public " + modifiers.trim() + " class " + name_2 + " : " + typeName_1);
|
|
451
|
+
newContext.appendLine("{");
|
|
452
|
+
newContext.indentLevel += 1;
|
|
453
|
+
newContext.classEnd = dec.end;
|
|
454
|
+
contexts.push(newContext);
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
if (allowDebugLogs)
|
|
458
|
+
console.log("Class type is unknown and will not generate a component: ", (_j = dec.name) === null || _j === void 0 ? void 0 : _j.escapedText);
|
|
459
|
+
}
|
|
460
|
+
lastTypeFound = null;
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
function testInheritsComponent(node) {
|
|
464
|
+
switch (node.kind) {
|
|
465
|
+
case ts.SyntaxKind.ClassDeclaration:
|
|
466
|
+
var dec = node;
|
|
467
|
+
if (dec.heritageClauses) {
|
|
468
|
+
for (var _i = 0, _a = dec.heritageClauses; _i < _a.length; _i++) {
|
|
469
|
+
var h = _a[_i];
|
|
470
|
+
if (h.types.length <= 0)
|
|
471
|
+
continue;
|
|
472
|
+
for (var _b = 0, _c = h.types; _b < _c.length; _b++) {
|
|
473
|
+
var type = _c[_b];
|
|
474
|
+
// const symbol = program.getTypeChecker().getSymbolAtLocation(type.expression);
|
|
475
|
+
// console.log(symbol);
|
|
476
|
+
var text = type.expression.getText();
|
|
477
|
+
if (text === "Component")
|
|
478
|
+
return true;
|
|
479
|
+
if (text === "Behaviour")
|
|
480
|
+
return true;
|
|
481
|
+
var known = tryGetKnownType(text);
|
|
482
|
+
if (known)
|
|
483
|
+
return known;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
function getTypeForAssignment(node, typeString) {
|
|
492
|
+
// console.log("-------------------\nAssign", ts.SyntaxKind[node.kind]);
|
|
493
|
+
switch (node.kind) {
|
|
494
|
+
case ts.SyntaxKind.FirstLiteralToken:
|
|
495
|
+
return node.getText();
|
|
496
|
+
case ts.SyntaxKind.NewExpression:
|
|
497
|
+
var type = undefined;
|
|
498
|
+
var args = undefined;
|
|
499
|
+
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
|
|
500
|
+
var ch = _a[_i];
|
|
501
|
+
var text = ch.getText();
|
|
502
|
+
console.log("child", ts.SyntaxKind[ch.kind], text);
|
|
503
|
+
switch (ch.kind) {
|
|
504
|
+
case ts.SyntaxKind.Identifier:
|
|
505
|
+
case ts.SyntaxKind.PropertyAccessExpression:
|
|
506
|
+
type = tryGetTypeFromText(text);
|
|
507
|
+
break;
|
|
508
|
+
case ts.SyntaxKind.SyntaxList:
|
|
509
|
+
for (var _b = 0, _c = ch.getChildren(); _b < _c.length; _b++) {
|
|
510
|
+
var arg = _c[_b];
|
|
511
|
+
if (args === undefined)
|
|
512
|
+
args = "";
|
|
513
|
+
var res = getTypeForAssignment(arg, typeString);
|
|
514
|
+
// handle floats being assigned with "f" suffix
|
|
515
|
+
if (Number.parseFloat(res) >= 0) {
|
|
516
|
+
args += res + "f";
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
args += res;
|
|
520
|
+
if (res === ",")
|
|
521
|
+
args += " ";
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (!args)
|
|
528
|
+
args = "";
|
|
529
|
+
if (type || typeString) {
|
|
530
|
+
if (typeString) {
|
|
531
|
+
console.log("Override type", type, typeString);
|
|
532
|
+
type = typeString;
|
|
533
|
+
}
|
|
534
|
+
return "new " + type + "(" + args + ")";
|
|
535
|
+
}
|
|
536
|
+
// const expType = node.getChildren().find(c => c.kind === ts.SyntaxKind.Identifier);
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
var str = node.getText();
|
|
540
|
+
if (allowDebugLogs)
|
|
541
|
+
console.log("Unknown assignment:", str, ts.SyntaxKind[node.kind]);
|
|
542
|
+
return str;
|
|
543
|
+
}
|
|
544
|
+
function shouldEmitMethod(node) {
|
|
545
|
+
if (node.kind === ts.SyntaxKind.PublicKeyword) {
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
548
|
+
else if (node.kind === ts.SyntaxKind.PrivateKeyword || node.kind === ts.SyntaxKind.ProtectedKeyword) {
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
// check if its static
|
|
552
|
+
else if (node.kind === ts.SyntaxKind.StaticKeyword) {
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
// check if its abstract
|
|
556
|
+
else if (node.kind === ts.SyntaxKind.AbstractKeyword) {
|
|
557
|
+
return false;
|
|
558
|
+
}
|
|
559
|
+
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
|
|
560
|
+
var ch = _a[_i];
|
|
561
|
+
if (!shouldEmitMethod(ch))
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
function tryParseNamespace(node, namespace) {
|
|
567
|
+
// console.log("TRAVERSE - " + ts.SyntaxKind[node.kind]);
|
|
568
|
+
switch (node.kind) {
|
|
569
|
+
case ts.SyntaxKind.ModuleDeclaration:
|
|
570
|
+
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
|
|
571
|
+
var ch = _a[_i];
|
|
572
|
+
// console.log("-- TRAVERSE - " + ts.SyntaxKind[ch.kind]);
|
|
573
|
+
switch (ch.kind) {
|
|
574
|
+
case ts.SyntaxKind.Identifier:
|
|
575
|
+
var id = ch;
|
|
576
|
+
if (id.text) {
|
|
577
|
+
if (!namespace)
|
|
578
|
+
namespace = "";
|
|
579
|
+
namespace = id.text + (namespace ? "." : "") + namespace;
|
|
580
|
+
}
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
if (node.parent) {
|
|
587
|
+
return tryParseNamespace(node.parent, namespace);
|
|
588
|
+
}
|
|
589
|
+
return namespace;
|
|
590
|
+
}
|
|
591
|
+
function tryGetTypeFromText(typeName) {
|
|
592
|
+
// if a type is imported via some namespace e.g. THREE.AnimationClip
|
|
593
|
+
// we want to remove that namespace / import name
|
|
594
|
+
var separatorIndex = typeName.lastIndexOf(".");
|
|
595
|
+
if (separatorIndex > 0) {
|
|
596
|
+
var newName = typeName.substring(separatorIndex + 1);
|
|
597
|
+
if (allowDebugLogs)
|
|
598
|
+
console.log("Remove import name from type: \"" + typeName + "\" → \"" + newName + "\"");
|
|
599
|
+
typeName = newName;
|
|
600
|
+
}
|
|
601
|
+
var res = dict[typeName];
|
|
602
|
+
if (res === undefined) {
|
|
603
|
+
switch (typeName) {
|
|
604
|
+
case "Array":
|
|
605
|
+
break;
|
|
606
|
+
default:
|
|
607
|
+
var knownType = tryGetKnownType(typeName);
|
|
608
|
+
res = knownType !== null && knownType !== void 0 ? knownType : undefined;
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// console.log(typeName, res);
|
|
613
|
+
return res;
|
|
614
|
+
}
|
|
615
|
+
function tryResolveTypeRecursive(node) {
|
|
616
|
+
if (!node)
|
|
617
|
+
return undefined;
|
|
618
|
+
// skip decorators (e.g. @serializable() may break array generation)
|
|
619
|
+
if (node.kind === ts.SyntaxKind.Decorator)
|
|
620
|
+
return undefined;
|
|
621
|
+
var typeName = node === null || node === void 0 ? void 0 : node.getText();
|
|
622
|
+
var varDec = node;
|
|
623
|
+
if (varDec.type) {
|
|
624
|
+
typeName = varDec.type.getText();
|
|
625
|
+
}
|
|
626
|
+
var res = undefined;
|
|
627
|
+
// if it's a { x: number } inline object type:
|
|
628
|
+
if (typeName.startsWith("{")) {
|
|
629
|
+
// check if it has XYZW we assume it's a vector
|
|
630
|
+
var hasX = typeName.includes("x");
|
|
631
|
+
var hasY = typeName.includes("y");
|
|
632
|
+
var hasZ = typeName.includes("z");
|
|
633
|
+
var hasW = typeName.includes("w");
|
|
634
|
+
if (hasX && hasY && hasZ && hasW) {
|
|
635
|
+
return tryGetTypeFromText("Vector4");
|
|
636
|
+
}
|
|
637
|
+
else if (hasX && hasY && hasZ) {
|
|
638
|
+
return tryGetTypeFromText("Vector3");
|
|
639
|
+
}
|
|
640
|
+
else if (hasX && hasY) {
|
|
641
|
+
return tryGetTypeFromText("Vector2");
|
|
642
|
+
}
|
|
643
|
+
return "object";
|
|
644
|
+
}
|
|
645
|
+
// const kindName = ts.SyntaxKind[node.kind];
|
|
646
|
+
// console.log("Unknown type: " + typeName);
|
|
647
|
+
switch (node.kind) {
|
|
648
|
+
case ts.SyntaxKind.ObjectBindingPattern:
|
|
649
|
+
res = "object";
|
|
650
|
+
break;
|
|
651
|
+
// case ts.SyntaxKind.SyntaxList:
|
|
652
|
+
// const list = node as ts.SyntaxList;
|
|
653
|
+
// for (const ch of list._children) {
|
|
654
|
+
// res = tryResolveTypeRecursive(ch);
|
|
655
|
+
// }
|
|
656
|
+
// break;
|
|
657
|
+
case ts.SyntaxKind.UnionType:
|
|
658
|
+
var union = node;
|
|
659
|
+
for (var _i = 0, _a = union.types; _i < _a.length; _i++) {
|
|
660
|
+
var t = _a[_i];
|
|
661
|
+
res = tryResolveTypeRecursive(t);
|
|
662
|
+
if (res !== undefined)
|
|
663
|
+
return res;
|
|
664
|
+
}
|
|
665
|
+
break;
|
|
666
|
+
case ts.SyntaxKind.ArrayType:
|
|
667
|
+
res = "[]";
|
|
668
|
+
break;
|
|
669
|
+
case ts.SyntaxKind.TypeReference:
|
|
670
|
+
var typeRef = node;
|
|
671
|
+
var typeName_2 = typeRef.typeName.getText();
|
|
672
|
+
if (allowDebugLogs)
|
|
673
|
+
console.log("TypeReference:", typeName_2);
|
|
674
|
+
switch (typeName_2) {
|
|
675
|
+
case "Array":
|
|
676
|
+
break;
|
|
677
|
+
default:
|
|
678
|
+
return tryGetTypeFromText(typeName_2);
|
|
679
|
+
}
|
|
680
|
+
// return res;
|
|
681
|
+
break;
|
|
682
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
683
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
684
|
+
case ts.SyntaxKind.StringKeyword:
|
|
685
|
+
case ts.SyntaxKind.ObjectKeyword:
|
|
686
|
+
var keyword = node.getText();
|
|
687
|
+
// the basic keywords are declared in the static dictionary
|
|
688
|
+
// no need for a complex lookup
|
|
689
|
+
res = dict[keyword];
|
|
690
|
+
break;
|
|
691
|
+
case ts.SyntaxKind.Identifier:
|
|
692
|
+
var id = node;
|
|
693
|
+
switch (id.text) {
|
|
694
|
+
// if we have an array we dont want to use the System.Array as a type but just make it to the array syntax
|
|
695
|
+
case "Array":
|
|
696
|
+
res = "[]";
|
|
697
|
+
break;
|
|
698
|
+
default:
|
|
699
|
+
// console.log(id.text);
|
|
700
|
+
// res = tryGetTypeFromText(id.text);
|
|
701
|
+
break;
|
|
702
|
+
}
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
var isInGenericDeclaration = false;
|
|
706
|
+
for (var _b = 0, _c = node.getChildren(); _b < _c.length; _b++) {
|
|
707
|
+
var child = _c[_b];
|
|
708
|
+
// Fix https://linear.app/needle/issue/NE-4423
|
|
709
|
+
if (child.kind === ts.SyntaxKind.Block) {
|
|
710
|
+
if (allowDebugLogs)
|
|
711
|
+
console.log("Skip block");
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
if (allowDebugLogs)
|
|
715
|
+
console.log("Child type: " + ts.SyntaxKind[child.kind]);
|
|
716
|
+
var isGenericStart = false;
|
|
717
|
+
var isAssignment = false;
|
|
718
|
+
switch (child.kind) {
|
|
719
|
+
case ts.SyntaxKind.FirstAssignment:
|
|
720
|
+
isAssignment = true;
|
|
721
|
+
break;
|
|
722
|
+
case ts.SyntaxKind.FirstBinaryOperator:
|
|
723
|
+
// console.log("Generic start: " + child.getText());
|
|
724
|
+
isInGenericDeclaration = true;
|
|
725
|
+
isGenericStart = true;
|
|
726
|
+
break;
|
|
727
|
+
case ts.SyntaxKind.GreaterThanGreaterThanToken:
|
|
728
|
+
isInGenericDeclaration = false;
|
|
729
|
+
// console.log("Generic end: " + child.getText());
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
// if (isAssignment) break;
|
|
733
|
+
var childResult = tryResolveTypeRecursive(child);
|
|
734
|
+
if (childResult !== undefined) {
|
|
735
|
+
if (res === undefined)
|
|
736
|
+
res = "";
|
|
737
|
+
if (allowDebugLogs)
|
|
738
|
+
console.log("Child: " + ts.SyntaxKind[child.kind] + " → " + childResult);
|
|
739
|
+
// if the thing is a generic return as generic result
|
|
740
|
+
if (isInGenericDeclaration && !res.includes("[]")) {
|
|
741
|
+
res = "<" + childResult + ">";
|
|
742
|
+
}
|
|
743
|
+
// we got a generic result, these need to be appended
|
|
744
|
+
else if (childResult.startsWith("<")) {
|
|
745
|
+
res += childResult;
|
|
746
|
+
}
|
|
747
|
+
// concat default
|
|
748
|
+
else
|
|
749
|
+
res = childResult + res;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
// if (ts.isTypeReferenceNode(node)) {
|
|
753
|
+
// const typeRef = node as ts.TypeReferenceNode;
|
|
754
|
+
// const typeName = typeRef.typeName.getText();
|
|
755
|
+
// switch (typeName) {
|
|
756
|
+
// case "Array":
|
|
757
|
+
// res += "[]";
|
|
758
|
+
// return res;
|
|
759
|
+
// }
|
|
760
|
+
// }
|
|
761
|
+
return res;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
exports.run = run;
|
|
766
|
+
if (process) {
|
|
767
|
+
if (process.argv.length < 4) {
|
|
768
|
+
console.error("Missing args, call with: <output_dir> <input_files>");
|
|
769
|
+
}
|
|
770
|
+
else {
|
|
771
|
+
var outputDir_1 = process.argv[2];
|
|
772
|
+
var fileNames = process.argv.slice(3);
|
|
773
|
+
fileNames.forEach(function (fileName) {
|
|
774
|
+
try {
|
|
775
|
+
if (!fs.existsSync(fileName)) {
|
|
776
|
+
console.error("File not found: " + fileName);
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
var code = (0, fs_1.readFileSync)(fileName).toString();
|
|
780
|
+
compile(code, fileName, outputDir_1);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
catch (e) {
|
|
784
|
+
console.error(e);
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
}
|