@needle-tools/needle-component-compiler 1.6.2 → 1.7.1
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 +12 -0
- package/package.json +1 -1
- package/src/component-compiler.js +180 -60
- package/src/component-compiler.ts +177 -48
- package/src/test.ts +29 -4
- package/src/types.js +2 -0
package/Changelog.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to this package will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
5
5
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [1.7.1] - 2022-07-25
|
|
8
|
+
- fix array type codegen, for example ``scenes: Array<AssetReference> = [];``, see issue https://github.com/needle-tools/needle-tiny-playground/issues/285
|
|
9
|
+
|
|
10
|
+
## [1.7.0] - 2022-07-14
|
|
11
|
+
- change: skip non-serializeable variables (private without ``@serializable``)
|
|
12
|
+
- improve member type generation
|
|
13
|
+
- fix bug in type generation for array types
|
|
14
|
+
- add/improve initial assignment codegen for object types
|
|
15
|
+
|
|
16
|
+
## [1.6.3] - 2022-07-12
|
|
17
|
+
- add warning when class type is unknown
|
|
18
|
+
|
|
7
19
|
## [1.6.2] - 2022-07-11
|
|
8
20
|
- fix ``@type`` for class declaration
|
|
9
21
|
|
package/package.json
CHANGED
|
@@ -38,7 +38,8 @@ function tryGetKnownType(str) {
|
|
|
38
38
|
}
|
|
39
39
|
if (typesFileContent) {
|
|
40
40
|
var fullType = typesFileContent[str];
|
|
41
|
-
|
|
41
|
+
if (fullType)
|
|
42
|
+
console.log(fullType);
|
|
42
43
|
return fullType;
|
|
43
44
|
}
|
|
44
45
|
return null;
|
|
@@ -114,7 +115,7 @@ function run(program, outputDir, sourceFile) {
|
|
|
114
115
|
ts.forEachChild(node, traverseFile);
|
|
115
116
|
}
|
|
116
117
|
function visit(node) {
|
|
117
|
-
var _a, _b, _c, _d, _e;
|
|
118
|
+
var _a, _b, _c, _d, _e, _f;
|
|
118
119
|
var context = contexts.length > 0 ? contexts[contexts.length - 1] : null;
|
|
119
120
|
if (context) {
|
|
120
121
|
if ((context === null || context === void 0 ? void 0 : context.classEnd) > 0 && node.pos >= (context === null || context === void 0 ? void 0 : context.classEnd)) {
|
|
@@ -194,8 +195,8 @@ function run(program, outputDir, sourceFile) {
|
|
|
194
195
|
// const isCoroutine = func.asteriskToken;
|
|
195
196
|
if (meth.name) {
|
|
196
197
|
var paramsStr = "";
|
|
197
|
-
for (var
|
|
198
|
-
var param = _g
|
|
198
|
+
for (var _g = 0, _h = meth.parameters; _g < _h.length; _g++) {
|
|
199
|
+
var param = _h[_g];
|
|
199
200
|
if (!param || !param.name)
|
|
200
201
|
continue;
|
|
201
202
|
if (paramsStr.length > 0)
|
|
@@ -217,20 +218,41 @@ function run(program, outputDir, sourceFile) {
|
|
|
217
218
|
break;
|
|
218
219
|
console.log("Found variable", node.getText());
|
|
219
220
|
var vardec = node;
|
|
221
|
+
var varName = "@" + vardec.name.getText();
|
|
222
|
+
var pub = isPublic(vardec);
|
|
223
|
+
var visibility = pub ? "public" : "private";
|
|
224
|
+
var isAccessible = pub;
|
|
225
|
+
if (!pub && serializeField) {
|
|
226
|
+
console.log("[SerializeField]");
|
|
227
|
+
context.appendLine("[UnityEngine.SerializeField]");
|
|
228
|
+
isAccessible = true;
|
|
229
|
+
}
|
|
230
|
+
if (!isAccessible) {
|
|
231
|
+
console.log("Skip because not public or serializeable");
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
220
234
|
var name_1 = vardec.name.getText();
|
|
221
|
-
console.log(name_1);
|
|
235
|
+
console.log("Variable:", name_1);
|
|
222
236
|
if (name_1.startsWith("\"@") || name_1.startsWith("\"$") || name_1.startsWith("$"))
|
|
223
237
|
break;
|
|
224
238
|
var typeString = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : tryResolveTypeRecursive(node);
|
|
239
|
+
var postFix = "";
|
|
240
|
+
var typeName = (_c = vardec.type) === null || _c === void 0 ? void 0 : _c.getText();
|
|
225
241
|
if (typeString === undefined) {
|
|
226
|
-
|
|
242
|
+
postFix = " → Could not resolve C# type";
|
|
227
243
|
}
|
|
228
244
|
var prefix = typeString === undefined ? "// " : "";
|
|
229
245
|
var assignment = "";
|
|
230
246
|
if (typeString !== undefined) {
|
|
231
|
-
for (var
|
|
232
|
-
var ch = _j
|
|
247
|
+
for (var _j = 0, _k = node.getChildren(); _j < _k.length; _j++) {
|
|
248
|
+
var ch = _k[_j];
|
|
233
249
|
switch (ch.kind) {
|
|
250
|
+
default:
|
|
251
|
+
// console.log("Unknown assignment:", ts.SyntaxKind[ch.kind]);
|
|
252
|
+
break;
|
|
253
|
+
case ts.SyntaxKind.NewExpression:
|
|
254
|
+
assignment = " = " + getTypeForAssignment(ch);
|
|
255
|
+
break;
|
|
234
256
|
case ts.SyntaxKind.FalseKeyword:
|
|
235
257
|
case ts.SyntaxKind.TrueKeyword:
|
|
236
258
|
assignment = " = " + ch.getText();
|
|
@@ -247,24 +269,23 @@ function run(program, outputDir, sourceFile) {
|
|
|
247
269
|
break;
|
|
248
270
|
case ts.SyntaxKind.ArrayLiteralExpression:
|
|
249
271
|
var arr = ch;
|
|
250
|
-
assignment = " = new " + typeString
|
|
272
|
+
assignment = " = new " + typeString;
|
|
273
|
+
// if (arr.elements.length > 0) {
|
|
274
|
+
assignment += "{" + arr.elements.map(function (e) { return " " + getTypeForAssignment(e); }) + " }";
|
|
275
|
+
// }
|
|
251
276
|
break;
|
|
252
277
|
}
|
|
253
278
|
}
|
|
254
279
|
}
|
|
255
|
-
var varName = "@" + vardec.name.getText();
|
|
256
|
-
var pub = isPublic(vardec);
|
|
257
|
-
var visibility = pub ? "public" : "private";
|
|
258
|
-
if (!pub && serializeField) {
|
|
259
|
-
console.log("SERIALIZE");
|
|
260
|
-
context.appendLine("[UnityEngine.SerializeField]");
|
|
261
|
-
}
|
|
262
280
|
var requireEndIf = false;
|
|
263
281
|
if (ifdefSections.length > 0) {
|
|
264
282
|
requireEndIf = true;
|
|
265
283
|
context.appendLine("#ifdef " + ifdefSections.pop());
|
|
266
284
|
}
|
|
267
|
-
|
|
285
|
+
if (typeString === undefined)
|
|
286
|
+
typeString = typeName;
|
|
287
|
+
console.log("EMIT member: " + typeString + " " + varName);
|
|
288
|
+
context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";" + postFix + "\n");
|
|
268
289
|
lastTypeFound = null;
|
|
269
290
|
if (requireEndIf) {
|
|
270
291
|
context.appendLine("#endif");
|
|
@@ -290,18 +311,21 @@ function run(program, outputDir, sourceFile) {
|
|
|
290
311
|
newContext.appendLine("{");
|
|
291
312
|
newContext.indentLevel += 1;
|
|
292
313
|
// newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
|
|
293
|
-
var
|
|
314
|
+
var typeName_1 = "UnityEngine.MonoBehaviour";
|
|
294
315
|
if (typeof inheritsComponent === "string")
|
|
295
|
-
|
|
316
|
+
typeName_1 = inheritsComponent;
|
|
296
317
|
if (lastTypeFound)
|
|
297
|
-
|
|
298
|
-
console.log(name_2 + " inherits " +
|
|
299
|
-
newContext.appendLine("public partial class " + name_2 + " : " +
|
|
318
|
+
typeName_1 = lastTypeFound;
|
|
319
|
+
console.log(name_2 + " inherits " + typeName_1);
|
|
320
|
+
newContext.appendLine("public partial class " + name_2 + " : " + typeName_1);
|
|
300
321
|
newContext.appendLine("{");
|
|
301
322
|
newContext.indentLevel += 1;
|
|
302
323
|
newContext.classEnd = dec.end;
|
|
303
324
|
contexts.push(newContext);
|
|
304
325
|
}
|
|
326
|
+
else {
|
|
327
|
+
console.log("Class type is unknown and will not generate a component: ", (_f = dec.name) === null || _f === void 0 ? void 0 : _f.escapedText);
|
|
328
|
+
}
|
|
305
329
|
lastTypeFound = null;
|
|
306
330
|
break;
|
|
307
331
|
}
|
|
@@ -333,6 +357,36 @@ function run(program, outputDir, sourceFile) {
|
|
|
333
357
|
}
|
|
334
358
|
return false;
|
|
335
359
|
}
|
|
360
|
+
function getTypeForAssignment(node) {
|
|
361
|
+
// console.log("-------------------\nAssign", ts.SyntaxKind[node.kind]);
|
|
362
|
+
switch (node.kind) {
|
|
363
|
+
case ts.SyntaxKind.FirstLiteralToken:
|
|
364
|
+
return node.getText();
|
|
365
|
+
case ts.SyntaxKind.NewExpression:
|
|
366
|
+
var type = undefined;
|
|
367
|
+
var args = undefined;
|
|
368
|
+
for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
|
|
369
|
+
var ch = _a[_i];
|
|
370
|
+
// console.log("child", ts.SyntaxKind[ch.kind]);
|
|
371
|
+
switch (ch.kind) {
|
|
372
|
+
case ts.SyntaxKind.PropertyAccessExpression:
|
|
373
|
+
type = tryGetTypeFromText(ch.getText());
|
|
374
|
+
break;
|
|
375
|
+
case ts.SyntaxKind.SyntaxList:
|
|
376
|
+
args = ch.getText();
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (!args)
|
|
381
|
+
args = "";
|
|
382
|
+
if (type)
|
|
383
|
+
return "new " + type + "(" + args + ")";
|
|
384
|
+
// const expType = node.getChildren().find(c => c.kind === ts.SyntaxKind.Identifier);
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
var str = node.getText();
|
|
388
|
+
return str;
|
|
389
|
+
}
|
|
336
390
|
function isPublic(node) {
|
|
337
391
|
if (node.kind === ts.SyntaxKind.PublicKeyword) {
|
|
338
392
|
return true;
|
|
@@ -372,8 +426,21 @@ function run(program, outputDir, sourceFile) {
|
|
|
372
426
|
}
|
|
373
427
|
return namespace;
|
|
374
428
|
}
|
|
429
|
+
function tryGetTypeFromText(typeName) {
|
|
430
|
+
var res = dict[typeName];
|
|
431
|
+
if (res === undefined) {
|
|
432
|
+
switch (typeName) {
|
|
433
|
+
case "Array":
|
|
434
|
+
break;
|
|
435
|
+
default:
|
|
436
|
+
var knownType = tryGetKnownType(typeName);
|
|
437
|
+
res = knownType !== null && knownType !== void 0 ? knownType : undefined;
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return res;
|
|
442
|
+
}
|
|
375
443
|
function tryResolveTypeRecursive(node) {
|
|
376
|
-
var _a;
|
|
377
444
|
if (!node)
|
|
378
445
|
return undefined;
|
|
379
446
|
// skip decorators (e.g. @serializable() may break array generation)
|
|
@@ -384,58 +451,111 @@ function run(program, outputDir, sourceFile) {
|
|
|
384
451
|
if (varDec.type) {
|
|
385
452
|
typeName = varDec.type.getText();
|
|
386
453
|
}
|
|
387
|
-
var res =
|
|
388
|
-
if (res !== undefined) {
|
|
389
|
-
// console.log("FOUND " + res, ts.SyntaxKind[node.kind]);
|
|
390
|
-
// console.log(node);
|
|
391
|
-
return res;
|
|
392
|
-
}
|
|
393
|
-
var knownType = tryGetKnownType(typeName);
|
|
394
|
-
if (knownType)
|
|
395
|
-
return knownType;
|
|
454
|
+
var res = undefined;
|
|
396
455
|
// console.log("Unknown type: " + typeName);
|
|
397
456
|
switch (node.kind) {
|
|
398
|
-
case ts.SyntaxKind.SyntaxList:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
457
|
+
// case ts.SyntaxKind.SyntaxList:
|
|
458
|
+
// const list = node as ts.SyntaxList;
|
|
459
|
+
// for (const ch of list._children) {
|
|
460
|
+
// res = tryResolveTypeRecursive(ch);
|
|
461
|
+
// }
|
|
462
|
+
// break;
|
|
403
463
|
case ts.SyntaxKind.UnionType:
|
|
404
464
|
var union = node;
|
|
405
|
-
for (var _i = 0,
|
|
406
|
-
var t =
|
|
465
|
+
for (var _i = 0, _a = union.types; _i < _a.length; _i++) {
|
|
466
|
+
var t = _a[_i];
|
|
407
467
|
res = tryResolveTypeRecursive(t);
|
|
408
468
|
if (res !== undefined)
|
|
409
469
|
return res;
|
|
410
470
|
}
|
|
411
471
|
break;
|
|
412
472
|
case ts.SyntaxKind.ArrayType:
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
473
|
+
res = "[]";
|
|
474
|
+
break;
|
|
475
|
+
case ts.SyntaxKind.TypeReference:
|
|
476
|
+
var typeRef = node;
|
|
477
|
+
var typeName_2 = typeRef.typeName.getText();
|
|
478
|
+
console.log("TypeReference:", typeName_2);
|
|
479
|
+
switch (typeName_2) {
|
|
480
|
+
case "Array":
|
|
481
|
+
break;
|
|
482
|
+
default:
|
|
483
|
+
return tryGetTypeFromText(typeName_2);
|
|
484
|
+
}
|
|
485
|
+
// return res;
|
|
486
|
+
break;
|
|
487
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
488
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
489
|
+
case ts.SyntaxKind.StringKeyword:
|
|
490
|
+
case ts.SyntaxKind.ObjectKeyword:
|
|
491
|
+
var keyword = node.getText();
|
|
492
|
+
// the basic keywords are declared in the static dictionary
|
|
493
|
+
// no need for a complex lookup
|
|
494
|
+
res = dict[keyword];
|
|
495
|
+
break;
|
|
496
|
+
case ts.SyntaxKind.Identifier:
|
|
497
|
+
var id = node;
|
|
498
|
+
switch (id.text) {
|
|
499
|
+
// if we have an array we dont want to use the System.Array as a type but just make it to the array syntax
|
|
500
|
+
case "Array":
|
|
501
|
+
res = "[]";
|
|
502
|
+
break;
|
|
503
|
+
default:
|
|
504
|
+
// console.log(id.text);
|
|
505
|
+
// res = tryGetTypeFromText(id.text);
|
|
506
|
+
break;
|
|
421
507
|
}
|
|
422
|
-
}
|
|
423
|
-
for (var _c = 0, _d = node.getChildren(); _c < _d.length; _c++) {
|
|
424
|
-
var child = _d[_c];
|
|
425
|
-
if (res !== undefined)
|
|
426
508
|
break;
|
|
427
|
-
console.log("Child type: " + ts.SyntaxKind[child.kind]);
|
|
428
|
-
res = tryResolveTypeRecursive(child);
|
|
429
509
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
var
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
510
|
+
var isInGenericDeclaration = false;
|
|
511
|
+
for (var _b = 0, _c = node.getChildren(); _b < _c.length; _b++) {
|
|
512
|
+
var child = _c[_b];
|
|
513
|
+
// if (res !== undefined) break;
|
|
514
|
+
// console.log("Child type: " + ts.SyntaxKind[child.kind]);
|
|
515
|
+
var isGenericStart = false;
|
|
516
|
+
var isAssignment = false;
|
|
517
|
+
switch (child.kind) {
|
|
518
|
+
case ts.SyntaxKind.FirstAssignment:
|
|
519
|
+
isAssignment = true;
|
|
520
|
+
break;
|
|
521
|
+
case ts.SyntaxKind.FirstBinaryOperator:
|
|
522
|
+
// console.log("Generic start: " + child.getText());
|
|
523
|
+
isInGenericDeclaration = true;
|
|
524
|
+
isGenericStart = true;
|
|
525
|
+
break;
|
|
526
|
+
case ts.SyntaxKind.GreaterThanGreaterThanToken:
|
|
527
|
+
isInGenericDeclaration = false;
|
|
528
|
+
// console.log("Generic end: " + child.getText());
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
// if (isAssignment) break;
|
|
532
|
+
var childResult = tryResolveTypeRecursive(child);
|
|
533
|
+
if (childResult !== undefined) {
|
|
534
|
+
if (res === undefined)
|
|
535
|
+
res = "";
|
|
536
|
+
console.log("Child: " + ts.SyntaxKind[child.kind] + " → " + childResult);
|
|
537
|
+
// if the thing is a generic return as generic result
|
|
538
|
+
if (isInGenericDeclaration && !res.includes("[]")) {
|
|
539
|
+
res = "<" + childResult + ">";
|
|
540
|
+
}
|
|
541
|
+
// we got a generic result, these need to be appended
|
|
542
|
+
else if (childResult.startsWith("<")) {
|
|
543
|
+
res += childResult;
|
|
544
|
+
}
|
|
545
|
+
// concat default
|
|
546
|
+
else
|
|
547
|
+
res = childResult + res;
|
|
437
548
|
}
|
|
438
549
|
}
|
|
550
|
+
// if (ts.isTypeReferenceNode(node)) {
|
|
551
|
+
// const typeRef = node as ts.TypeReferenceNode;
|
|
552
|
+
// const typeName = typeRef.typeName.getText();
|
|
553
|
+
// switch (typeName) {
|
|
554
|
+
// case "Array":
|
|
555
|
+
// res += "[]";
|
|
556
|
+
// return res;
|
|
557
|
+
// }
|
|
558
|
+
// }
|
|
439
559
|
return res;
|
|
440
560
|
}
|
|
441
561
|
}
|
|
@@ -30,7 +30,6 @@ function resetExportNextClass() {
|
|
|
30
30
|
|
|
31
31
|
let typesFileContent: object | undefined | null = undefined;
|
|
32
32
|
function tryGetKnownType(str: string): string | null {
|
|
33
|
-
|
|
34
33
|
if (typesFileContent === undefined) {
|
|
35
34
|
typesFileContent = null;
|
|
36
35
|
const filePath = path.dirname(__dirname) + "/src/types.json";
|
|
@@ -43,7 +42,8 @@ function tryGetKnownType(str: string): string | null {
|
|
|
43
42
|
|
|
44
43
|
if (typesFileContent) {
|
|
45
44
|
const fullType = typesFileContent[str];
|
|
46
|
-
|
|
45
|
+
if (fullType)
|
|
46
|
+
console.log(fullType);
|
|
47
47
|
return fullType;
|
|
48
48
|
}
|
|
49
49
|
return null;
|
|
@@ -240,18 +240,41 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
240
240
|
if (!context) break;
|
|
241
241
|
console.log("Found variable", node.getText());
|
|
242
242
|
const vardec = node as ts.VariableDeclaration;
|
|
243
|
+
|
|
244
|
+
const varName = "@" + vardec.name.getText();
|
|
245
|
+
const pub = isPublic(vardec);
|
|
246
|
+
const visibility = pub ? "public" : "private";
|
|
247
|
+
let isAccessible = pub;
|
|
248
|
+
if (!pub && serializeField) {
|
|
249
|
+
console.log("[SerializeField]");
|
|
250
|
+
context.appendLine("[UnityEngine.SerializeField]");
|
|
251
|
+
isAccessible = true;
|
|
252
|
+
}
|
|
253
|
+
if (!isAccessible) {
|
|
254
|
+
console.log("Skip because not public or serializeable")
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
|
|
243
258
|
const name = vardec.name.getText();
|
|
244
|
-
console.log(name);
|
|
259
|
+
console.log("Variable:", name);
|
|
245
260
|
if (name.startsWith("\"@") || name.startsWith("\"$") || name.startsWith("$")) break;
|
|
246
261
|
let typeString = lastTypeFound ?? tryResolveTypeRecursive(node);
|
|
262
|
+
let postFix = "";
|
|
263
|
+
let typeName = vardec.type?.getText();
|
|
247
264
|
if (typeString === undefined) {
|
|
248
|
-
|
|
265
|
+
postFix = " → Could not resolve C# type";
|
|
249
266
|
}
|
|
250
267
|
const prefix = typeString === undefined ? "// " : "";
|
|
251
268
|
let assignment = "";
|
|
252
269
|
if (typeString !== undefined) {
|
|
253
270
|
for (const ch of node.getChildren()) {
|
|
254
271
|
switch (ch.kind) {
|
|
272
|
+
default:
|
|
273
|
+
// console.log("Unknown assignment:", ts.SyntaxKind[ch.kind]);
|
|
274
|
+
break;
|
|
275
|
+
case ts.SyntaxKind.NewExpression:
|
|
276
|
+
assignment = " = " + getTypeForAssignment(ch);
|
|
277
|
+
break;
|
|
255
278
|
case ts.SyntaxKind.FalseKeyword:
|
|
256
279
|
case ts.SyntaxKind.TrueKeyword:
|
|
257
280
|
assignment = " = " + ch.getText();
|
|
@@ -268,24 +291,22 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
268
291
|
break;
|
|
269
292
|
case ts.SyntaxKind.ArrayLiteralExpression:
|
|
270
293
|
const arr = ch as ts.ArrayLiteralExpression;
|
|
271
|
-
assignment = " = new " + typeString
|
|
294
|
+
assignment = " = new " + typeString;
|
|
295
|
+
// if (arr.elements.length > 0) {
|
|
296
|
+
assignment += "{" + arr.elements.map(e => " " + getTypeForAssignment(e)) + " }";
|
|
297
|
+
// }
|
|
272
298
|
break;
|
|
273
299
|
}
|
|
274
300
|
}
|
|
275
301
|
}
|
|
276
|
-
const varName = "@" + vardec.name.getText();
|
|
277
|
-
const pub = isPublic(vardec);
|
|
278
|
-
const visibility = pub ? "public" : "private";
|
|
279
|
-
if (!pub && serializeField) {
|
|
280
|
-
console.log("SERIALIZE");
|
|
281
|
-
context.appendLine("[UnityEngine.SerializeField]");
|
|
282
|
-
}
|
|
283
302
|
let requireEndIf = false;
|
|
284
303
|
if (ifdefSections.length > 0) {
|
|
285
304
|
requireEndIf = true;
|
|
286
305
|
context.appendLine("#ifdef " + ifdefSections.pop());
|
|
287
306
|
}
|
|
288
|
-
|
|
307
|
+
if (typeString === undefined) typeString = typeName;
|
|
308
|
+
console.log("EMIT member: " + typeString + " " + varName)
|
|
309
|
+
context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";" + postFix + "\n");
|
|
289
310
|
lastTypeFound = null;
|
|
290
311
|
if (requireEndIf) {
|
|
291
312
|
context.appendLine("#endif");
|
|
@@ -314,7 +335,7 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
314
335
|
// newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
|
|
315
336
|
let typeName = "UnityEngine.MonoBehaviour";
|
|
316
337
|
if (typeof inheritsComponent === "string") typeName = inheritsComponent;
|
|
317
|
-
if(lastTypeFound) typeName = lastTypeFound;
|
|
338
|
+
if (lastTypeFound) typeName = lastTypeFound;
|
|
318
339
|
console.log(name + " inherits " + typeName);
|
|
319
340
|
newContext.appendLine("public partial class " + name + " : " + typeName);
|
|
320
341
|
newContext.appendLine("{");
|
|
@@ -322,6 +343,9 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
322
343
|
newContext.classEnd = dec.end;
|
|
323
344
|
contexts.push(newContext);
|
|
324
345
|
}
|
|
346
|
+
else {
|
|
347
|
+
console.log("Class type is unknown and will not generate a component: ", dec.name?.escapedText);
|
|
348
|
+
}
|
|
325
349
|
lastTypeFound = null;
|
|
326
350
|
break;
|
|
327
351
|
}
|
|
@@ -349,6 +373,35 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
349
373
|
return false;
|
|
350
374
|
}
|
|
351
375
|
|
|
376
|
+
function getTypeForAssignment(node: ts.Node) {
|
|
377
|
+
// console.log("-------------------\nAssign", ts.SyntaxKind[node.kind]);
|
|
378
|
+
switch (node.kind) {
|
|
379
|
+
case ts.SyntaxKind.FirstLiteralToken:
|
|
380
|
+
return node.getText();
|
|
381
|
+
case ts.SyntaxKind.NewExpression:
|
|
382
|
+
let type: string | undefined = undefined;
|
|
383
|
+
let args: string | undefined = undefined;
|
|
384
|
+
for (const ch of node.getChildren()) {
|
|
385
|
+
// console.log("child", ts.SyntaxKind[ch.kind]);
|
|
386
|
+
switch (ch.kind) {
|
|
387
|
+
case ts.SyntaxKind.PropertyAccessExpression:
|
|
388
|
+
type = tryGetTypeFromText(ch.getText());
|
|
389
|
+
break;
|
|
390
|
+
case ts.SyntaxKind.SyntaxList:
|
|
391
|
+
args = ch.getText();
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (!args) args = "";
|
|
396
|
+
if (type)
|
|
397
|
+
return "new " + type + "(" + args + ")";
|
|
398
|
+
// const expType = node.getChildren().find(c => c.kind === ts.SyntaxKind.Identifier);
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
const str = node.getText();
|
|
402
|
+
return str;
|
|
403
|
+
}
|
|
404
|
+
|
|
352
405
|
function isPublic(node: ts.Node): boolean {
|
|
353
406
|
if (node.kind === ts.SyntaxKind.PublicKeyword) {
|
|
354
407
|
return true;
|
|
@@ -387,6 +440,21 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
387
440
|
return namespace;
|
|
388
441
|
}
|
|
389
442
|
|
|
443
|
+
function tryGetTypeFromText(typeName: string) {
|
|
444
|
+
let res = dict[typeName];
|
|
445
|
+
if (res === undefined) {
|
|
446
|
+
switch (typeName) {
|
|
447
|
+
case "Array":
|
|
448
|
+
break;
|
|
449
|
+
default:
|
|
450
|
+
const knownType = tryGetKnownType(typeName);
|
|
451
|
+
res = knownType ?? undefined;
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return res;
|
|
456
|
+
}
|
|
457
|
+
|
|
390
458
|
function tryResolveTypeRecursive(node: ts.Node | ts.VariableDeclaration): string | undefined {
|
|
391
459
|
if (!node) return undefined;
|
|
392
460
|
|
|
@@ -401,23 +469,19 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
401
469
|
typeName = varDec.type.getText();
|
|
402
470
|
}
|
|
403
471
|
|
|
404
|
-
let res =
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
return res;
|
|
409
|
-
}
|
|
410
|
-
const knownType = tryGetKnownType(typeName);
|
|
411
|
-
if (knownType)
|
|
412
|
-
return knownType;
|
|
472
|
+
let res: string | undefined = undefined;
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
413
476
|
// console.log("Unknown type: " + typeName);
|
|
414
477
|
|
|
415
478
|
switch (node.kind) {
|
|
416
|
-
case ts.SyntaxKind.SyntaxList:
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
479
|
+
// case ts.SyntaxKind.SyntaxList:
|
|
480
|
+
// const list = node as ts.SyntaxList;
|
|
481
|
+
// for (const ch of list._children) {
|
|
482
|
+
// res = tryResolveTypeRecursive(ch);
|
|
483
|
+
// }
|
|
484
|
+
// break;
|
|
421
485
|
case ts.SyntaxKind.UnionType:
|
|
422
486
|
const union = node as ts.UnionTypeNode;
|
|
423
487
|
for (const t of union.types) {
|
|
@@ -425,33 +489,98 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
425
489
|
if (res !== undefined) return res;
|
|
426
490
|
}
|
|
427
491
|
break;
|
|
492
|
+
|
|
428
493
|
case ts.SyntaxKind.ArrayType:
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
494
|
+
res = "[]";
|
|
495
|
+
break;
|
|
496
|
+
|
|
497
|
+
case ts.SyntaxKind.TypeReference:
|
|
498
|
+
const typeRef = node as ts.TypeReferenceNode;
|
|
499
|
+
const typeName = typeRef.typeName.getText();
|
|
500
|
+
console.log("TypeReference:", typeName);
|
|
501
|
+
switch (typeName) {
|
|
502
|
+
case "Array":
|
|
503
|
+
break;
|
|
504
|
+
default:
|
|
505
|
+
return tryGetTypeFromText(typeName);
|
|
437
506
|
}
|
|
438
|
-
|
|
507
|
+
// return res;
|
|
508
|
+
break;
|
|
439
509
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
510
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
511
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
512
|
+
case ts.SyntaxKind.StringKeyword:
|
|
513
|
+
case ts.SyntaxKind.ObjectKeyword:
|
|
514
|
+
const keyword = node.getText();
|
|
515
|
+
// the basic keywords are declared in the static dictionary
|
|
516
|
+
// no need for a complex lookup
|
|
517
|
+
res = dict[keyword];
|
|
518
|
+
break;
|
|
519
|
+
|
|
520
|
+
case ts.SyntaxKind.Identifier:
|
|
521
|
+
const id = node as ts.Identifier;
|
|
522
|
+
switch (id.text) {
|
|
523
|
+
// if we have an array we dont want to use the System.Array as a type but just make it to the array syntax
|
|
524
|
+
case "Array":
|
|
525
|
+
res = "[]";
|
|
526
|
+
break;
|
|
527
|
+
default:
|
|
528
|
+
// console.log(id.text);
|
|
529
|
+
// res = tryGetTypeFromText(id.text);
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
break;
|
|
444
533
|
}
|
|
445
534
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
535
|
+
let isInGenericDeclaration = false;
|
|
536
|
+
for (const child of node.getChildren()) {
|
|
537
|
+
// if (res !== undefined) break;
|
|
538
|
+
// console.log("Child type: " + ts.SyntaxKind[child.kind]);
|
|
539
|
+
let isGenericStart = false;
|
|
540
|
+
let isAssignment = false;
|
|
541
|
+
switch (child.kind) {
|
|
542
|
+
case ts.SyntaxKind.FirstAssignment:
|
|
543
|
+
isAssignment = true;
|
|
544
|
+
break;
|
|
545
|
+
case ts.SyntaxKind.FirstBinaryOperator:
|
|
546
|
+
// console.log("Generic start: " + child.getText());
|
|
547
|
+
isInGenericDeclaration = true;
|
|
548
|
+
isGenericStart = true;
|
|
549
|
+
break;
|
|
550
|
+
case ts.SyntaxKind.GreaterThanGreaterThanToken:
|
|
551
|
+
isInGenericDeclaration = false;
|
|
552
|
+
// console.log("Generic end: " + child.getText());
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
// if (isAssignment) break;
|
|
556
|
+
const childResult = tryResolveTypeRecursive(child);
|
|
557
|
+
if (childResult !== undefined) {
|
|
558
|
+
if (res === undefined) res = "";
|
|
559
|
+
console.log("Child: " + ts.SyntaxKind[child.kind] + " → " + childResult);
|
|
560
|
+
// if the thing is a generic return as generic result
|
|
561
|
+
if (isInGenericDeclaration && !res.includes("[]")) {
|
|
562
|
+
res = "<" + childResult + ">";
|
|
563
|
+
}
|
|
564
|
+
// we got a generic result, these need to be appended
|
|
565
|
+
else if (childResult.startsWith("<")) {
|
|
566
|
+
res += childResult;
|
|
567
|
+
}
|
|
568
|
+
// concat default
|
|
569
|
+
else
|
|
570
|
+
res = childResult + res;
|
|
453
571
|
}
|
|
454
572
|
}
|
|
573
|
+
|
|
574
|
+
// if (ts.isTypeReferenceNode(node)) {
|
|
575
|
+
// const typeRef = node as ts.TypeReferenceNode;
|
|
576
|
+
// const typeName = typeRef.typeName.getText();
|
|
577
|
+
// switch (typeName) {
|
|
578
|
+
// case "Array":
|
|
579
|
+
// res += "[]";
|
|
580
|
+
// return res;
|
|
581
|
+
// }
|
|
582
|
+
// }
|
|
583
|
+
|
|
455
584
|
return res;
|
|
456
585
|
}
|
|
457
586
|
}
|
package/src/test.ts
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
export class ButtonObject extends Interactable implements IPointerClickHandler, ISerializable {
|
|
1
|
+
import { ThisExpression } from "typescript";
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export class SocLoader extends Behaviour {
|
|
4
|
+
|
|
5
|
+
@serializeable(AssetReference)
|
|
6
|
+
scenes: Array<AssetReference> = [];
|
|
6
7
|
}
|
|
8
|
+
// class Test123 {}
|
|
9
|
+
|
|
10
|
+
export class Bla extends Behaviour
|
|
11
|
+
{
|
|
12
|
+
myNumber:number = 42;
|
|
13
|
+
myBool:boolean = true;
|
|
14
|
+
myString:string = "test";
|
|
15
|
+
numberArr: number[] = [1,2,3];
|
|
16
|
+
myColor : THREE.Color = new THREE.Color(255, 0, 0);
|
|
17
|
+
renderers = new Array<Renderer>();
|
|
18
|
+
renderers2 : Renderer[] = [];
|
|
19
|
+
objArr : object[];
|
|
20
|
+
colArr: THREE.Color[] = [new THREE.Color(1,2,3)];
|
|
21
|
+
map : Map<string> = new Map<string>();
|
|
22
|
+
map2 : Map<object> = new Map<object>();
|
|
23
|
+
private myThing : Test123;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// //@type UnityEngine.MonoBehaviour
|
|
27
|
+
// export class ButtonObject extends Interactable implements IPointerClickHandler, ISerializable {
|
|
28
|
+
|
|
29
|
+
// //@type UnityEngine.Transform[]
|
|
30
|
+
// myType?: SceneFXWindow;
|
|
31
|
+
// }
|
|
7
32
|
|
|
8
33
|
// import { Behaviour } from "needle.tiny.engine/engine-components/Component";
|
|
9
34
|
// import { RoomEntity } from "./Room";
|
package/src/types.js
CHANGED
|
@@ -3,9 +3,11 @@ exports.__esModule = true;
|
|
|
3
3
|
exports.delint = void 0;
|
|
4
4
|
|
|
5
5
|
const dict = {
|
|
6
|
+
"object" : "UnityEngine.Object",
|
|
6
7
|
"number": "float",
|
|
7
8
|
"string": "string",
|
|
8
9
|
"boolean": "bool",
|
|
10
|
+
"Map" : "System.Collections.Generic.HashSet",
|
|
9
11
|
// basic
|
|
10
12
|
"Behaviour" : "UnityEngine.Behaviour",
|
|
11
13
|
"Component" : "UnityEngine.Component",
|