@needle-tools/needle-component-compiler 1.1.0 → 1.3.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 CHANGED
@@ -4,6 +4,12 @@ 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.3.0] - 2022-06-27
8
+ - add support for typescript namespace
9
+
10
+ ## [1.2.1] - 2022-06-15
11
+ - allow adding ``@type(MyNamespace.MyType)`` to class declaration
12
+
7
13
  ## [1.1.0] - 2022-06-13
8
14
  - add ``@type(MyNamespace.MyType)`` decorator for fields to specifiy C# type
9
15
  - add minimal docs to readme
package/Readme.md CHANGED
@@ -11,4 +11,4 @@ Please run ``npm install`` first before using.
11
11
  - ``@dont-generate-component`` add before class to skip generating a component
12
12
  - ``@generate-component`` to enforce generating a component (not required)
13
13
  - ``@serializeField`` field decorator, similar to ``[SerializeField]``
14
- - ``@type(MyNamespace.MyType)`` field decorator, specifiy C# type of field
14
+ - ``@type(MyNamespace.MyType)`` decorator for fields or classes, specifiy C# type of field or class
package/dist/MyClass.cs CHANGED
@@ -1,23 +1,10 @@
1
- // auto generated code - do not edit
2
- namespace Needle.Typescript.GeneratedComponents
1
+ // auto generated code - do not edit directly
2
+
3
+ #pragma warning disable
4
+
5
+ namespace Hello.World.Deep
3
6
  {
4
- // source: C:\git\needle-tiny-playground\projects\Compiled_Export\myProject\src\scripts\MyClass.ts
5
- public class MyClass : UnityEngine.MonoBehaviour
7
+ public partial class MyClass : UnityEngine.MonoBehaviour
6
8
  {
7
- public void start(){}
8
- public float myFloat = 15;
9
- public bool myBool;
10
- // just some default values
11
- public float[] myArray = new float[]{ 1, 2, 3 };
12
- // comment for myString
13
- public string myString = "this is a string";
14
- public UnityEngine.Transform myObject;
15
- public bool myBool2;
16
- public void myFunction(){}
17
- public void myFunctionWithStringParameter(string @string){}
18
- public void myFunctionWithSomeObjectAndArray(UnityEngine.Transform @obj, float[] @arr){}
19
- public void myFunctionWithoutParamTypes(object @test){}
20
- public UnityEngine.Transform[] someOtherStuff;
21
- public UnityEngine.Events.UnityEvent myEvent;
22
9
  }
23
10
  }
@@ -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,10 @@
1
+ // auto generated code - do not edit directly
2
+
3
+ #pragma warning disable
4
+
5
+ namespace Needle.Typescript.GeneratedComponents
6
+ {
7
+ public partial class OtherClass : UnityEngine.MonoBehaviour
8
+ {
9
+ }
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/needle-component-compiler",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Compile mock unity components from typescript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,7 +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
+ var typePattern = new RegExp("@type ?\((?<type>.+)\)");
15
15
  // will be set to true when e.g. a comment for export is found
16
16
  var exportNextClass = false;
17
17
  var dontExportNextClass = false;
@@ -78,16 +78,18 @@ function run(program, outputDir, sourceFile) {
78
78
  ts.forEachChild(node, traverseFile);
79
79
  }
80
80
  function visit(node) {
81
- var _a, _b, _c;
81
+ var _a, _b, _c, _d, _e;
82
82
  var context = contexts.length > 0 ? contexts[contexts.length - 1] : null;
83
- if ((context === null || context === void 0 ? void 0 : context.classEnd) > 0 && node.pos >= (context === null || context === void 0 ? void 0 : context.classEnd)) {
84
- while (context.indentLevel > 0) {
85
- context.indentLevel -= 1;
86
- 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();
87
92
  }
88
- context.flush();
89
- context = null;
90
- contexts.pop();
91
93
  }
92
94
  console.log("\t", ts.SyntaxKind[node.kind]);
93
95
  var commentRanges = ts.getLeadingCommentRanges(sourceFile.getFullText(), node.getFullStart());
@@ -107,29 +109,32 @@ function run(program, outputDir, sourceFile) {
107
109
  }
108
110
  else if (comment.includes(serializeCommand))
109
111
  serializeField = true;
110
- else {
111
- console.log(comment);
112
- var match = typePattern.exec(comment);
113
- if (match && match.groups) {
114
- // for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
115
- // so we remove them
116
- var type = match.groups["type"];
117
- if (type.startsWith("("))
118
- type = type.slice(1);
119
- if (type.endsWith(")"))
120
- type = type.slice(0, -1);
121
- console.log("found type: ", type);
122
- lastTypeFound = type;
123
- }
124
- }
125
112
  }
126
113
  if (comment.includes(exportNextClassCommand))
127
114
  exportNextClass = true;
128
115
  if (comment.includes(dontExportNextClassCommand))
129
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
+ }
130
126
  }
