@needle-tools/needle-component-compiler 3.0.0-alpha.1.b3ca219 → 3.0.0-alpha.2.873d456

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