@needle-tools/needle-component-compiler 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +12 -0
- package/package.json +1 -1
- package/src/component-compiler.js +181 -59
- package/src/component-compiler.ts +177 -48
- package/src/test.ts +32 -6
- 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.0] - 2022-07-14
|
|
8
|
+
- change: skip non-serializeable variables (private without ``@serializable``)
|
|
9
|
+
- improve member type generation
|
|
10
|
+
- fix bug in type generation for array types
|
|
11
|
+
- add/improve initial assignment codegen for object types
|
|
12
|
+
|
|
13
|
+
## [1.6.3] - 2022-07-12
|
|
14
|
+
- add warning when class type is unknown
|
|
15
|
+
|
|
16
|
+
## [1.6.2] - 2022-07-11
|
|
17
|
+
- fix ``@type`` for class declaration
|
|
18
|
+
|
|
7
19
|
## [1.6.1] - 2022-07-10
|
|
8
20
|
- add using ``types.json`` json file that will be generated from Unity
|
|
9
21
|
- change ``@type`` annotiation to only work without braces to be consistent
|
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,16 +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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
316
|
+
typeName_1 = inheritsComponent;
|
|
317
|
+
if (lastTypeFound)
|
|
318
|
+
typeName_1 = lastTypeFound;
|
|
319
|
+
console.log(name_2 + " inherits " + typeName_1);
|
|
320
|
+
newContext.appendLine("public partial class " + name_2 + " : " + typeName_1);
|
|
298
321
|
newContext.appendLine("{");
|
|
299
322
|
newContext.indentLevel += 1;
|
|
300
323
|
newContext.classEnd = dec.end;
|
|
301
324
|
contexts.push(newContext);
|
|
302
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
|
+
}
|
|
303
329
|
lastTypeFound = null;
|
|
304
330
|
break;
|
|
305
331
|
}
|
|
@@ -331,6 +357,36 @@ function run(program, outputDir, sourceFile) {
|
|
|
331
357
|
}
|
|
332
358
|
return false;
|
|
333
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
|
+
}
|
|
334
390
|
function isPublic(node) {
|
|
335
391
|
if (node.kind === ts.SyntaxKind.PublicKeyword) {
|
|
336
392
|
return true;
|
|
@@ -370,8 +426,21 @@ function run(program, outputDir, sourceFile) {
|
|
|
370
426
|
}
|
|
371
427
|
return namespace;
|
|
372
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
|
+
}
|
|
373
443
|
function tryResolveTypeRecursive(node) {
|
|
374
|
-
var _a;
|
|
375
444
|
if (!node)
|
|
376
445
|
return undefined;
|
|
377
446
|
// skip decorators (e.g. @serializable() may break array generation)
|
|
@@ -382,58 +451,111 @@ function run(program, outputDir, sourceFile) {
|
|
|
382
451
|
if (varDec.type) {
|
|
383
452
|
typeName = varDec.type.getText();
|
|
384
453
|
}
|
|
385
|
-
var res =
|
|
386
|
-
if (res !== undefined) {
|
|
387
|
-
// console.log("FOUND " + res, ts.SyntaxKind[node.kind]);
|
|
388
|
-
// console.log(node);
|
|
389
|
-
return res;
|
|
390
|
-
}
|
|
391
|
-
var knownType = tryGetKnownType(typeName);
|
|
392
|
-
if (knownType)
|
|
393
|
-
return knownType;
|
|
454
|
+
var res = undefined;
|
|
394
455
|
// console.log("Unknown type: " + typeName);
|
|
395
456
|
switch (node.kind) {
|
|
396
|
-
case ts.SyntaxKind.SyntaxList:
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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;
|
|
401
463
|
case ts.SyntaxKind.UnionType:
|
|
402
464
|
var union = node;
|
|
403
|
-
for (var _i = 0,
|
|
404
|
-
var t =
|
|
465
|
+
for (var _i = 0, _a = union.types; _i < _a.length; _i++) {
|
|
466
|
+
var t = _a[_i];
|
|
405
467
|
res = tryResolveTypeRecursive(t);
|
|
406
468
|
if (res !== undefined)
|
|
407
469
|
return res;
|
|
408
470
|
}
|
|
409
471
|
break;
|
|
410
472
|
case ts.SyntaxKind.ArrayType:
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
+
res = "[]";
|
|
482
|
+
break;
|
|
483
|
+
default:
|
|
484
|
+
res = tryGetTypeFromText(typeName_2);
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
return res;
|
|
488
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
489
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
490
|
+
case ts.SyntaxKind.StringKeyword:
|
|
491
|
+
case ts.SyntaxKind.ObjectKeyword:
|
|
492
|
+
var keyword = node.getText();
|
|
493
|
+
// the basic keywords are declared in the static dictionary
|
|
494
|
+
// no need for a complex lookup
|
|
495
|
+
res = dict[keyword];
|
|
496
|
+
break;
|
|
497
|
+
case ts.SyntaxKind.Identifier:
|
|
498
|
+
var id = node;
|
|
499
|
+
switch (id.text) {
|
|
500
|
+
// if we have an array we dont want to use the System.Array as a type but just make it to the array syntax
|
|
501
|
+
case "Array":
|
|
502
|
+
res = "[]";
|
|
503
|
+
break;
|
|
504
|
+
default:
|
|
505
|
+
// res = tryGetTypeFromText(id.text);
|
|
506
|
+
break;
|
|
419
507
|
}
|
|
420
|
-
}
|
|
421
|
-
for (var _c = 0, _d = node.getChildren(); _c < _d.length; _c++) {
|
|
422
|
-
var child = _d[_c];
|
|
423
|
-
if (res !== undefined)
|
|
424
508
|
break;
|
|
425
|
-
console.log("Child type: " + ts.SyntaxKind[child.kind]);
|
|
426
|
-
res = tryResolveTypeRecursive(child);
|
|
427
509
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
var
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
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;
|
|
435
548
|
}
|
|
436
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
|
+
// }
|
|
437
559
|
return res;
|
|
438
560
|
}
|
|
439
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");
|
|
@@ -312,8 +333,9 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
312
333
|
newContext.appendLine("{");
|
|
313
334
|
newContext.indentLevel += 1;
|
|
314
335
|
// newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
|
|
315
|
-
let typeName =
|
|
336
|
+
let typeName = "UnityEngine.MonoBehaviour";
|
|
316
337
|
if (typeof inheritsComponent === "string") typeName = inheritsComponent;
|
|
338
|
+
if (lastTypeFound) typeName = lastTypeFound;
|
|
317
339
|
console.log(name + " inherits " + typeName);
|
|
318
340
|
newContext.appendLine("public partial class " + name + " : " + typeName);
|
|
319
341
|
newContext.appendLine("{");
|
|
@@ -321,6 +343,9 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
321
343
|
newContext.classEnd = dec.end;
|
|
322
344
|
contexts.push(newContext);
|
|
323
345
|
}
|
|
346
|
+
else {
|
|
347
|
+
console.log("Class type is unknown and will not generate a component: ", dec.name?.escapedText);
|
|
348
|
+
}
|
|
324
349
|
lastTypeFound = null;
|
|
325
350
|
break;
|
|
326
351
|
}
|
|
@@ -348,6 +373,35 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
348
373
|
return false;
|
|
349
374
|
}
|
|
350
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
|
+
|
|
351
405
|
function isPublic(node: ts.Node): boolean {
|
|
352
406
|
if (node.kind === ts.SyntaxKind.PublicKeyword) {
|
|
353
407
|
return true;
|
|
@@ -386,6 +440,21 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
386
440
|
return namespace;
|
|
387
441
|
}
|
|
388
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
|
+
|
|
389
458
|
function tryResolveTypeRecursive(node: ts.Node | ts.VariableDeclaration): string | undefined {
|
|
390
459
|
if (!node) return undefined;
|
|
391
460
|
|
|
@@ -400,23 +469,19 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
400
469
|
typeName = varDec.type.getText();
|
|
401
470
|
}
|
|
402
471
|
|
|
403
|
-
let res =
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return res;
|
|
408
|
-
}
|
|
409
|
-
const knownType = tryGetKnownType(typeName);
|
|
410
|
-
if (knownType)
|
|
411
|
-
return knownType;
|
|
472
|
+
let res: string | undefined = undefined;
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
412
476
|
// console.log("Unknown type: " + typeName);
|
|
413
477
|
|
|
414
478
|
switch (node.kind) {
|
|
415
|
-
case ts.SyntaxKind.SyntaxList:
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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;
|
|
420
485
|
case ts.SyntaxKind.UnionType:
|
|
421
486
|
const union = node as ts.UnionTypeNode;
|
|
422
487
|
for (const t of union.types) {
|
|
@@ -425,32 +490,96 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
|
|
|
425
490
|
}
|
|
426
491
|
break;
|
|
427
492
|
case ts.SyntaxKind.ArrayType:
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
493
|
+
res = "[]";
|
|
494
|
+
break;
|
|
495
|
+
|
|
496
|
+
case ts.SyntaxKind.TypeReference:
|
|
497
|
+
const typeRef = node as ts.TypeReferenceNode;
|
|
498
|
+
const typeName = typeRef.typeName.getText();
|
|
499
|
+
console.log("TypeReference:", typeName);
|
|
500
|
+
switch (typeName) {
|
|
501
|
+
case "Array":
|
|
502
|
+
res = "[]";
|
|
503
|
+
break;
|
|
504
|
+
default:
|
|
505
|
+
res = tryGetTypeFromText(typeName);
|
|
506
|
+
break;
|
|
436
507
|
}
|
|
437
|
-
|
|
508
|
+
return res;
|
|
509
|
+
|
|
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;
|
|
438
519
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
+
// res = tryGetTypeFromText(id.text);
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
break;
|
|
443
532
|
}
|
|
444
533
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
534
|
+
let isInGenericDeclaration = false;
|
|
535
|
+
for (const child of node.getChildren()) {
|
|
536
|
+
// if (res !== undefined) break;
|
|
537
|
+
// console.log("Child type: " + ts.SyntaxKind[child.kind]);
|
|
538
|
+
let isGenericStart = false;
|
|
539
|
+
let isAssignment = false;
|
|
540
|
+
switch (child.kind) {
|
|
541
|
+
case ts.SyntaxKind.FirstAssignment:
|
|
542
|
+
isAssignment = true;
|
|
543
|
+
break;
|
|
544
|
+
case ts.SyntaxKind.FirstBinaryOperator:
|
|
545
|
+
// console.log("Generic start: " + child.getText());
|
|
546
|
+
isInGenericDeclaration = true;
|
|
547
|
+
isGenericStart = true;
|
|
548
|
+
break;
|
|
549
|
+
case ts.SyntaxKind.GreaterThanGreaterThanToken:
|
|
550
|
+
isInGenericDeclaration = false;
|
|
551
|
+
// console.log("Generic end: " + child.getText());
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
// if (isAssignment) break;
|
|
555
|
+
const childResult = tryResolveTypeRecursive(child);
|
|
556
|
+
if (childResult !== undefined) {
|
|
557
|
+
if (res === undefined) res = "";
|
|
558
|
+
console.log("Child: " + ts.SyntaxKind[child.kind] + " → " + childResult);
|
|
559
|
+
// if the thing is a generic return as generic result
|
|
560
|
+
if (isInGenericDeclaration && !res.includes("[]")) {
|
|
561
|
+
res = "<" + childResult + ">";
|
|
562
|
+
}
|
|
563
|
+
// we got a generic result, these need to be appended
|
|
564
|
+
else if (childResult.startsWith("<")) {
|
|
565
|
+
res += childResult;
|
|
566
|
+
}
|
|
567
|
+
// concat default
|
|
568
|
+
else
|
|
569
|
+
res = childResult + res;
|
|
452
570
|
}
|
|
453
571
|
}
|
|
572
|
+
|
|
573
|
+
// if (ts.isTypeReferenceNode(node)) {
|
|
574
|
+
// const typeRef = node as ts.TypeReferenceNode;
|
|
575
|
+
// const typeName = typeRef.typeName.getText();
|
|
576
|
+
// switch (typeName) {
|
|
577
|
+
// case "Array":
|
|
578
|
+
// res += "[]";
|
|
579
|
+
// return res;
|
|
580
|
+
// }
|
|
581
|
+
// }
|
|
582
|
+
|
|
454
583
|
return res;
|
|
455
584
|
}
|
|
456
585
|
}
|
package/src/test.ts
CHANGED
|
@@ -1,14 +1,40 @@
|
|
|
1
|
+
import { ThisExpression } from "typescript";
|
|
2
|
+
|
|
3
|
+
class Test123 {}
|
|
4
|
+
|
|
5
|
+
export class Bla extends Behaviour
|
|
6
|
+
{
|
|
7
|
+
myNumber:number = 42;
|
|
8
|
+
myBool:boolean = true;
|
|
9
|
+
myString:string = "test";
|
|
10
|
+
numberArr: number[] = [1,2,3];
|
|
11
|
+
myColor : THREE.Color = new THREE.Color(255, 0, 0);
|
|
12
|
+
renderers = new Array<Renderer>();
|
|
13
|
+
renderers2 : Renderer[] = [];
|
|
14
|
+
objArr : object[];
|
|
15
|
+
colArr: THREE.Color[] = [new THREE.Color(1,2,3)];
|
|
16
|
+
map : Map<string> = new Map<string>();
|
|
17
|
+
map2 : Map<object> = new Map<object>();
|
|
18
|
+
private myThing : Test123;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// //@type UnityEngine.MonoBehaviour
|
|
22
|
+
// export class ButtonObject extends Interactable implements IPointerClickHandler, ISerializable {
|
|
23
|
+
|
|
24
|
+
// //@type UnityEngine.Transform[]
|
|
25
|
+
// myType?: SceneFXWindow;
|
|
26
|
+
// }
|
|
1
27
|
|
|
2
28
|
// import { Behaviour } from "needle.tiny.engine/engine-components/Component";
|
|
3
29
|
// import { RoomEntity } from "./Room";
|
|
4
30
|
|
|
5
|
-
import { Behaviour } from "needle.tiny.engine/engine-components/Component";
|
|
31
|
+
// import { Behaviour } from "needle.tiny.engine/engine-components/Component";
|
|
6
32
|
|
|
7
|
-
export class MyNewScript extends DriveClient
|
|
8
|
-
{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
33
|
+
// export class MyNewScript extends DriveClient
|
|
34
|
+
// {
|
|
35
|
+
// //@type test
|
|
36
|
+
// texture : RenderTexture;
|
|
37
|
+
// }
|
|
12
38
|
|
|
13
39
|
// namespace Hello.World
|
|
14
40
|
// {
|
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",
|