@needle-tools/needle-component-compiler 1.0.1 → 1.2.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 CHANGED
@@ -4,6 +4,15 @@ 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.2.1] - 2022-06-15
8
+ - allow adding ``@type(MyNamespace.MyType)`` to class declaration
9
+
10
+ ## [1.1.0] - 2022-06-13
11
+ - add ``@type(MyNamespace.MyType)`` decorator for fields to specifiy C# type
12
+ - add minimal docs to readme
13
+ - dont emit comments anymore
14
+ - make created classes partial
15
+
7
16
  ## [1.0.1] - 2022-05-29
8
17
  - disable all warnings for generated scripts
9
18
  - add mesh and texture types
package/Readme.md CHANGED
@@ -4,4 +4,11 @@ Little helper package to transpile typescript files to Unity C# components.
4
4
  Please run ``npm install`` first before using.
5
5
 
6
6
  ### Usage
7
- ``node <path to>/component-compiler.js <output_directory> <path_to/my_script.ts>``
7
+ ``node <path to>/component-compiler.js <output_directory> <path_to/my_script.ts>``
8
+
9
+
10
+ ### Command decorators
11
+ - ``@dont-generate-component`` add before class to skip generating a component
12
+ - ``@generate-component`` to enforce generating a component (not required)
13
+ - ``@serializeField`` field decorator, similar to ``[SerializeField]``
14
+ - ``@type(MyNamespace.MyType)`` field decorator, specifiy C# type of field
@@ -0,0 +1,13 @@
1
+ // auto generated code - do not edit directly
2
+
3
+ #pragma warning disable
4
+
5
+ namespace Needle.Typescript.GeneratedComponents
6
+ {
7
+ public partial class NavComponent : UnityEngine.MonoBehaviour
8
+ {
9
+ public void next(){}
10
+ public void prev(){}
11
+ public void isAtEnd(){}
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ // auto generated code - do not edit directly
2
+
3
+ #pragma warning disable
4
+
5
+ namespace Needle.Typescript.GeneratedComponents
6
+ {
7
+ public partial class NavigationManager : RoomEntity
8
+ {
9
+ public float @fl = 1f;
10
+ public void nav_forward(){}
11
+ public void nav_backward(){}
12
+ }
13
+ }
@@ -0,0 +1,14 @@
1
+ // auto generated code - do not edit directly
2
+
3
+ #pragma warning disable
4
+
5
+ namespace Needle.Typescript.GeneratedComponents
6
+ {
7
+ public partial class PointOfInterest : UnityEngine.MonoBehaviour
8
+ {
9
+ public float @myVal = 12f;
10
+ public void myFunction(){}
11
+ public UnityEngine.Camera @view;
12
+ public string @test = "123";
13
+ }
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/needle-component-compiler",
3
- "version": "1.0.1",
3
+ "version": "1.2.1",
4
4
  "description": "Compile mock unity components from typescript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,6 +11,7 @@ var exportNextClassCommand = "@generate-component";
11
11
  var dontExportNextClassCommand = "@dont-generate-component";
12
12
  // add above field to add [SerializeField] attribute
13
13
  var serializeCommand = "@serializeField";
14
+ var typePattern = new RegExp("@type ?\((?<type>.+)\)");
14
15
  // will be set to true when e.g. a comment for export is found
15
16
  var exportNextClass = false;
16
17
  var dontExportNextClass = false;
@@ -65,6 +66,7 @@ var ExportContext = /** @class */ (function () {
65
66
  return ExportContext;
66
67
  }());
67
68
  var contexts = [];
69
+ var lastTypeFound = null;
68
70
  function run(program, outputDir, sourceFile) {
69
71
  if (!fs.existsSync(outputDir)) {
70
72
  console.error("Output directory does not exist: \"" + outputDir + "\"");
@@ -76,16 +78,18 @@ function run(program, outputDir, sourceFile) {
76
78
  ts.forEachChild(node, traverseFile);
77
79
  }
78
80
  function visit(node) {
79
- var _a, _b, _c;
81
+ var _a, _b, _c, _d;
80
82
  var context = contexts.length > 0 ? contexts[contexts.length - 1] : null;
81
- if ((context === null || context === void 0 ? void 0 : context.classEnd) > 0 && node.pos >= (context === null || context === void 0 ? void 0 : context.classEnd)) {
82
- while (context.indentLevel > 0) {
83
- context.indentLevel -= 1;
84
- context.append("}\n");
83
+ if (context) {
84
+ if ((context === null || context === void 0 ? void 0 : context.classEnd) > 0 && node.pos >= (context === null || context === void 0 ? void 0 : context.classEnd)) {
85
+ while (context.indentLevel > 0) {
86
+ context.indentLevel -= 1;
87
+ context.append("}\n");
88
+ }
89
+ context.flush();
90
+ context = null;
91
+ contexts.pop();
85
92
  }
86
- context.flush();
87
- context = null;
88
- contexts.pop();
89
93
  }
90
94
  console.log("\t", ts.SyntaxKind[node.kind]);
91
95
  var commentRanges = ts.getLeadingCommentRanges(sourceFile.getFullText(), node.getFullStart());
@@ -105,13 +109,20 @@ function run(program, outputDir, sourceFile) {
105
109
  }
106
110
  else if (comment.includes(serializeCommand))
107
111
  serializeField = true;
108
- else
109
- context.appendLine(comment);
110
112
  }
111
113
  if (comment.includes(exportNextClassCommand))
112
114
  exportNextClass = true;
113
115
  if (comment.includes(dontExportNextClassCommand))
114
116
  dontExportNextClass = true;
117
+ var match = typePattern.exec(comment);
118
+ if (match && match.groups) {
119
+ // for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
120
+ // so we remove them
121
+ var type = match.groups["type"];
122
+ type = type.replace(/\(/, "").replace(/\)/, "");
123
+ console.log("found type: ", type);
124
+ lastTypeFound = type;
125
+ }
115
126
  }
116
127
  }
117
128
  switch (node.kind) {
@@ -122,6 +133,7 @@ function run(program, outputDir, sourceFile) {
122
133
  case ts.SyntaxKind.Decorator:
123
134
  break;
124
135
  case ts.SyntaxKind.MethodDeclaration:
136
+ lastTypeFound = null;
125
137
  serializeField = false;
126
138
  resetExportNextClass();
127
139
  if (!context)
@@ -131,8 +143,8 @@ function run(program, outputDir, sourceFile) {
131
143
  // const isCoroutine = func.asteriskToken;
132
144
  if (meth.name) {
133
145
  var paramsStr = "";
134
- for (var _d = 0, _e = meth.parameters; _d < _e.length; _d++) {
135
- var param = _e[_d];
146
+ for (var _e = 0, _f = meth.parameters; _e < _f.length; _e++) {
147
+ var param = _f[_e];
136
148
  if (!param || !param.name)
137
149
  continue;
138
150
  if (paramsStr.length > 0)
@@ -158,15 +170,15 @@ function run(program, outputDir, sourceFile) {
158
170
  console.log(name_1);
159
171
  if (name_1.startsWith("\"@") || name_1.startsWith("\"$") || name_1.startsWith("$"))
160
172
  break;
161
- var typeString = tryResolveTypeRecursive(node);
173
+ var typeString = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : tryResolveTypeRecursive(node);
162
174
  if (typeString === undefined) {
163
175
  context.append("// Could not resolve type \"" + ((_c = vardec.type) === null || _c === void 0 ? void 0 : _c.getText()) + "\"\n");
164
176
  }
165
177
  var prefix = typeString === undefined ? "// " : "";
166
178
  var assignment = "";
167
179
  if (typeString !== undefined) {
168
- for (var _f = 0, _g = node.getChildren(); _f < _g.length; _f++) {
169
- var ch = _g[_f];
180
+ for (var _g = 0, _h = node.getChildren(); _g < _h.length; _g++) {
181
+ var ch = _h[_g];
170
182
  switch (ch.kind) {
171
183
  case ts.SyntaxKind.FalseKeyword:
172
184
  case ts.SyntaxKind.TrueKeyword:
@@ -197,17 +209,18 @@ function run(program, outputDir, sourceFile) {
197
209
  context.appendLine("[UnityEngine.SerializeField]");
198
210
  }
199
211
  context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";\n");
212
+ lastTypeFound = null;
200
213
  break;
201
214
  case ts.SyntaxKind.ClassDeclaration:
202
215
  serializeField = false;
203
216
  var dec = node;
204
217
  // a class must inherit a component
205
- if (!dontExportNextClass && (exportNextClass || testInheritsComponent(node))) {
218
+ if (!dontExportNextClass && (lastTypeFound || exportNextClass || testInheritsComponent(node))) {
206
219
  resetExportNextClass();
207
- var name_2 = dec.name.escapedText;
220
+ var name_2 = (_d = dec.name) === null || _d === void 0 ? void 0 : _d.escapedText;
208
221
  console.log("Found class: ", name_2);
209
222
  var newContext = new ExportContext(outputDir, name_2 + ".cs");
210
- newContext.appendLine("// auto generated code - do not edit");
223
+ newContext.appendLine("// auto generated code - do not edit directly");
211
224
  newContext.appendLine("");
212
225
  newContext.appendLine("#pragma warning disable");
213
226
  newContext.appendLine("");
@@ -215,12 +228,15 @@ function run(program, outputDir, sourceFile) {
215
228
  newContext.appendLine("{");
216
229
  newContext.indentLevel += 1;
217
230
  // newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
218
- newContext.appendLine("public class " + name_2 + " : UnityEngine.MonoBehaviour");
231
+ var typeName = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : "UnityEngine.MonoBehaviour";
232
+ console.log(name_2 + " inherits " + typeName);
233
+ newContext.appendLine("public partial class " + name_2 + " : " + typeName);
219
234
  newContext.appendLine("{");
220
235
  newContext.indentLevel += 1;
221
236
  newContext.classEnd = dec.end;
222
237
  contexts.push(newContext);
223
238
  }
239
+ lastTypeFound = null;
224
240
  break;
225
241
  }
226
242
  function testInheritsComponent(node) {
@@ -11,6 +11,7 @@ const exportNextClassCommand = "@generate-component";
11
11
  const dontExportNextClassCommand = "@dont-generate-component";
12
12
  // add above field to add [SerializeField] attribute
13
13
  const serializeCommand = "@serializeField";
14
+ const typePattern = new RegExp("@type ?\((?<type>.+)\)");
14
15
 
15
16
  // will be set to true when e.g. a comment for export is found
16
17
  let exportNextClass: boolean = false;
@@ -80,6 +81,8 @@ class ExportContext {
80
81
 
81
82
  const contexts: ExportContext[] = [];
82
83
 
84
+ let lastTypeFound: string | null = null;
85
+
83
86
  export function run(program: ts.Program, outputDir: string, sourceFile: ts.SourceFile) {
84
87
 
85
88
  if (!fs.existsSync(outputDir)) {
@@ -97,14 +100,16 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
97
100
  function visit(node: ts.Node) {
98
101
  let context: ExportContext | null = contexts.length > 0 ? contexts[contexts.length - 1] : null;
99
102
 
100
- if (context?.classEnd > 0 && node.pos >= context?.classEnd) {
101
- while (context.indentLevel > 0) {
102
- context.indentLevel -= 1;
103
- context.append("}\n");
103
+ if (context) {
104
+ if (context?.classEnd > 0 && node.pos >= context?.classEnd) {
105
+ while (context.indentLevel > 0) {
106
+ context.indentLevel -= 1;
107
+ context.append("}\n");
108
+ }
109
+ context.flush();
110
+ context = null;
111
+ contexts.pop();
104
112
  }
105
- context.flush();
106
- context = null;
107
- contexts.pop();
108
113
  }
109
114
  console.log("\t", ts.SyntaxKind[node.kind]);
110
115
 
@@ -125,13 +130,20 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
125
130
  }
126
131
  else if (comment.includes(serializeCommand))
127
132
  serializeField = true;
128
- else
129
- context.appendLine(comment);
130
133
  }
131
134
  if (comment.includes(exportNextClassCommand))
132
135
  exportNextClass = true;
133
136
  if (comment.includes(dontExportNextClassCommand))
134
137
  dontExportNextClass = true;
138
+ const match = typePattern.exec(comment);
139
+ if (match && match.groups) {
140
+ // for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
141
+ // so we remove them
142
+ let type = match.groups["type"];
143
+ type = type.replace(/\(/, "").replace(/\)/, "");
144
+ console.log("found type: ", type);
145
+ lastTypeFound = type;
146
+ }
135
147
  }
136
148
  }
137
149
 
@@ -143,6 +155,7 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
143
155
  case ts.SyntaxKind.Decorator:
144
156
  break;
145
157
  case ts.SyntaxKind.MethodDeclaration:
158
+ lastTypeFound = null;
146
159
  serializeField = false;
147
160
  resetExportNextClass();
148
161
  if (!context) break;
@@ -174,7 +187,7 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
174
187
  const name = vardec.name.getText();
175
188
  console.log(name);
176
189
  if (name.startsWith("\"@") || name.startsWith("\"$") || name.startsWith("$")) break;
177
- let typeString = tryResolveTypeRecursive(node);
190
+ let typeString = lastTypeFound ?? tryResolveTypeRecursive(node);
178
191
  if (typeString === undefined) {
179
192
  context.append("// Could not resolve type \"" + vardec.type?.getText() + "\"\n");
180
193
  }
@@ -212,15 +225,16 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
212
225
  context.appendLine("[UnityEngine.SerializeField]");
213
226
  }
214
227
  context.append(prefix + visibility + " " + typeString + " " + varName + assignment + ";\n");
228
+ lastTypeFound = null;
215
229
  break;
216
230
 
217
231
  case ts.SyntaxKind.ClassDeclaration:
218
232
  serializeField = false;
219
233
  const dec = <ts.ClassDeclaration>node;
220
234
  // a class must inherit a component
221
- if (!dontExportNextClass && (exportNextClass || testInheritsComponent(node))) {
235
+ if (!dontExportNextClass && (lastTypeFound || exportNextClass || testInheritsComponent(node))) {
222
236
  resetExportNextClass();
223
- const name = dec.name.escapedText;
237
+ const name = dec.name?.escapedText;
224
238
  console.log("Found class: ", name);
225
239
  const newContext = new ExportContext(outputDir, name + ".cs");
226
240
  newContext.appendLine("// auto generated code - do not edit directly");
@@ -231,12 +245,15 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
231
245
  newContext.appendLine("{");
232
246
  newContext.indentLevel += 1;
233
247
  // newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
234
- newContext.appendLine("public class " + name + " : UnityEngine.MonoBehaviour");
248
+ const typeName = lastTypeFound ?? "UnityEngine.MonoBehaviour";
249
+ console.log(name + " inherits " + typeName);
250
+ newContext.appendLine("public partial class " + name + " : " + typeName);
235
251
  newContext.appendLine("{");
236
252
  newContext.indentLevel += 1;
237
253
  newContext.classEnd = dec.end;
238
254
  contexts.push(newContext);
239
255
  }
256
+ lastTypeFound = null;
240
257
  break;
241
258
  }
242
259
 
@@ -278,7 +295,7 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
278
295
  if (!node) return undefined;
279
296
 
280
297
  // skip decorators (e.g. @serializable() may break array generation)
281
- if(node.kind === ts.SyntaxKind.Decorator)
298
+ if (node.kind === ts.SyntaxKind.Decorator)
282
299
  return undefined;
283
300
 
284
301
  let typeName = node?.getText();
@@ -326,12 +343,11 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
326
343
  console.log("Child type: " + ts.SyntaxKind[child.kind]);
327
344
  res = tryResolveTypeRecursive(child);
328
345
  }
329
-
330
- if(ts.isTypeReferenceNode(node)){
346
+
347
+ if (ts.isTypeReferenceNode(node)) {
331
348
  const typeRef = node as ts.TypeReferenceNode;
332
349
  const typeName = typeRef.typeName.getText();
333
- switch(typeName)
334
- {
350
+ switch (typeName) {
335
351
  case "Array":
336
352
  res += "[]";
337
353
  return res;
package/src/test.ts CHANGED
@@ -1,13 +1,50 @@
1
1
 
2
- // @generate-component
2
+ import { Behaviour } from "needle.tiny.engine/engine-components/Component";
3
+ import { RoomEntity } from "./Room";
3
4
 
5
+ //@type (RoomEntity)
6
+ export class NavigationManager extends RoomEntity {
4
7
 
5
- export class MaterialColorHandler extends Behaviour {
8
+ fl:number = 1;
6
9
 
7
- @serializeable(Renderer)
8
- renderer?: Renderer[];
10
+ nav_forward() {
11
+
12
+ }
13
+
14
+ nav_backward() {
15
+
16
+ }
9
17
  }
10
18
 
19
+ export abstract class NavComponent extends Behaviour {
20
+
21
+ abstract next();
22
+ abstract prev();
23
+ abstract isAtEnd():boolean;
24
+ }
25
+
26
+
27
+ // export class PointOfInterest extends Behaviour {
28
+
29
+ // myVal:number = 12;
30
+
31
+ // // @type(HELLO)
32
+ // myFunction(){
33
+
34
+ // }
35
+
36
+ // // @type(UnityEngine.Camera)
37
+ // view?:Camera;
38
+ // test:string = "123";
39
+ // // test
40
+ // }
41
+
42
+ // export class MaterialColorHandler extends Behaviour {
43
+
44
+ // @serializeable(Renderer)
45
+ // renderer?: Renderer[];
46
+ // }
47
+
11
48
  // export class MyArray extends Behaviour {
12
49
 
13
50
  // arr? : Array<number> = [1,2,3];