131
127
  }
132
128
  switch (node.kind) {
129
+ // Namespace
130
+ // case ts.SyntaxKind.ModuleDeclaration:
131
+ // const mod = node as ts.ModuleDeclaration;
132
+ // console.log(ts.SyntaxKind[mod.getChildAt(1).kind])
133
+ // const type = mod.getChildAt(1) as ts.Identifier;
134
+ // console.log("MODULE", type.text)
135
+ // break;
136
+ // case ts.SyntaxKind.Identifier:
137
+ // break;
133
138
  // case ts.SyntaxKind.ClassDeclaration:
134
139
  // case ts.SyntaxKind.SingleLineCommentTrivia:
135
140
  // console.log("comment: " + node.getText())
@@ -147,8 +152,8 @@ function run(program, outputDir, sourceFile) {
147
152
  // const isCoroutine = func.asteriskToken;
148
153
  if (meth.name) {
149
154
  var paramsStr = "";
150
- for (var _d = 0, _e = meth.parameters; _d < _e.length; _d++) {
151
- var param = _e[_d];
155
+ for (var _f = 0, _g = meth.parameters; _f < _g.length; _f++) {
156
+ var param = _g[_f];
152
157
  if (!param || !param.name)
153
158
  continue;
154
159
  if (paramsStr.length > 0)
@@ -181,8 +186,8 @@ function run(program, outputDir, sourceFile) {
181
186
  var prefix = typeString === undefined ? "// " : "";
182
187
  var assignment = "";
183
188
  if (typeString !== undefined) {
184
- for (var _f = 0, _g = node.getChildren(); _f < _g.length; _f++) {
185
- var ch = _g[_f];
189
+ for (var _h = 0, _j = node.getChildren(); _h < _j.length; _h++) {
190
+ var ch = _j[_h];
186
191
  switch (ch.kind) {
187
192
  case ts.SyntaxKind.FalseKeyword:
188
193
  case ts.SyntaxKind.TrueKeyword:
@@ -217,28 +222,32 @@ function run(program, outputDir, sourceFile) {
217
222
  break;
218
223
  case ts.SyntaxKind.ClassDeclaration:
219
224
  serializeField = false;
220
- lastTypeFound = null;
221
225
  var dec = node;
222
226
  // a class must inherit a component
223
- if (!dontExportNextClass && (exportNextClass || testInheritsComponent(node))) {
227
+ if (!dontExportNextClass && (lastTypeFound || exportNextClass || testInheritsComponent(node))) {
224
228
  resetExportNextClass();
225
- var name_2 = dec.name.escapedText;
229
+ var name_2 = (_d = dec.name) === null || _d === void 0 ? void 0 : _d.escapedText;
226
230
  console.log("Found class: ", name_2);
231
+ var namespace = (_e = tryParseNamespace(node)) !== null && _e !== void 0 ? _e : "Needle.Typescript.GeneratedComponents";
232
+ console.log("NAMESPACE", namespace);
227
233
  var newContext = new ExportContext(outputDir, name_2 + ".cs");
228
234
  newContext.appendLine("// auto generated code - do not edit directly");
229
235
  newContext.appendLine("");
230
236
  newContext.appendLine("#pragma warning disable");
231
237
  newContext.appendLine("");
232
- newContext.appendLine("namespace Needle.Typescript.GeneratedComponents");
238
+ newContext.appendLine("namespace " + namespace);
233
239
  newContext.appendLine("{");
234
240
  newContext.indentLevel += 1;
235
241
  // newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
236
- newContext.appendLine("public partial class " + name_2 + " : UnityEngine.MonoBehaviour");
242
+ var typeName = lastTypeFound !== null && lastTypeFound !== void 0 ? lastTypeFound : "UnityEngine.MonoBehaviour";
243
+ console.log(name_2 + " inherits " + typeName);
244
+ newContext.appendLine("public partial class " + name_2 + " : " + typeName);
237
245
  newContext.appendLine("{");
238
246
  newContext.indentLevel += 1;
239
247
  newContext.classEnd = dec.end;
240
248
  contexts.push(newContext);
241
249
  }
250
+ lastTypeFound = null;
242
251
  break;
243
252
  }
244
253
  function testInheritsComponent(node) {
@@ -279,6 +288,31 @@ function run(program, outputDir, sourceFile) {
279
288
  }
280
289
  return true;
281
290
  }
291
+ function tryParseNamespace(node, namespace) {
292
+ // console.log("TRAVERSE - " + ts.SyntaxKind[node.kind]);
293
+ switch (node.kind) {
294
+ case ts.SyntaxKind.ModuleDeclaration:
295
+ for (var _i = 0, _a = node.getChildren(); _i < _a.length; _i++) {
296
+ var ch = _a[_i];
297
+ // console.log("-- TRAVERSE - " + ts.SyntaxKind[ch.kind]);
298
+ switch (ch.kind) {
299
+ case ts.SyntaxKind.Identifier:
300
+ var id = ch;
301
+ if (id.text) {
302
+ if (!namespace)
303
+ namespace = "";
304
+ namespace = id.text + (namespace ? "." : "") + namespace;
305
+ }
306
+ break;
307
+ }
308
+ }
309
+ break;
310
+ }
311
+ if (node.parent) {
312
+ return tryParseNamespace(node.parent, namespace);
313
+ }
314
+ return namespace;
315
+ }
282
316
  function tryResolveTypeRecursive(node) {
283
317
  var _a;
284
318
  if (!node)
@@ -4,6 +4,7 @@ import * as fs from "fs";
4
4
  import * as path from "path";
5
5
 
6
6
  import * as types from "./types";
7
+ import { traceDeprecation } from "process";
7
8
  const dict = types.dict;
8
9
 
9
10
  // add either of these two comments above a class to enforce code gen or disable it for the next class
@@ -11,7 +12,7 @@ const exportNextClassCommand = "@generate-component";
11
12
  const dontExportNextClassCommand = "@dont-generate-component";
12
13
  // add above field to add [SerializeField] attribute
13
14
  const serializeCommand = "@serializeField";
14
- const typePattern = new RegExp("@type\((?<type>.+)\)");
15
+ const typePattern = new RegExp("@type ?\((?<type>.+)\)");
15
16
 
16
17
  // will be set to true when e.g. a comment for export is found
17
18
  let exportNextClass: boolean = false;
@@ -81,7 +82,7 @@ class ExportContext {
81
82
 
82
83
  const contexts: ExportContext[] = [];
83
84
 
84
- let lastTypeFound : string | null = null;
85
+ let lastTypeFound: string | null = null;
85
86
 
86
87
  export function run(program: ts.Program, outputDir: string, sourceFile: ts.SourceFile) {
87
88
 
@@ -100,14 +101,16 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
100
101
  function visit(node: ts.Node) {
101
102
  let context: ExportContext | null = contexts.length > 0 ? contexts[contexts.length - 1] : null;
102
103
 
103
- if (context?.classEnd > 0 && node.pos >= context?.classEnd) {
104
- while (context.indentLevel > 0) {
105
- context.indentLevel -= 1;
106
- context.append("}\n");
104
+ if (context) {
105
+ if (context?.classEnd > 0 && node.pos >= context?.classEnd) {
106
+ while (context.indentLevel > 0) {
107
+ context.indentLevel -= 1;
108
+ context.append("}\n");
109
+ }
110
+ context.flush();
111
+ context = null;
112
+ contexts.pop();
107
113
  }
108
- context.flush();
109
- context = null;
110
- contexts.pop();
111
114
  }
112
115
  console.log("\t", ts.SyntaxKind[node.kind]);
113
116
 
@@ -128,28 +131,33 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
128
131
  }
129
132
  else if (comment.includes(serializeCommand))
130
133
  serializeField = true;
131
- else {
132
- console.log(comment);
133
- const match = typePattern.exec(comment);
134
- if(match && match.groups){
135
- // for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
136
- // so we remove them
137
- let type = match.groups["type"];
138
- if(type.startsWith("(")) type = type.slice(1);
139
- if(type.endsWith(")")) type = type.slice(0, -1);
140
- console.log("found type: ", type);
141
- lastTypeFound = type;
142
- }
143
- }
144
134
  }
145
135
  if (comment.includes(exportNextClassCommand))
146
136
  exportNextClass = true;
147
137
  if (comment.includes(dontExportNextClassCommand))
148
138
  dontExportNextClass = true;
139
+ const match = typePattern.exec(comment);
140
+ if (match && match.groups) {
141
+ // for some reason our regex does also match surrounding ( ) even tho: https://regex101.com/r/PoWK6V/1
142
+ // so we remove them
143
+ let type = match.groups["type"];
144
+ type = type.replace(/\(/, "").replace(/\)/, "");
145
+ console.log("found type: ", type);
146
+ lastTypeFound = type;
147
+ }
149
148
  }
150
149
  }
151
150
 
152
151
  switch (node.kind) {
152
+ // Namespace
153
+ // case ts.SyntaxKind.ModuleDeclaration:
154
+ // const mod = node as ts.ModuleDeclaration;
155
+ // console.log(ts.SyntaxKind[mod.getChildAt(1).kind])
156
+ // const type = mod.getChildAt(1) as ts.Identifier;
157
+ // console.log("MODULE", type.text)
158
+ // break;
159
+ // case ts.SyntaxKind.Identifier:
160
+ // break;
153
161
  // case ts.SyntaxKind.ClassDeclaration:
154
162
  // case ts.SyntaxKind.SingleLineCommentTrivia:
155
163
  // console.log("comment: " + node.getText())
@@ -232,28 +240,32 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
232
240
 
233
241
  case ts.SyntaxKind.ClassDeclaration:
234
242
  serializeField = false;
235
- lastTypeFound = null;
236
243
  const dec = <ts.ClassDeclaration>node;
237
244
  // a class must inherit a component
238
- if (!dontExportNextClass && (exportNextClass || testInheritsComponent(node))) {
245
+ if (!dontExportNextClass && (lastTypeFound || exportNextClass || testInheritsComponent(node))) {
239
246
  resetExportNextClass();
240
- const name = dec.name.escapedText;
247
+ const name = dec.name?.escapedText;
241
248
  console.log("Found class: ", name);
249
+ const namespace = tryParseNamespace(node) ?? "Needle.Typescript.GeneratedComponents";
250
+ console.log("NAMESPACE", namespace);
242
251
  const newContext = new ExportContext(outputDir, name + ".cs");
243
252
  newContext.appendLine("// auto generated code - do not edit directly");
244
253
  newContext.appendLine("");
245
254
  newContext.appendLine("#pragma warning disable");
246
255
  newContext.appendLine("");
247
- newContext.appendLine("namespace Needle.Typescript.GeneratedComponents");
256
+ newContext.appendLine("namespace " + namespace);
248
257
  newContext.appendLine("{");
249
258
  newContext.indentLevel += 1;
250
259
  // newContext.appendLine("// source: " + path.resolve(sourceFile.fileName));
251
- newContext.appendLine("public partial class " + name + " : UnityEngine.MonoBehaviour");
260
+ const typeName = lastTypeFound ?? "UnityEngine.MonoBehaviour";
261
+ console.log(name + " inherits " + typeName);
262
+ newContext.appendLine("public partial class " + name + " : " + typeName);
252
263
  newContext.appendLine("{");
253
264
  newContext.indentLevel += 1;
254
265
  newContext.classEnd = dec.end;
255
266
  contexts.push(newContext);
256
267
  }
268
+ lastTypeFound = null;
257
269
  break;
258
270
  }
259
271
 
@@ -291,6 +303,30 @@ export function run(program: ts.Program, outputDir: string, sourceFile: ts.Sourc
291
303
  return true;
292
304
  }
293
305
 
306
+ function tryParseNamespace(node: ts.Node, namespace?: string): string | null | undefined {
307
+ // console.log("TRAVERSE - " + ts.SyntaxKind[node.kind]);
308
+ switch (node.kind) {
309
+ case ts.SyntaxKind.ModuleDeclaration:
310
+ for (const ch of node.getChildren()) {
311
+ // console.log("-- TRAVERSE - " + ts.SyntaxKind[ch.kind]);
312
+ switch (ch.kind) {
313
+ case ts.SyntaxKind.Identifier:
314
+ const id = ch as ts.Identifier;
315
+ if (id.text) {
316
+ if(!namespace) namespace = "";
317
+ namespace = id.text + (namespace ? "." : "") + namespace;
318
+ }
319
+ break;
320
+ }
321
+ }
322
+ break;
323
+ }
324
+ if (node.parent) {
325
+ return tryParseNamespace(node.parent, namespace);
326
+ }
327
+ return namespace;
328
+ }
329
+
294
330
  function tryResolveTypeRecursive(node: ts.Node | ts.VariableDeclaration): string | undefined {
295
331
  if (!node) return undefined;
296
332
 
package/src/test.ts CHANGED
@@ -1,22 +1,58 @@
1
1
 
2
- // @generate-component
2
+ // import { Behaviour } from "needle.tiny.engine/engine-components/Component";
3
+ // import { RoomEntity } from "./Room";
3
4
 
4
5
 
5
- export class PointOfInterest extends Behaviour {
6
-
7
- myVal:number = 12;
6
+ namespace Hello.World
7
+ {
8
+ namespace Deep {
9
+ export class MyClass extends Behaviour {
8
10
 
9
- // @type(HELLO)
10
- myFunction(){
11
-
11
+ }
12
12
  }
13
+ }
14
+
15
+ class OtherClass extends Behaviour {
13
16
 
14
- // @type(UnityEngine.Camera)
15
- view?:Camera;
16
- test:string = "123";
17
- // test
18
17
  }
19
18
 
19
+ //@type (RoomEntity)
20
+ // export class NavigationManager extends RoomEntity {
21
+
22
+ // fl:number = 1;
23
+
24
+ // nav_forward() {
25
+
26
+ // }
27
+
28
+ // nav_backward() {
29
+
30
+ // }
31
+ // }
32
+
33
+ // export abstract class NavComponent extends Behaviour {
34
+
35
+ // abstract next();
36
+ // abstract prev();
37
+ // abstract isAtEnd():boolean;
38
+ // }
39
+
40
+
41
+ // export class PointOfInterest extends Behaviour {
42
+
43
+ // myVal:number = 12;
44
+
45
+ // // @type(HELLO)
46
+ // myFunction(){
47
+
48
+ // }
49
+
50
+ // // @type(UnityEngine.Camera)
51
+ // view?:Camera;
52
+ // test:string = "123";
53
+ // // test
54
+ // }
55
+
20
56
  // export class MaterialColorHandler extends Behaviour {
21
57
 
22
58
  // @serializeable(Renderer)