@runtime-type-inspector/transpiler 2.0.4

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.
Files changed (4) hide show
  1. package/README.md +3 -0
  2. package/index.cjs +2620 -0
  3. package/index.mjs +2236 -0
  4. package/package.json +26 -0
package/index.mjs ADDED
@@ -0,0 +1,2236 @@
1
+ import { parse } from '@babel/parser';
2
+ import ts$1 from 'typescript';
3
+
4
+ function expandTypeDepFree(type) {
5
+ type = type.trim();
6
+ while (!type.includes('|') && type[0] == '(' && type[type.length - 1] == ')') {
7
+ type = type.slice(1, -1).trim();
8
+ }
9
+ if (type[0] === '.' && type[1] === '.' && type[2] === '.') {
10
+ return {
11
+ type: 'array',
12
+ elementType: type.slice(3)
13
+ };
14
+ }
15
+ if (type.startsWith("Array<") && type.endsWith('>')) {
16
+ const typeSlice = type.slice(6, -1);
17
+ return {
18
+ type: "array",
19
+ elementType: expandTypeDepFree(typeSlice)
20
+ };
21
+ }
22
+ if ((type.startsWith("Object<") || type.startsWith("Record<")) && type.endsWith('>')) {
23
+ const recordSlice = type.slice(7, -1);
24
+ const firstComma = recordSlice.indexOf(',');
25
+ if (firstComma === -1) {
26
+ console.warn("expandTypeDepFree> invalid Object/Record");
27
+ }
28
+ const key = recordSlice.slice(0, firstComma).trim();
29
+ const val = recordSlice.slice(firstComma + 1).trim();
30
+ return {
31
+ type: "record",
32
+ key: expandTypeDepFree(key),
33
+ val: expandTypeDepFree(val)
34
+ };
35
+ }
36
+ if (type[0] == '{' && type[type.length - 1] == '}') {
37
+ const propertiesArray = type.slice(1, -1).split(',');
38
+ const properties = {};
39
+ propertiesArray.forEach(_ => {
40
+ const [propName, propType] = _.split(":").map(_ => _.trim());
41
+ if (!propName || !propType) {
42
+ console.warn('expandTypeDepFree> unexpected type format, fix');
43
+ return false;
44
+ }
45
+ properties[propName] = propType;
46
+ });
47
+ return {
48
+ type: 'object',
49
+ properties
50
+ };
51
+ }
52
+ const members = type.split("|");
53
+ if (members.length >= 2) {
54
+ members.forEach((_, i) => members[i] = _.trim());
55
+ return {
56
+ type: 'union',
57
+ members: members.map(expandTypeDepFree)
58
+ };
59
+ }
60
+ if (type.endsWith("[]")) {
61
+ const typeSlice = type.slice(0, -2);
62
+ return {
63
+ type: 'array',
64
+ elementType: expandTypeDepFree(typeSlice)
65
+ };
66
+ }
67
+ if (type[0] == '[' && type[type.length - 1] == ']') {
68
+ const elements = type.slice(1, -1).split(',');
69
+ return {
70
+ type: 'tuple',
71
+ elements: elements.map(expandTypeDepFree)
72
+ };
73
+ }
74
+ if (type === 'object' || type === 'Object') {
75
+ return {
76
+ type: 'object',
77
+ properties: {}
78
+ };
79
+ }
80
+ return type;
81
+ }
82
+
83
+ function nodeIsFunction(node) {
84
+ switch (node.type) {
85
+ case 'ArrowFunctionExpression':
86
+ case 'ClassMethod':
87
+ case 'ClassPrivateMethod':
88
+ case 'FunctionDeclaration':
89
+ case 'FunctionExpression':
90
+ case 'ObjectMethod':
91
+ return true;
92
+ }
93
+ return false;
94
+ }
95
+
96
+ function simplifyType(type, optional) {
97
+ if (type instanceof Object) {
98
+ type.optional = optional;
99
+ } else if (typeof type === 'string') {
100
+ type = type.trim();
101
+ if (type != 'object' && type != 'object[]' && type != 'union' && !optional) {
102
+ return type;
103
+ }
104
+ type = {
105
+ type,
106
+ optional
107
+ };
108
+ } else {
109
+ debugger;
110
+ console.warn("simplifyType> neither object nor string for type", type);
111
+ }
112
+ if (type.type == 'object' && type.properties && Object.keys(type.properties).length === 0) {
113
+ delete type.properties;
114
+ }
115
+ return type;
116
+ }
117
+
118
+ function parseJSDoc(src, expandType = expandTypeDepFree) {
119
+ const regex = /@param \{(.*?)\} ([\[\]a-zA-Z0-9_$=\{\}\.'" ]+)/g;
120
+ const matches = [...src.matchAll(regex)];
121
+ const params = Object.create(null);
122
+ matches.forEach(_ => {
123
+ const type = expandType(_[1].trim());
124
+ let name = _[2].trim();
125
+ let optional = false;
126
+ if (name[0] === '[') {
127
+ const closer = name.lastIndexOf(']');
128
+ name = name.substring(1, closer);
129
+ optional = true;
130
+ }
131
+ name = name.split(' ')[0].split('=')[0].trim();
132
+ const simplifiedType = simplifyType(type, optional);
133
+ const parts = name.split(".");
134
+ if (parts.length == 3) {
135
+ let parts0 = parts[0];
136
+ let parts1 = parts[1];
137
+ let parts2 = parts[2];
138
+ const toptype = params[parts0];
139
+ toptype.properties[parts1].properties = toptype.properties[parts1].properties || {};
140
+ toptype.properties[parts1].properties[parts2] = simplifiedType;
141
+ } else if (parts.length == 2) {
142
+ let parts0 = parts[0];
143
+ let parts1 = parts[1];
144
+ if (parts0.endsWith('[]')) {
145
+ parts0 = parts0.slice(0, -2);
146
+ }
147
+ const toptype = params[parts0];
148
+ if ((toptype == null ? void 0 : toptype.type) == "union") {
149
+ const typeObject = toptype.members.find(_ => (_ == null ? void 0 : _.type) == 'object');
150
+ typeObject.properties[parts1] = simplifiedType;
151
+ } else if ((toptype == null ? void 0 : toptype.type) == "array") {
152
+ toptype.elementType.properties[parts1] = simplifiedType;
153
+ } else if ((toptype == null ? void 0 : toptype.type) == "object") {
154
+ toptype.properties = toptype.properties || {};
155
+ toptype.properties[parts1] = simplifiedType;
156
+ } else {
157
+ console.warn("parseJSDoc> skipping @param, unseen syntax detected, please check if your JSDoc is valid or open an issue about this", {
158
+ src,
159
+ toptype,
160
+ parts0,
161
+ parts1,
162
+ simplifiedType
163
+ });
164
+ }
165
+ } else {
166
+ params[name] = simplifiedType;
167
+ }
168
+ });
169
+ if (Object.keys(params).length === 0) {
170
+ return;
171
+ }
172
+ return params;
173
+ }
174
+
175
+ function parseJSDocSetter(src, expandType = expandTypeDepFree) {
176
+ const regex = /@type \{(.*?)\}/g;
177
+ const matches = [...src.matchAll(regex)];
178
+ if (matches.length === 1) {
179
+ const match = matches[0];
180
+ const type = expandType(match[1]);
181
+ const simplifiedType = simplifyType(type, false);
182
+ return simplifiedType;
183
+ }
184
+ }
185
+
186
+ function extractNameAndOptionality(rest) {
187
+ rest = rest.trim();
188
+ let optional = false;
189
+ if (rest[0] === '[') {
190
+ const closer = rest.lastIndexOf(']');
191
+ rest = rest.substring(1, closer);
192
+ optional = true;
193
+ }
194
+ const name = rest.split(' ')[0].split('=')[0].trim();
195
+ return [name, optional];
196
+ }
197
+
198
+ function extractCurlyContent(line) {
199
+ const firstCurly = line.indexOf('{');
200
+ let k = firstCurly + 1;
201
+ let count = 0;
202
+ for (; k < line.length; k++) {
203
+ const c = line[k];
204
+ if (c === '{') {
205
+ count++;
206
+ } else if (c === '}') {
207
+ count--;
208
+ }
209
+ if (count === -1) {
210
+ break;
211
+ }
212
+ }
213
+ const content = line.substring(firstCurly + 1, k);
214
+ return {
215
+ content,
216
+ nextIndex: k + 1
217
+ };
218
+ }
219
+ function parseJSDocTypedef(typedefs, warn, comment, expandType) {
220
+ const {
221
+ type,
222
+ value
223
+ } = comment;
224
+ if (type !== 'CommentBlock') {
225
+ return;
226
+ }
227
+ const lines = value.split('\n');
228
+ let lastTypedef = undefined;
229
+ for (let line of lines) {
230
+ line = line.trim();
231
+ if (line[0] === '*') {
232
+ line = line.slice(1).trim();
233
+ }
234
+ if (line.startsWith('@typedef')) {
235
+ const {
236
+ content: def,
237
+ nextIndex
238
+ } = extractCurlyContent(line);
239
+ let name = line.substring(nextIndex).trim();
240
+ name = name.split(' ')[0];
241
+ lastTypedef = expandType(def);
242
+ typedefs[name] = lastTypedef;
243
+ } else if (line.startsWith('@property')) {
244
+ var _lastTypedef;
245
+ if (!lastTypedef) {
246
+ continue;
247
+ }
248
+ const {
249
+ content,
250
+ nextIndex
251
+ } = extractCurlyContent(line);
252
+ const rest = line.substring(nextIndex);
253
+ const propType = expandType(content);
254
+ const [name, optional] = extractNameAndOptionality(rest);
255
+ const finalType = simplifyType(propType, optional);
256
+ if (((_lastTypedef = lastTypedef) == null ? void 0 : _lastTypedef.type) === 'object') {
257
+ lastTypedef.properties[name] = finalType;
258
+ } else {
259
+ warn("not an extensible type", lastTypedef);
260
+ }
261
+ }
262
+ }
263
+ }
264
+
265
+ function statReset(stat) {
266
+ stat.checked = 0;
267
+ stat.unchecked = 0;
268
+ }
269
+
270
+ function trimEndSpaces(str) {
271
+ let i = str.length - 1;
272
+ while (str[i] === ' ') {
273
+ i--;
274
+ }
275
+ return str.slice(0, i + 1);
276
+ }
277
+
278
+ class Stringifier {
279
+ constructor() {
280
+ this.forceCurly = false;
281
+ this.parents = [];
282
+ this.numSpaces = 0;
283
+ }
284
+ toSource(node) {
285
+ var _node$extra;
286
+ const {
287
+ leadingComments,
288
+ trailingComments
289
+ } = node;
290
+ if (node === null) {
291
+ return '';
292
+ }
293
+ if (node.type === 'File') {
294
+ this.parents.length = 0;
295
+ }
296
+ this.parents.push(node);
297
+ let out = '';
298
+ let comments = '';
299
+ if (leadingComments) {
300
+ comments += this.mapToSource(leadingComments).join('');
301
+ }
302
+ if (node != null && (_node$extra = node.extra) != null && _node$extra.parenthesized) {
303
+ out += `(${comments}${this.toSource_(node)})`;
304
+ } else {
305
+ out += comments + this.toSource_(node);
306
+ }
307
+ if (trailingComments) {
308
+ for (const trailingComment of trailingComments) {
309
+ out += ' ' + this.toSource(trailingComment).trim();
310
+ }
311
+ }
312
+ this.parents.pop();
313
+ return out;
314
+ }
315
+ toSource_(node) {
316
+ if (!node) {
317
+ return '';
318
+ }
319
+ const {
320
+ type
321
+ } = node;
322
+ if (type === undefined) {
323
+ console.log("toSource> node without type", node);
324
+ }
325
+ if (this[type]) {
326
+ return this[type](node);
327
+ }
328
+ console.log(node);
329
+ const notOfInterest = ["start", "end", "loc", "type"];
330
+ const ofInterest = Object.keys(node).filter(_ => !notOfInterest.includes(_));
331
+ const props = ofInterest.join(', ');
332
+ const fn = `${type}(node) {\n const {${props}} = node;\n return ;\n}`;
333
+ console.warn('TODO ADD METHOD:', fn);
334
+ return `rtiUnhandled("${node.type}");\n`;
335
+ }
336
+ toSourceCurly(node) {
337
+ if (!this.forceCurly) {
338
+ return this.toSource(node);
339
+ }
340
+ const {
341
+ type
342
+ } = node;
343
+ const needCurly = type != 'BlockStatement' && type != 'EmptyStatement';
344
+ const spaces = this.spaces;
345
+ let out = '';
346
+ if (needCurly) {
347
+ out += ' {\n';
348
+ }
349
+ out += this.toSource(node);
350
+ if (needCurly) {
351
+ out += '\n';
352
+ out += spaces;
353
+ out += '}';
354
+ }
355
+ return out;
356
+ }
357
+ get parent() {
358
+ return this.parents[this.parents.length - 2];
359
+ }
360
+ get parentType() {
361
+ var _this$parent;
362
+ return (_this$parent = this.parent) == null ? void 0 : _this$parent.type;
363
+ }
364
+ get needSpaces() {
365
+ const t = this.parentType;
366
+ return t != "ForStatement" && t != "ForInStatement" && t != "ForOfStatement";
367
+ }
368
+ mapToSource(arr) {
369
+ return arr.map(_ => this.toSource(_));
370
+ }
371
+ generateTypeChecks(node) {
372
+ const {
373
+ spaces
374
+ } = this;
375
+ return `${spaces}/* Stub of Stringifier#generateTypeChecks({type=${node.type}}); */\n`;
376
+ }
377
+ get spaces() {
378
+ return ' '.repeat(this.numSpaces);
379
+ }
380
+ debugSpaces() {
381
+ const {
382
+ spaces,
383
+ parents
384
+ } = this;
385
+ const n = spaces.length;
386
+ const path = parents.map(_ => _.type).join('/');
387
+ return `${spaces}// got ${n} spaces for ${path}\n`;
388
+ }
389
+ AwaitExpression(node) {
390
+ const {
391
+ argument
392
+ } = node;
393
+ return `await ${this.toSource(argument)}`;
394
+ }
395
+ ClassBody(node) {
396
+ const {
397
+ body
398
+ } = node;
399
+ return this.mapToSource(body).join('\n');
400
+ }
401
+ ClassMethod(node) {
402
+ const {
403
+ static: static_,
404
+ key,
405
+ computed,
406
+ kind,
407
+ id,
408
+ generator,
409
+ async,
410
+ params,
411
+ body
412
+ } = node;
413
+ let out = this.spaces;
414
+ if (generator) {
415
+ out += '*';
416
+ }
417
+ if (id) {
418
+ console.warn('Stringifier#ClassMethod> unhandled id', node);
419
+ }
420
+ if (static_) {
421
+ out += 'static ';
422
+ }
423
+ if (async) {
424
+ out += 'async ';
425
+ }
426
+ if (kind === 'get') {
427
+ out += 'get ';
428
+ } else if (kind === 'set') {
429
+ out += 'set ';
430
+ } else if (kind === 'constructor' || kind === 'method') ; else {
431
+ console.warn("unhandled kind", kind, "for", node);
432
+ }
433
+ let methodName = this.toSource(key);
434
+ if (computed) {
435
+ methodName = `[${methodName}]`;
436
+ }
437
+ out += methodName;
438
+ out += `(${this.mapToSource(params).join(', ')})`;
439
+ out += this.toSource(body);
440
+ return out;
441
+ }
442
+ ClassExpression(node) {
443
+ const {
444
+ id,
445
+ superClass,
446
+ body
447
+ } = node;
448
+ let out = 'class ';
449
+ if (id !== null) {
450
+ out += this.toSource(id) + ' ';
451
+ }
452
+ if (superClass !== null) {
453
+ const s = this.toSource(superClass);
454
+ out += `extends ${s} `;
455
+ }
456
+ const c = this.toSource(body);
457
+ out += `{\n${c}\n}`;
458
+ return out;
459
+ }
460
+ ClassDeclaration(node) {
461
+ const {
462
+ id,
463
+ superClass,
464
+ body,
465
+ trailingComments,
466
+ leadingComments
467
+ } = node;
468
+ const spaces = this.spaces;
469
+ let out = spaces + 'class ' + this.toSource(id);
470
+ if (superClass) {
471
+ out += ` extends ${this.toSource(superClass)}`;
472
+ }
473
+ out += ' {\n';
474
+ this.numSpaces++;
475
+ out += this.toSource(body);
476
+ this.numSpaces--;
477
+ out += spaces;
478
+ out += '\n}\n';
479
+ return out;
480
+ }
481
+ ClassPrivateMethod(node) {
482
+ const {
483
+ static: static_,
484
+ key,
485
+ kind,
486
+ id,
487
+ generator,
488
+ async,
489
+ params,
490
+ body
491
+ } = node;
492
+ let out = this.spaces;
493
+ if (generator) {
494
+ out += '*';
495
+ }
496
+ if (id) {
497
+ console.warn('Stringifier#ClassPrivateMethod> unhandled id', node);
498
+ }
499
+ if (static_) {
500
+ out += 'static ';
501
+ }
502
+ if (async) {
503
+ out += 'async ';
504
+ }
505
+ if (kind === 'get') {
506
+ out += 'get ';
507
+ } else if (kind === 'set') {
508
+ out += 'set ';
509
+ } else if (kind === 'method') ; else {
510
+ console.warn("unhandled kind", kind, "for", node);
511
+ }
512
+ out += this.toSource(key);
513
+ out += `(${this.mapToSource(params).join(', ')})`;
514
+ out += this.toSource(body);
515
+ return out;
516
+ }
517
+ ClassProperty(node) {
518
+ const {
519
+ key,
520
+ computed,
521
+ value,
522
+ leadingComments
523
+ } = node;
524
+ const static_ = node.static;
525
+ const a = this.toSource(key);
526
+ const b = this.toSource(value);
527
+ let out = this.spaces;
528
+ if (static_) {
529
+ out += 'static ';
530
+ }
531
+ if (computed) {
532
+ out += `[${a}]`;
533
+ } else {
534
+ out += a;
535
+ }
536
+ if (b) {
537
+ out += ` = ${b}`;
538
+ }
539
+ out += ';';
540
+ return out;
541
+ }
542
+ ContinueStatement(node) {
543
+ const {
544
+ label
545
+ } = node;
546
+ let out = this.spaces + 'continue';
547
+ if (label) {
548
+ out += ' ' + this.toSource(label);
549
+ }
550
+ out += ';';
551
+ return out;
552
+ }
553
+ FunctionDeclarationParams(params) {
554
+ return '(' + this.mapToSource(params).join(', ') + ')';
555
+ }
556
+ FunctionDeclaration(node) {
557
+ const {
558
+ async,
559
+ body,
560
+ generator,
561
+ id,
562
+ leadingComments,
563
+ params
564
+ } = node;
565
+ let out = '';
566
+ if (this.parentType !== 'ExportNamedDeclaration') {
567
+ out += this.spaces;
568
+ }
569
+ if (async) {
570
+ out += 'async ';
571
+ }
572
+ const asterix = generator ? '*' : '';
573
+ out += 'function' + asterix + ' ' + this.toSource(id) + this.FunctionDeclarationParams(params);
574
+ out += this.toSource(body);
575
+ return out;
576
+ }
577
+ FunctionExpression(node) {
578
+ const {
579
+ async,
580
+ body,
581
+ generator,
582
+ id,
583
+ params
584
+ } = node;
585
+ let out = '';
586
+ if (async) {
587
+ out += 'async ';
588
+ }
589
+ const star = generator ? '*' : '';
590
+ out += 'function' + star + ' ' + this.toSource(id) + this.FunctionDeclarationParams(params);
591
+ out += this.toSource(body);
592
+ return out;
593
+ }
594
+ ArrowFunctionExpression(node) {
595
+ const {
596
+ async,
597
+ body,
598
+ generator,
599
+ params
600
+ } = node;
601
+ let out = '';
602
+ if (async) {
603
+ out += 'async ';
604
+ }
605
+ if (generator) {
606
+ out += ' * ';
607
+ }
608
+ out += this.FunctionDeclarationParams(params);
609
+ out += ' => ';
610
+ out += this.toSource(body);
611
+ return out;
612
+ }
613
+ BigIntLiteral(node) {
614
+ const {
615
+ extra,
616
+ value
617
+ } = node;
618
+ return extra.raw;
619
+ }
620
+ BlockStatement(node) {
621
+ const {
622
+ body,
623
+ directives
624
+ } = node;
625
+ const spaces = this.spaces;
626
+ let out = '';
627
+ out += ' {';
628
+ this.numSpaces++;
629
+ if (directives && directives.length) {
630
+ out += '\n';
631
+ out += this.mapToSource(directives).join('\n') + '\n';
632
+ }
633
+ out += this.generateTypeChecks(node);
634
+ if (body.length) {
635
+ if (out.length === 2) {
636
+ out += '\n';
637
+ }
638
+ out += this.mapToSource(body).join('\n') + '\n';
639
+ out += spaces;
640
+ }
641
+ this.numSpaces--;
642
+ out += '}';
643
+ return out;
644
+ }
645
+ Directive(node) {
646
+ const {
647
+ value
648
+ } = node;
649
+ return this.toSource(value);
650
+ }
651
+ DirectiveLiteral(node) {
652
+ const {
653
+ extra,
654
+ value
655
+ } = node;
656
+ const {
657
+ spaces
658
+ } = this;
659
+ return `${spaces}${extra.raw};`;
660
+ }
661
+ ReturnStatement(node) {
662
+ const {
663
+ argument
664
+ } = node;
665
+ const {
666
+ spaces
667
+ } = this;
668
+ if (!argument) {
669
+ return spaces + 'return;';
670
+ }
671
+ return spaces + 'return ' + this.toSource(argument) + ';';
672
+ }
673
+ Identifier(node) {
674
+ return node.name;
675
+ }
676
+ IfStatement(node) {
677
+ const {
678
+ alternate,
679
+ consequent,
680
+ test
681
+ } = node;
682
+ const spaces = this.spaces;
683
+ let out = '';
684
+ {
685
+ out += spaces;
686
+ }
687
+ out += `if (${this.toSource(test)})`;
688
+ out += this.toSourceCurly(consequent);
689
+ if (alternate) {
690
+ out += ` else${this.toSourceCurly(alternate)}`;
691
+ }
692
+ return out;
693
+ }
694
+ LabeledStatement(node) {
695
+ const {
696
+ body,
697
+ label
698
+ } = node;
699
+ const {
700
+ spaces
701
+ } = this;
702
+ let out = '';
703
+ out += spaces + this.toSource(label);
704
+ out += ': \n';
705
+ out += spaces + this.toSource(body);
706
+ return out;
707
+ }
708
+ UnaryExpression(node) {
709
+ let out = '';
710
+ const {
711
+ argument,
712
+ operator,
713
+ prefix
714
+ } = node;
715
+ if (!prefix) {
716
+ console.warn("Stringifier#UnaryExpression> never considered !prefix", node);
717
+ }
718
+ const c = operator.charCodeAt(0);
719
+ let op = operator;
720
+ if (c >= 97 && c <= 122) {
721
+ op += ' ';
722
+ }
723
+ out += op;
724
+ out += this.toSource(argument);
725
+ return out;
726
+ }
727
+ MemberExpression(node) {
728
+ const {
729
+ computed,
730
+ object,
731
+ property
732
+ } = node;
733
+ if (computed) {
734
+ return `${this.toSource(object)}[${this.toSource(property)}]`;
735
+ }
736
+ return `${this.toSource(object)}.${this.toSource(property)}`;
737
+ }
738
+ MetaProperty(node) {
739
+ const {
740
+ meta,
741
+ property
742
+ } = node;
743
+ const lhs = this.toSource(meta);
744
+ const rhs = this.toSource(property);
745
+ return `${lhs}.${rhs}`;
746
+ }
747
+ ExpressionStatement(node) {
748
+ const {
749
+ expression
750
+ } = node;
751
+ return this.spaces + this.toSource(expression) + ';';
752
+ }
753
+ CallExpression(node) {
754
+ const {
755
+ callee,
756
+ arguments: args,
757
+ extra
758
+ } = node;
759
+ let out = this.toSource(callee);
760
+ out += "(";
761
+ out += this.mapToSource(args).join(', ');
762
+ if (!!(extra != null && extra.trailingComma)) {
763
+ out += ',';
764
+ }
765
+ out += ")";
766
+ return out;
767
+ }
768
+ ObjectExpression(node) {
769
+ const {
770
+ properties,
771
+ extra
772
+ } = node;
773
+ let out = '{';
774
+ if (properties.length) {
775
+ this.numSpaces++;
776
+ const props = this.mapToSource(properties).join(',\n');
777
+ this.numSpaces--;
778
+ out += '\n';
779
+ out += props;
780
+ if (extra != null && extra.trailingComma) {
781
+ out += ',';
782
+ }
783
+ out += '\n';
784
+ out += this.spaces;
785
+ }
786
+ out += '}';
787
+ return out;
788
+ }
789
+ ObjectProperty(node) {
790
+ const {
791
+ computed,
792
+ key,
793
+ method,
794
+ shorthand,
795
+ value
796
+ } = node;
797
+ if (method) {
798
+ console.warn("ObjectProperty> unhandled method property:", {
799
+ method,
800
+ shorthand
801
+ });
802
+ }
803
+ const spaces = this.spaces;
804
+ let left = this.toSource(key);
805
+ const right = this.toSource(value);
806
+ let out = spaces;
807
+ if (computed) {
808
+ left = `[${left}]`;
809
+ }
810
+ if (!shorthand) {
811
+ out += left + ': ';
812
+ }
813
+ out += right;
814
+ return out;
815
+ }
816
+ BooleanLiteral(node) {
817
+ return node.value.toString();
818
+ }
819
+ AssignmentExpression(node) {
820
+ const {
821
+ left,
822
+ operator,
823
+ right
824
+ } = node;
825
+ const left_ = this.toSource(left);
826
+ const right_ = this.toSource(right);
827
+ return `${left_} ${operator} ${right_}`;
828
+ }
829
+ BinaryExpression(node) {
830
+ const {
831
+ left,
832
+ operator,
833
+ right
834
+ } = node;
835
+ const left_ = this.toSource(left);
836
+ const right_ = this.toSource(right);
837
+ return `${left_} ${operator} ${right_}`;
838
+ }
839
+ ThisExpression(node) {
840
+ return 'this';
841
+ }
842
+ ArrayExpression(node) {
843
+ const {
844
+ elements,
845
+ extra
846
+ } = node;
847
+ const e = !!(extra != null && extra.trailingComma) ? ',' : '';
848
+ return '[' + this.mapToSource(elements).join(', ') + e + ']';
849
+ }
850
+ VariableDeclaration(node) {
851
+ const {
852
+ declarations,
853
+ kind
854
+ } = node;
855
+ let spaces = '';
856
+ let semicolon = '';
857
+ if (this.needSpaces) {
858
+ semicolon = ';';
859
+ spaces = this.spaces;
860
+ }
861
+ return `${spaces}${kind} ${this.mapToSource(declarations).join(', ')}${semicolon}`;
862
+ }
863
+ VariableDeclarator(node) {
864
+ const {
865
+ id,
866
+ init
867
+ } = node;
868
+ if (init) {
869
+ return this.toSource(id) + ' = ' + this.toSource(init);
870
+ }
871
+ return this.toSource(id);
872
+ }
873
+ ConditionalExpression(node) {
874
+ const {
875
+ alternate,
876
+ consequent,
877
+ test
878
+ } = node;
879
+ return `${this.toSource(test)} ? ${this.toSource(consequent)} : ${this.toSource(alternate)}`;
880
+ }
881
+ LogicalExpression(node) {
882
+ const {
883
+ left,
884
+ operator,
885
+ right
886
+ } = node;
887
+ const l = this.toSource(left);
888
+ const r = this.toSource(right);
889
+ if (l === '') {
890
+ console.warn("LogicalExpression> unhandled empty left", node);
891
+ }
892
+ if (r === '') {
893
+ console.warn("LogicalExpression> unhandled empty right", node);
894
+ }
895
+ return `${l} ${operator} ${r}`;
896
+ }
897
+ ForStatement(node) {
898
+ const {
899
+ init,
900
+ test,
901
+ update,
902
+ body
903
+ } = node;
904
+ const spaces = this.spaces;
905
+ const i = this.toSource(init);
906
+ const t = this.toSource(test);
907
+ const u = this.toSource(update);
908
+ const b = this.toSourceCurly(body);
909
+ return `${spaces}for (${i}; ${t}; ${u})${b}`;
910
+ }
911
+ UpdateExpression(node) {
912
+ const {
913
+ operator,
914
+ prefix,
915
+ argument
916
+ } = node;
917
+ if (prefix) {
918
+ return `${operator}${this.toSource(argument)}`;
919
+ } else {
920
+ return `${this.toSource(argument)}${operator}`;
921
+ }
922
+ }
923
+ NewExpression(node) {
924
+ const {
925
+ callee,
926
+ arguments: args_
927
+ } = node;
928
+ const c = this.toSource(callee);
929
+ const args = this.mapToSource(args_).join(', ');
930
+ return `new ${c}(${args})`;
931
+ }
932
+ TemplateLiteral(node) {
933
+ const {
934
+ expressions,
935
+ quasis
936
+ } = node;
937
+ let out = '`';
938
+ for (var i = 0; i < quasis.length; i++) {
939
+ out += this.toSource(quasis[i]);
940
+ if (expressions[i]) {
941
+ out += '${' + this.toSource(expressions[i]) + '}';
942
+ }
943
+ }
944
+ out += '`';
945
+ return out;
946
+ }
947
+ TemplateElement(node) {
948
+ const {
949
+ value
950
+ } = node;
951
+ return value.raw;
952
+ }
953
+ PrivateName(node) {
954
+ const {
955
+ id
956
+ } = node;
957
+ return `#${this.toSource(id)}`;
958
+ }
959
+ ExportAllDeclaration(node) {
960
+ return `export * from ${node.source.extra.raw};`;
961
+ }
962
+ ExportNamedDeclaration(node) {
963
+ const {
964
+ declaration,
965
+ source,
966
+ specifiers
967
+ } = node;
968
+ let out = this.spaces;
969
+ if (specifiers.length) {
970
+ out += 'export {\n';
971
+ out += this.mapToSource(specifiers).map(_ => ` ${this.spaces}${_}`).join(',\n');
972
+ out += '\n';
973
+ out += this.spaces;
974
+ out += '}';
975
+ if (source) {
976
+ out += " from " + this.toSource(source);
977
+ }
978
+ out += ";\n";
979
+ } else if (declaration) {
980
+ out += 'export ' + this.toSource(declaration);
981
+ } else {
982
+ console.warn("ExportNamedDeclaration> unhandled case for", node);
983
+ }
984
+ return out;
985
+ }
986
+ ExportDefaultDeclaration(node) {
987
+ const {
988
+ declaration
989
+ } = node;
990
+ const a = this.toSource(declaration);
991
+ return `export default ${a};`;
992
+ }
993
+ ExportSpecifier(node) {
994
+ const {
995
+ exported,
996
+ local
997
+ } = node;
998
+ const left = this.toSource(exported);
999
+ const right = this.toSource(local);
1000
+ const {
1001
+ spaces
1002
+ } = this;
1003
+ if (left === right) {
1004
+ return `${spaces}${left}`;
1005
+ }
1006
+ return `${spaces}${right} as ${left}`;
1007
+ }
1008
+ Super(node) {
1009
+ return 'super';
1010
+ }
1011
+ ForInStatement(node) {
1012
+ const {
1013
+ left,
1014
+ right,
1015
+ body
1016
+ } = node;
1017
+ const {
1018
+ spaces
1019
+ } = this;
1020
+ const l = this.toSource(left);
1021
+ const r = this.toSource(right);
1022
+ const b = this.toSourceCurly(body);
1023
+ return `${spaces}for (${l} in ${r})${b}`;
1024
+ }
1025
+ ThrowStatement(node) {
1026
+ const {
1027
+ argument
1028
+ } = node;
1029
+ const {
1030
+ spaces
1031
+ } = this;
1032
+ const arg = this.toSource(argument);
1033
+ return `${spaces}throw ${arg};`;
1034
+ }
1035
+ WhileStatement(node) {
1036
+ const {
1037
+ test,
1038
+ body
1039
+ } = node;
1040
+ const {
1041
+ spaces
1042
+ } = this;
1043
+ const t = this.toSource(test);
1044
+ const b = this.toSourceCurly(body);
1045
+ return `${spaces}while (${t})${b}`;
1046
+ }
1047
+ BreakStatement(node) {
1048
+ const {
1049
+ label
1050
+ } = node;
1051
+ let out = this.spaces + 'break';
1052
+ if (label) {
1053
+ out += ' ' + this.toSource(label);
1054
+ }
1055
+ out += ';';
1056
+ return out;
1057
+ }
1058
+ ForOfStatement(node) {
1059
+ const {
1060
+ await: await_,
1061
+ left,
1062
+ right,
1063
+ body
1064
+ } = node;
1065
+ const {
1066
+ spaces
1067
+ } = this;
1068
+ const l = this.toSource(left);
1069
+ const r = this.toSource(right);
1070
+ const b = this.toSourceCurly(body);
1071
+ const a = await_ ? 'await ' : '';
1072
+ return `${spaces}for ${a}(${l} of ${r})${b}`;
1073
+ }
1074
+ ArrayPattern(node) {
1075
+ const {
1076
+ elements
1077
+ } = node;
1078
+ const e = this.mapToSource(elements).join(', ');
1079
+ return `[${e}]`;
1080
+ }
1081
+ SwitchStatement(node) {
1082
+ const {
1083
+ discriminant,
1084
+ cases
1085
+ } = node;
1086
+ const {
1087
+ spaces
1088
+ } = this;
1089
+ let out = '';
1090
+ out += spaces + `switch (${this.toSource(discriminant)}) {\n`;
1091
+ out += this.mapToSource(cases).join('\n') + '\n';
1092
+ out += spaces + '}';
1093
+ return out;
1094
+ }
1095
+ SwitchCase(node) {
1096
+ const {
1097
+ consequent,
1098
+ test
1099
+ } = node;
1100
+ const {
1101
+ spaces
1102
+ } = this;
1103
+ const c = this.mapToSource(consequent).join('\n');
1104
+ if (test) {
1105
+ const t = this.toSource(test);
1106
+ return `${spaces}case ${t}:\n${c}`;
1107
+ }
1108
+ return `${spaces}default:\n${c}`;
1109
+ }
1110
+ RegExpLiteral(node) {
1111
+ const {
1112
+ extra,
1113
+ value,
1114
+ pattern,
1115
+ flags
1116
+ } = node;
1117
+ return extra.raw;
1118
+ }
1119
+ SequenceExpression(node) {
1120
+ const {
1121
+ expressions
1122
+ } = node;
1123
+ return this.mapToSource(expressions).join(', ');
1124
+ }
1125
+ EmptyStatement(node) {
1126
+ return ';';
1127
+ }
1128
+ SpreadElement(node) {
1129
+ const {
1130
+ argument
1131
+ } = node;
1132
+ const a = this.toSource(argument);
1133
+ return `...${a}`;
1134
+ }
1135
+ ObjectMethod(node) {
1136
+ const {
1137
+ method,
1138
+ key,
1139
+ computed,
1140
+ kind,
1141
+ id,
1142
+ generator,
1143
+ async,
1144
+ params,
1145
+ body
1146
+ } = node;
1147
+ if (id !== null) {
1148
+ console.warn("ObjectMethod> id !== null is unhandled", node);
1149
+ debugger;
1150
+ }
1151
+ let out = this.spaces;
1152
+ if (generator) {
1153
+ out += '*';
1154
+ }
1155
+ if (id) {
1156
+ console.warn('Stringifier#ClassMethod> unhandled id', node);
1157
+ }
1158
+ if (async) {
1159
+ out += 'async ';
1160
+ }
1161
+ if (kind === 'get') {
1162
+ out += 'get ';
1163
+ } else if (kind === 'set') {
1164
+ out += 'set ';
1165
+ } else if (kind === 'method') ; else {
1166
+ console.warn("unhandled kind", kind, "for", node);
1167
+ }
1168
+ let methodName = this.toSource(key);
1169
+ if (computed) {
1170
+ methodName = `[${methodName}]`;
1171
+ }
1172
+ out += methodName;
1173
+ out += `(${this.mapToSource(params).join(', ')})`;
1174
+ out += this.toSource(body);
1175
+ return out;
1176
+ }
1177
+ ObjectPattern(node) {
1178
+ const {
1179
+ properties,
1180
+ extra
1181
+ } = node;
1182
+ let out = '{';
1183
+ if (properties.length) {
1184
+ out += '\n';
1185
+ this.numSpaces++;
1186
+ out += this.mapToSource(properties).join(',\n');
1187
+ this.numSpaces--;
1188
+ if (!!(extra != null && extra.trailingComma)) {
1189
+ out += ',';
1190
+ }
1191
+ out += '\n';
1192
+ out += this.spaces.slice(2);
1193
+ }
1194
+ out += '}';
1195
+ return out;
1196
+ }
1197
+ OptionalMemberExpression(node) {
1198
+ const {
1199
+ object,
1200
+ computed,
1201
+ property,
1202
+ optional
1203
+ } = node;
1204
+ const a = this.toSource(object);
1205
+ const b = this.toSource(property);
1206
+ if (!computed && !optional) {
1207
+ return `${a}.${b}`;
1208
+ } else if (!computed && optional) {
1209
+ return `${a}?.${b}`;
1210
+ } else if (computed && !optional) {
1211
+ return `${a}[${b}]`;
1212
+ }
1213
+ return `${a}?.[${b}]`;
1214
+ }
1215
+ OptionalCallExpression(node) {
1216
+ const {
1217
+ callee,
1218
+ optional,
1219
+ arguments: args
1220
+ } = node;
1221
+ const a = this.toSource(callee);
1222
+ const b = this.mapToSource(args);
1223
+ if (optional) {
1224
+ return `${a}?.(${b})`;
1225
+ }
1226
+ return `${a}(${b})`;
1227
+ }
1228
+ DoWhileStatement(node) {
1229
+ const {
1230
+ body,
1231
+ test,
1232
+ trailingComments
1233
+ } = node;
1234
+ const {
1235
+ spaces
1236
+ } = this;
1237
+ let out = spaces;
1238
+ out += "do ";
1239
+ out += this.toSourceCurly(body);
1240
+ out += ` while (${this.toSource(test)});`;
1241
+ return out;
1242
+ }
1243
+ TryStatement(node) {
1244
+ const {
1245
+ block,
1246
+ handler,
1247
+ finalizer
1248
+ } = node;
1249
+ let out = this.spaces;
1250
+ const b = this.toSource(block);
1251
+ out += `try ${b}`;
1252
+ if (handler) {
1253
+ out += this.toSource(handler);
1254
+ }
1255
+ if (finalizer) {
1256
+ out += 'finally' + this.toSource(finalizer);
1257
+ }
1258
+ return out;
1259
+ }
1260
+ CatchClause(node) {
1261
+ const {
1262
+ param,
1263
+ body
1264
+ } = node;
1265
+ const b = this.toSource(body);
1266
+ if (param) {
1267
+ const p = this.toSource(param);
1268
+ return ` catch (${p}) ${b}`;
1269
+ }
1270
+ return ` catch ${b}`;
1271
+ }
1272
+ RestElement(node) {
1273
+ const {
1274
+ argument
1275
+ } = node;
1276
+ return `...${this.toSource(argument)}`;
1277
+ }
1278
+ DebuggerStatement(node) {
1279
+ return `${this.spaces}debugger;`;
1280
+ }
1281
+ CommentBlock(node) {
1282
+ let {
1283
+ value
1284
+ } = node;
1285
+ const {
1286
+ spaces,
1287
+ parents
1288
+ } = this;
1289
+ const par = parents[parents.length - 3];
1290
+ let out = `${spaces}/*`;
1291
+ if (value.includes('\n')) {
1292
+ value = trimEndSpaces(value.replace(/^\s*\*/gm, '*')).split('\n').filter(_ => _.length).map((line, i) => (i ? spaces + ' ' : '') + line).join('\n');
1293
+ out += `${value}\n${spaces} */`;
1294
+ } else {
1295
+ out += `${value}*/`;
1296
+ }
1297
+ if (par && par.type === 'BlockStatement' || par.type === 'ObjectExpression' || par.type === 'Program') {
1298
+ return out + '\n';
1299
+ }
1300
+ return ' ' + out + ' ';
1301
+ }
1302
+ CommentLine(node) {
1303
+ const {
1304
+ value
1305
+ } = node;
1306
+ return `${this.spaces.slice(2)}//${value}\n`;
1307
+ }
1308
+ Import(node) {
1309
+ return 'import';
1310
+ }
1311
+ ImportDeclaration(node) {
1312
+ const {
1313
+ specifiers,
1314
+ source
1315
+ } = node;
1316
+ const a = this.mapToSource(specifiers).join(', ');
1317
+ const b = this.toSource(source);
1318
+ if (specifiers.length === 0) {
1319
+ return `import ${b}`;
1320
+ }
1321
+ if (specifiers[0].type !== 'ImportSpecifier') {
1322
+ return `import ${a} from ${b};`;
1323
+ }
1324
+ return `import {${a}} from ${b};`;
1325
+ }
1326
+ ImportSpecifier(node) {
1327
+ const {
1328
+ imported,
1329
+ local
1330
+ } = node;
1331
+ const a = this.toSource(imported);
1332
+ const b = this.toSource(local);
1333
+ if (a !== b) {
1334
+ return `${a} as ${b}`;
1335
+ }
1336
+ return a;
1337
+ }
1338
+ ImportDefaultSpecifier(node) {
1339
+ const {
1340
+ local
1341
+ } = node;
1342
+ return this.toSource(local);
1343
+ }
1344
+ ImportNamespaceSpecifier(node) {
1345
+ const {
1346
+ local
1347
+ } = node;
1348
+ return `* as ${this.toSource(local)}`;
1349
+ }
1350
+ File(node) {
1351
+ return this.toSource(node.program) + '\n';
1352
+ }
1353
+ Program(node) {
1354
+ const {
1355
+ sourceType,
1356
+ interpreter,
1357
+ body,
1358
+ directives
1359
+ } = node;
1360
+ let out = '';
1361
+ out += this.mapToSource(directives);
1362
+ out += this.mapToSource(body).join('\n');
1363
+ return out;
1364
+ }
1365
+ StringLiteral(node) {
1366
+ const {
1367
+ extra
1368
+ } = node;
1369
+ if (!extra) {
1370
+ debugger;
1371
+ return '';
1372
+ }
1373
+ if (typeof extra.raw !== 'string') {
1374
+ debugger;
1375
+ return '';
1376
+ }
1377
+ return extra.raw;
1378
+ }
1379
+ NumericLiteral(node) {
1380
+ return node.extra.raw;
1381
+ }
1382
+ AssignmentPattern(node) {
1383
+ const {
1384
+ left,
1385
+ right
1386
+ } = node;
1387
+ return `${this.toSource(left)} = ${this.toSource(right)}`;
1388
+ }
1389
+ NullLiteral(node) {
1390
+ return 'null';
1391
+ }
1392
+ TaggedTemplateExpression(node) {
1393
+ const {
1394
+ tag,
1395
+ quasi
1396
+ } = node;
1397
+ const t = this.toSource(tag);
1398
+ const q = this.toSource(quasi);
1399
+ return t + q;
1400
+ }
1401
+ YieldExpression(node) {
1402
+ const {
1403
+ delegate,
1404
+ argument
1405
+ } = node;
1406
+ let keyword = 'yield';
1407
+ if (delegate) {
1408
+ keyword += '*';
1409
+ }
1410
+ const a = this.toSource(argument);
1411
+ return `${keyword} ${a}`;
1412
+ }
1413
+ }
1414
+
1415
+ class Asserter extends Stringifier {
1416
+ constructor({
1417
+ forceCurly = true,
1418
+ validateDivision = true,
1419
+ expandType = expandTypeDepFree,
1420
+ filename
1421
+ } = {}) {
1422
+ super();
1423
+ this.stats = {
1424
+ 'ArrowFunctionExpression': {
1425
+ checked: 0,
1426
+ unchecked: 0
1427
+ },
1428
+ 'ClassMethod#constructor': {
1429
+ checked: 0,
1430
+ unchecked: 0
1431
+ },
1432
+ 'ClassMethod#get': {
1433
+ checked: 0,
1434
+ unchecked: 0
1435
+ },
1436
+ 'ClassMethod#method': {
1437
+ checked: 0,
1438
+ unchecked: 0
1439
+ },
1440
+ 'ClassMethod#set': {
1441
+ checked: 0,
1442
+ unchecked: 0
1443
+ },
1444
+ 'ClassPrivateMethod#get': {
1445
+ checked: 0,
1446
+ unchecked: 0
1447
+ },
1448
+ 'ClassPrivateMethod#method': {
1449
+ checked: 0,
1450
+ unchecked: 0
1451
+ },
1452
+ 'ClassPrivateMethod#set': {
1453
+ checked: 0,
1454
+ unchecked: 0
1455
+ },
1456
+ 'FunctionDeclaration': {
1457
+ checked: 0,
1458
+ unchecked: 0
1459
+ },
1460
+ 'FunctionExpression': {
1461
+ checked: 0,
1462
+ unchecked: 0
1463
+ },
1464
+ 'ObjectMethod': {
1465
+ checked: 0,
1466
+ unchecked: 0
1467
+ }
1468
+ };
1469
+ this.typedefs = {};
1470
+ this.forceCurly = forceCurly;
1471
+ this.validateDivision = validateDivision;
1472
+ this.expandType = expandType;
1473
+ this.filename = filename;
1474
+ }
1475
+ ArrowFunctionExpression(node) {
1476
+ const {
1477
+ async,
1478
+ body,
1479
+ generator,
1480
+ params
1481
+ } = node;
1482
+ let out = '';
1483
+ if (async) {
1484
+ out += 'async ';
1485
+ }
1486
+ if (generator) {
1487
+ out += ' * ';
1488
+ }
1489
+ out += this.FunctionDeclarationParams(params);
1490
+ out += ' =>';
1491
+ if (body.type === 'BlockStatement') {
1492
+ out += this.toSource(body);
1493
+ } else {
1494
+ out += ' {\n';
1495
+ out += this.generateTypeChecks(node);
1496
+ out += this.spaces + 'return ' + this.toSource(body) + ';\n';
1497
+ out += '}';
1498
+ }
1499
+ return out;
1500
+ }
1501
+ ClassDeclaration(node) {
1502
+ const {
1503
+ id
1504
+ } = node;
1505
+ const id_ = this.toSource(id);
1506
+ let out = super.ClassDeclaration(node);
1507
+ out += `${this.spaces}registerClass(${id_});`;
1508
+ return out;
1509
+ }
1510
+ findParentOfType(node, type) {
1511
+ const currentIndex = this.parents.findLastIndex(_ => _ == node);
1512
+ return this.parents.findLast((_, i) => {
1513
+ if (i > currentIndex) {
1514
+ return false;
1515
+ }
1516
+ return _.type === type;
1517
+ });
1518
+ }
1519
+ getLeadingCommentsNodeForArrowFunctionExpression(node) {
1520
+ const {
1521
+ parents
1522
+ } = this;
1523
+ let i = parents.findLastIndex(_ => _ == node);
1524
+ let parent = parents[i];
1525
+ if (parent.leadingComments) {
1526
+ return parent;
1527
+ }
1528
+ i--;
1529
+ while (i >= 0) {
1530
+ parent = parents[i];
1531
+ if (parent.leadingComments) {
1532
+ return parent;
1533
+ }
1534
+ if (nodeIsFunction(parent)) {
1535
+ break;
1536
+ }
1537
+ i--;
1538
+ }
1539
+ }
1540
+ warn(...args) {
1541
+ if (this.filename) {
1542
+ console.warn("[WARN]", this.filename);
1543
+ }
1544
+ console.warn(...args);
1545
+ }
1546
+ getJSDoc(node) {
1547
+ if (node.type === 'BlockStatement') {
1548
+ node = this.parent;
1549
+ }
1550
+ if (node.type === 'FunctionExpression') {
1551
+ if (node.leadingComments) {
1552
+ this.warn("Case of FunctionExpression containing its own leadingComments is not handled");
1553
+ return;
1554
+ }
1555
+ node = this.findParentOfType(node, 'ExpressionStatement');
1556
+ if (!node) {
1557
+ node = this.parents.findLast(_ => _.type == 'VariableDeclaration');
1558
+ if (!node) {
1559
+ return;
1560
+ }
1561
+ }
1562
+ }
1563
+ let {
1564
+ leadingComments
1565
+ } = node;
1566
+ if (!leadingComments) {
1567
+ if (node.type === 'FunctionDeclaration') {
1568
+ const exportNamedDeclaration = this.findParentOfType(node, 'ExportNamedDeclaration');
1569
+ leadingComments = exportNamedDeclaration == null ? void 0 : exportNamedDeclaration.leadingComments;
1570
+ }
1571
+ if (node.type === 'ArrowFunctionExpression') {
1572
+ const tmp = this.getLeadingCommentsNodeForArrowFunctionExpression(node);
1573
+ leadingComments = tmp == null ? void 0 : tmp.leadingComments;
1574
+ }
1575
+ }
1576
+ if (leadingComments && leadingComments.length) {
1577
+ const lastComment = leadingComments[leadingComments.length - 1];
1578
+ if (lastComment.type == "CommentBlock") {
1579
+ if (lastComment.value.includes('@event')) {
1580
+ return;
1581
+ }
1582
+ if (node.type === 'ClassMethod' && node.kind === 'set') {
1583
+ const paramName = this.getNameOfParam(node.params[0]);
1584
+ if (node.params.length !== 1) {
1585
+ this.warn("getJSDoc> setters require exactly one argument");
1586
+ }
1587
+ return {
1588
+ [paramName]: parseJSDocSetter(lastComment.value, this.expandType)
1589
+ };
1590
+ }
1591
+ return parseJSDoc(lastComment.value, this.expandType);
1592
+ }
1593
+ }
1594
+ }
1595
+ getNameOfParam(param) {
1596
+ if (param.type === 'Identifier') {
1597
+ return param.name;
1598
+ } else if (param.type === 'AssignmentPattern') {
1599
+ if (param.left.type === 'Identifier') {
1600
+ return param.left.name;
1601
+ }
1602
+ }
1603
+ debugger;
1604
+ this.warn("unable to extra name from param in specified way - may contain too much information");
1605
+ return this.toSource(param);
1606
+ }
1607
+ statsReset() {
1608
+ Object.values(this.stats).forEach(statReset);
1609
+ }
1610
+ statsPrint() {
1611
+ console.table(this.stats);
1612
+ }
1613
+ getStatsForNode(node) {
1614
+ const {
1615
+ stats
1616
+ } = this;
1617
+ const type = nodeIsFunction(node) ? node.type : this.parentType;
1618
+ if (type === 'ClassMethod') {
1619
+ const parent = this.parent;
1620
+ const {
1621
+ kind
1622
+ } = parent;
1623
+ return stats[`ClassMethod#${kind}`];
1624
+ } else if (type === 'ClassPrivateMethod') {
1625
+ const parent = this.parent;
1626
+ const {
1627
+ kind
1628
+ } = parent;
1629
+ return stats[`ClassPrivateMethod#${kind}`];
1630
+ }
1631
+ const stat = stats[type];
1632
+ if (!stat) {
1633
+ this.warn("getStatsForNode> dummy, but unhandled... fix for node type", node);
1634
+ return {
1635
+ checked: 0,
1636
+ unchecked: 0
1637
+ };
1638
+ }
1639
+ return stat;
1640
+ }
1641
+ nodeHasParamName(node, name) {
1642
+ if (node.type === 'BlockStatement') {
1643
+ node = this.parent;
1644
+ }
1645
+ const {
1646
+ params
1647
+ } = node;
1648
+ if (!params) {
1649
+ this.warn("nodeHasParamName> Expected params for", {
1650
+ node,
1651
+ name
1652
+ });
1653
+ return false;
1654
+ }
1655
+ return params.some(node => {
1656
+ const {
1657
+ type
1658
+ } = node;
1659
+ if (type === "AssignmentPattern") {
1660
+ const {
1661
+ left
1662
+ } = node;
1663
+ console.assert(left.type === 'Identifier' || left.type === 'ObjectPattern' || left.type === 'ArrayPattern' || left.type === 'AssignmentPattern', 'Expected Identifier or ObjectPattern');
1664
+ return left.name === name;
1665
+ } else if (type === 'Identifier') {
1666
+ return node.name === name;
1667
+ } else if (type === 'ArrayPattern' || type === 'ObjectPattern' || type === 'RestElement') {
1668
+ return false;
1669
+ } else {
1670
+ const _ = new Stringifier();
1671
+ const code = _.toSource(node);
1672
+ console.log("Unknown type to test params for", type, code);
1673
+ }
1674
+ return false;
1675
+ });
1676
+ }
1677
+ generateTypeChecks(node) {
1678
+ const {
1679
+ parent
1680
+ } = this;
1681
+ if (node.type === 'BlockStatement' && !nodeIsFunction(parent)) {
1682
+ return '';
1683
+ }
1684
+ const jsdoc = this.getJSDoc(node);
1685
+ const stat = this.getStatsForNode(node);
1686
+ if (!jsdoc) {
1687
+ stat.unchecked++;
1688
+ return '';
1689
+ }
1690
+ stat.checked++;
1691
+ const {
1692
+ spaces
1693
+ } = this;
1694
+ let out = '';
1695
+ let first = true;
1696
+ for (let name in jsdoc) {
1697
+ const type = jsdoc[name];
1698
+ const hasParam = this.nodeHasParamName(node, name);
1699
+ if (!hasParam) {
1700
+ let testNode = node;
1701
+ if (node.type === 'BlockStatement') {
1702
+ testNode = this.parent;
1703
+ }
1704
+ const paramIndex = Object.keys(jsdoc).findIndex(_ => _ === name);
1705
+ const param = testNode.params[paramIndex];
1706
+ if (param) {
1707
+ const isObjectPattern = param.type === 'ObjectPattern';
1708
+ const isArrayPattern = param.type === 'ArrayPattern';
1709
+ const isSupportedPattern = isObjectPattern || isArrayPattern;
1710
+ if (isSupportedPattern) {
1711
+ name = `arguments[${paramIndex}]`;
1712
+ } else if (param.type === 'AssignmentPattern') {
1713
+ const _loc = this.getName(node);
1714
+ if (param.left.type === 'ArrayPattern' && type.type === 'array') {
1715
+ for (const element of param.left.elements) {
1716
+ if (element.type !== 'Identifier') {
1717
+ this.warn('Only Identifier case handled right now');
1718
+ continue;
1719
+ }
1720
+ const _t = JSON.stringify(type.elementType, null, 2).replaceAll('\n', '\n' + spaces);
1721
+ out += `${spaces}if (!assertType(${element.name}, ${_t}, '${_loc}', '${name}')) {\n`;
1722
+ out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`;
1723
+ }
1724
+ continue;
1725
+ } else if (param.left.type === 'ObjectPattern' && type.type === 'object') {
1726
+ for (const property of param.left.properties) {
1727
+ if (property.key.type !== 'Identifier') {
1728
+ this.warn('ObjectPattern> Only Identifier case handled right now');
1729
+ continue;
1730
+ }
1731
+ const keyName = property.key.name;
1732
+ const subType = type.properties[keyName];
1733
+ if (!subType) {
1734
+ this.warn("missing subtype information in JSDoc");
1735
+ continue;
1736
+ }
1737
+ const _t2 = JSON.stringify(subType, null, 2).replaceAll('\n', '\n' + spaces);
1738
+ out += `${spaces}if (!assertType(${keyName}, ${_t2}, '${_loc}', '${name}')) {\n`;
1739
+ out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`;
1740
+ }
1741
+ continue;
1742
+ }
1743
+ this.warn(`generateTypeChecks> ${_loc}> todo implement`, `AssignmentPattern for parameter ${name}`);
1744
+ continue;
1745
+ }
1746
+ } else {
1747
+ const _loc2 = this.getName(node);
1748
+ this.warn(`generateTypeChecks> ${_loc2}> Missing param: ${name}`);
1749
+ continue;
1750
+ }
1751
+ }
1752
+ let t = JSON.stringify(type, null, 2).replaceAll('\n', '\n' + spaces);
1753
+ if (type === 'this') {
1754
+ const classDecl = this.findParentOfType(node, 'ClassDeclaration');
1755
+ if (!(classDecl != null && classDecl.id)) {
1756
+ this.warn('generateTypeChecks> !classDecl?.id');
1757
+ }
1758
+ t = '"' + this.toSource(classDecl.id) + '"';
1759
+ }
1760
+ const loc = this.getName(node);
1761
+ let prevCheck = '';
1762
+ if (loc === 'ContactPoint#constructor' || loc === 'ContactResult#constructor' || loc === 'SingleContactResult#constructor') {
1763
+ prevCheck = 'arguments.length !== 0 && ';
1764
+ }
1765
+ if (first) {
1766
+ out += '\n';
1767
+ first = false;
1768
+ }
1769
+ out += `${spaces}if (${prevCheck}!assertType(${name}, ${t}, '${loc}', '${name}')) {\n`;
1770
+ out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`;
1771
+ }
1772
+ return out;
1773
+ }
1774
+ getName(node) {
1775
+ const toSource = this.toSource.bind(this);
1776
+ if (node.type === 'BlockStatement') {
1777
+ node = this.parent;
1778
+ }
1779
+ const {
1780
+ type,
1781
+ key,
1782
+ id
1783
+ } = node;
1784
+ switch (type) {
1785
+ case 'FunctionDeclaration':
1786
+ return toSource(id);
1787
+ case 'ClassMethod':
1788
+ case 'ClassPrivateMethod':
1789
+ const classDecl = this.parents.findLast(_ => _.type == 'ClassDeclaration');
1790
+ let out = '';
1791
+ if (classDecl) {
1792
+ out += toSource(classDecl.id) + '#';
1793
+ }
1794
+ out += toSource(key);
1795
+ return out;
1796
+ case 'FunctionExpression':
1797
+ if (id) {
1798
+ return toSource(id);
1799
+ }
1800
+ const expressionStatement = this.findParentOfType(node, 'ExpressionStatement');
1801
+ if (!expressionStatement) {
1802
+ return 'unnamed function expression';
1803
+ }
1804
+ return toSource(expressionStatement.expression.left);
1805
+ case 'ArrowFunctionExpression':
1806
+ const parent = this.findParentOfType(node, 'VariableDeclarator');
1807
+ if (parent) {
1808
+ return toSource(parent.id);
1809
+ } else {
1810
+ return 'getName> missing parent for ' + node.type;
1811
+ }
1812
+ case 'ObjectMethod':
1813
+ return toSource(key);
1814
+ default:
1815
+ this.warn('getName> unhandled type', type, 'for', node);
1816
+ return '/*MISSING*/';
1817
+ }
1818
+ }
1819
+ BinaryExpression(node) {
1820
+ if (!this.validateDivision) {
1821
+ return super.BinaryExpression(node);
1822
+ }
1823
+ const {
1824
+ left,
1825
+ operator,
1826
+ right
1827
+ } = node;
1828
+ const left_ = this.toSource(left);
1829
+ const right_ = this.toSource(right);
1830
+ if (operator === '/') {
1831
+ return `validateDivision(${left_}, ${right_})`;
1832
+ }
1833
+ return `${left_} ${operator} ${right_}`;
1834
+ }
1835
+ File(node) {
1836
+ const {
1837
+ errors,
1838
+ program,
1839
+ comments
1840
+ } = node;
1841
+ if (comments) {
1842
+ for (const comment of comments) {
1843
+ const warn = this.warn.bind(this);
1844
+ parseJSDocTypedef(this.typedefs, warn, comment, this.expandType);
1845
+ }
1846
+ }
1847
+ let out = '';
1848
+ for (const name in this.typedefs) {
1849
+ const typedef = this.typedefs[name];
1850
+ const json = JSON.stringify(typedef, null, 2);
1851
+ out += `registerTypedef('${name}', ${json});\n`;
1852
+ }
1853
+ const code = this.toSource(program) + '\n';
1854
+ out += code;
1855
+ return out;
1856
+ }
1857
+ }
1858
+
1859
+ function addTypeChecks(src, options) {
1860
+ try {
1861
+ const asserter = new Asserter(options);
1862
+ const ast = parse(src, {
1863
+ sourceType: 'module'
1864
+ });
1865
+ const out = asserter.toSource(ast);
1866
+ return out;
1867
+ } catch (e) {
1868
+ console.error(e);
1869
+ return `/*<addTypeChecks-error>*/${src}/*</addTypeChecks-error>*/`;
1870
+ }
1871
+ }
1872
+
1873
+ function ast2json(ast) {
1874
+ return JSON.stringify(ast, function (name, val) {
1875
+ if (name == "loc" || name == "start" || name == "end") {
1876
+ return undefined;
1877
+ }
1878
+ return val;
1879
+ }, 2);
1880
+ }
1881
+
1882
+ const drop = ['loc', 'start', 'end', 'leadingComments', 'trailingComments', 'innerComments', 'innerComments', 'comments'];
1883
+ function ast2jsonForComparison(ast) {
1884
+ return JSON.stringify(ast, function (name, val) {
1885
+ if (name === 'trailingComma' || name === 'parenStart') {
1886
+ return 'offset removed for better comparison';
1887
+ }
1888
+ if (drop.includes(name)) {
1889
+ return undefined;
1890
+ }
1891
+ return val;
1892
+ }, 2);
1893
+ }
1894
+
1895
+ function code2ast2code(code) {
1896
+ const stringifier = new Stringifier();
1897
+ const ast = parse(code, {
1898
+ sourceType: 'module'
1899
+ });
1900
+ if (!ast) {
1901
+ return;
1902
+ }
1903
+ const out = stringifier.toSource(ast);
1904
+ return out;
1905
+ }
1906
+
1907
+ function expandType(type) {
1908
+ const ast = parseType(type);
1909
+ return toSourceTS(ast);
1910
+ }
1911
+ function parseType(str) {
1912
+ if (str.startsWith('...')) {
1913
+ str = str.slice(3);
1914
+ str += '[]';
1915
+ }
1916
+ str = `type tmp = ${str};`;
1917
+ const ast = ts$1.createSourceFile('repl.ts', str, ts$1.ScriptTarget.Latest, true);
1918
+ return ast.statements[0].type;
1919
+ }
1920
+ function toSourceTS(node) {
1921
+ const {
1922
+ typeArguments,
1923
+ typeName
1924
+ } = node;
1925
+ const kind_ = ts$1.SyntaxKind[node.kind];
1926
+ const {
1927
+ AnyKeyword,
1928
+ ArrayType,
1929
+ BooleanKeyword,
1930
+ FunctionType,
1931
+ Identifier,
1932
+ IntersectionType,
1933
+ JSDocAllType,
1934
+ LastTypeNode,
1935
+ LiteralType,
1936
+ NullKeyword,
1937
+ NumberKeyword,
1938
+ NumericLiteral,
1939
+ ObjectKeyword,
1940
+ Parameter,
1941
+ ParenthesizedType,
1942
+ PropertySignature,
1943
+ StringKeyword,
1944
+ StringLiteral,
1945
+ ThisType,
1946
+ TupleType,
1947
+ TypeLiteral,
1948
+ TypeReference,
1949
+ UndefinedKeyword,
1950
+ UnionType,
1951
+ JSDocNullableType,
1952
+ TrueKeyword,
1953
+ FalseKeyword,
1954
+ VoidKeyword
1955
+ } = ts$1.SyntaxKind;
1956
+ switch (node.kind) {
1957
+ case FunctionType:
1958
+ const parameters = node.parameters.map(toSourceTS);
1959
+ return {
1960
+ type: 'function',
1961
+ parameters
1962
+ };
1963
+ case JSDocNullableType:
1964
+ const t = toSourceTS(node.type);
1965
+ return {
1966
+ type: 'union',
1967
+ members: [t, 'null']
1968
+ };
1969
+ case Parameter:
1970
+ const type = node.type ? toSourceTS(node.type) : 'any';
1971
+ const name = toSourceTS(node.name);
1972
+ const ret = {
1973
+ type,
1974
+ name
1975
+ };
1976
+ if (node.dotDotDotToken) {
1977
+ return {
1978
+ type: 'array',
1979
+ elementType: ret
1980
+ };
1981
+ }
1982
+ return ret;
1983
+ case TypeReference:
1984
+ if ((typeName.text === 'Object' || typeName.text === 'Record') && (typeArguments == null ? void 0 : typeArguments.length) === 2) {
1985
+ return {
1986
+ type: 'record',
1987
+ key: toSourceTS(typeArguments[0]),
1988
+ val: toSourceTS(typeArguments[1])
1989
+ };
1990
+ } else if (typeName.text === 'Object' && (!typeArguments || (typeArguments == null ? void 0 : typeArguments.length) === 0)) {
1991
+ return {
1992
+ type: 'object',
1993
+ properties: {}
1994
+ };
1995
+ } else if (typeName.text === 'Map' && (typeArguments == null ? void 0 : typeArguments.length) === 2) {
1996
+ return {
1997
+ type: 'map',
1998
+ key: toSourceTS(typeArguments[0]),
1999
+ val: toSourceTS(typeArguments[1])
2000
+ };
2001
+ } else if (typeName.text === 'Array' && (typeArguments == null ? void 0 : typeArguments.length) === 1) {
2002
+ const elementType = toSourceTS(typeArguments[0]);
2003
+ return {
2004
+ type: 'array',
2005
+ elementType
2006
+ };
2007
+ } else if (typeName.text === 'Set' && (typeArguments == null ? void 0 : typeArguments.length) === 1) {
2008
+ const elementType = toSourceTS(typeArguments[0]);
2009
+ return {
2010
+ type: 'set',
2011
+ elementType
2012
+ };
2013
+ } else if (typeName.text === 'Class' && (typeArguments == null ? void 0 : typeArguments.length) === 1) {
2014
+ return {
2015
+ type: 'class',
2016
+ elementType: toSourceTS(typeArguments[0])
2017
+ };
2018
+ } else {
2019
+ if (!typeArguments) {
2020
+ return typeName.getText();
2021
+ }
2022
+ console.warn('unhandled TypeReference', kind_, node);
2023
+ return {
2024
+ type: 'unhandled TypeReference'
2025
+ };
2026
+ }
2027
+ case StringKeyword:
2028
+ return node.getText();
2029
+ case NumberKeyword:
2030
+ return node.getText();
2031
+ case IntersectionType:
2032
+ return {
2033
+ type: 'intersection',
2034
+ members: node.types.map(toSourceTS)
2035
+ };
2036
+ case TupleType:
2037
+ return {
2038
+ type: 'tuple',
2039
+ elements: node.elements.map(toSourceTS)
2040
+ };
2041
+ case UnionType:
2042
+ return {
2043
+ type: 'union',
2044
+ members: node.types.map(toSourceTS)
2045
+ };
2046
+ case TypeLiteral:
2047
+ const properties = {};
2048
+ node.members.forEach(member => {
2049
+ const name = toSourceTS(member.name);
2050
+ const type = toSourceTS(member.type);
2051
+ properties[name] = type;
2052
+ });
2053
+ return {
2054
+ type: 'object',
2055
+ properties
2056
+ };
2057
+ case PropertySignature:
2058
+ console.warn('toSourceTS> should not happen, handled by TypeLiteral directly');
2059
+ return `${toSourceTS(node.name)}: ${toSourceTS(node.type)}`;
2060
+ case Identifier:
2061
+ return node.text;
2062
+ case ArrayType:
2063
+ return {
2064
+ type: 'array',
2065
+ elementType: toSourceTS(node.elementType)
2066
+ };
2067
+ case LiteralType:
2068
+ return toSourceTS(node.literal);
2069
+ case AnyKeyword:
2070
+ case BooleanKeyword:
2071
+ case JSDocAllType:
2072
+ case NullKeyword:
2073
+ case NumericLiteral:
2074
+ case StringLiteral:
2075
+ case ThisType:
2076
+ case UndefinedKeyword:
2077
+ case TrueKeyword:
2078
+ case FalseKeyword:
2079
+ case VoidKeyword:
2080
+ return node.getText();
2081
+ case ObjectKeyword:
2082
+ return {
2083
+ type: 'object',
2084
+ properties: {}
2085
+ };
2086
+ case ParenthesizedType:
2087
+ return toSourceTS(node.type);
2088
+ case LastTypeNode:
2089
+ return toSourceTS(node.qualifier);
2090
+ default:
2091
+ console.warn('toSourceTS> unhandled kind - make sure to understand you cannot reverse TS enums');
2092
+ console.warn('if they contain range aliases, for example:');
2093
+ console.warn('ts.SyntaxKind.NumericLiteral === ts.SyntaxKind.FirstLiteralToken');
2094
+ console.warn('so this "kind" could be wrong, but requires handling anyway:', kind_, node);
2095
+ debugger;
2096
+ }
2097
+ }
2098
+
2099
+ function expandTypeBabelTS(type) {
2100
+ const ast = parseTypeBabelTS(type);
2101
+ return toSourceBabelTS(ast);
2102
+ }
2103
+ function parseTypeBabelTS(str) {
2104
+ str = `type tmp = ${str};`;
2105
+ const ast = parse(str, {
2106
+ plugins: ['typescript']
2107
+ });
2108
+ return ast.program.body[0].typeAnnotation;
2109
+ }
2110
+ function toSourceBabelTS(node) {
2111
+ const {
2112
+ typeName
2113
+ } = node;
2114
+ const kind_ = ts.SyntaxKind[node.kind];
2115
+ switch (node.type) {
2116
+ case 'TSTypeReference':
2117
+ {
2118
+ const name = toSourceBabelTS(node.typeName);
2119
+ console.assert(node.typeParameters.type === 'TSTypeParameterInstantiation');
2120
+ const typeArguments = node.typeParameters.params;
2121
+ if ((name === 'Object' || name === 'Record') && (typeArguments == null ? void 0 : typeArguments.length) === 2) {
2122
+ return {
2123
+ type: 'record',
2124
+ key: toSourceBabelTS(typeArguments[0]),
2125
+ val: toSourceBabelTS(typeArguments[1])
2126
+ };
2127
+ } else if (name === 'Object' && (!typeArguments || (typeArguments == null ? void 0 : typeArguments.length) === 0)) {
2128
+ return {
2129
+ type: 'object',
2130
+ properties: {}
2131
+ };
2132
+ } else if (name === 'Map' && (typeArguments == null ? void 0 : typeArguments.length) === 2) {
2133
+ return {
2134
+ type: 'map',
2135
+ key: toSourceBabelTS(typeArguments[0]),
2136
+ val: toSourceBabelTS(typeArguments[1])
2137
+ };
2138
+ } else if (name === 'Array' && (typeArguments == null ? void 0 : typeArguments.length) === 1) {
2139
+ const elementType = toSourceBabelTS(typeArguments[0]);
2140
+ return {
2141
+ type: 'array',
2142
+ elementType
2143
+ };
2144
+ } else if (name === 'Set' && (typeArguments == null ? void 0 : typeArguments.length) === 1) {
2145
+ const elementType = toSourceBabelTS(typeArguments[0]);
2146
+ return {
2147
+ type: 'set',
2148
+ elementType
2149
+ };
2150
+ } else if (name === 'Class' && (typeArguments == null ? void 0 : typeArguments.length) === 1) {
2151
+ return {
2152
+ type: 'class',
2153
+ elementType: toSourceBabelTS(typeArguments[0])
2154
+ };
2155
+ } else {
2156
+ if (!typeArguments) {
2157
+ return typeName.name;
2158
+ }
2159
+ console.warn('unhandled TypeReference', kind_, node);
2160
+ return {
2161
+ type: 'unhandled TypeReference'
2162
+ };
2163
+ }
2164
+ }
2165
+ case 'TSStringKeyword':
2166
+ return 'string';
2167
+ case 'TSNumberKeyword':
2168
+ return 'number';
2169
+ case 'TSIntersectionType':
2170
+ return {
2171
+ type: 'intersection',
2172
+ members: node.types.map(toSourceBabelTS)
2173
+ };
2174
+ case 'TSTupleType':
2175
+ return {
2176
+ type: 'tuple',
2177
+ elements: node.elementTypes.map(toSourceBabelTS)
2178
+ };
2179
+ case 'TSUnionType':
2180
+ return {
2181
+ type: 'union',
2182
+ members: node.types.map(toSourceBabelTS)
2183
+ };
2184
+ case 'TypeLiteral':
2185
+ const properties = {};
2186
+ node.members.forEach(member => {
2187
+ const name = toSourceBabelTS(member.name);
2188
+ const type = toSourceBabelTS(member.type);
2189
+ properties[name] = type;
2190
+ });
2191
+ return {
2192
+ type: 'object',
2193
+ properties
2194
+ };
2195
+ case 'Identifier':
2196
+ return node.name;
2197
+ case 'TSArrayType':
2198
+ return {
2199
+ type: 'array',
2200
+ elementType: toSourceBabelTS(node.elementType)
2201
+ };
2202
+ case 'TSLiteralType':
2203
+ return toSourceBabelTS(node.literal);
2204
+ case 'TSAnyKeyword':
2205
+ return 'any';
2206
+ case 'TSBooleanKeyword':
2207
+ return 'boolean';
2208
+ case 'BooleanLiteral':
2209
+ return node.value.toString();
2210
+ case 'TSNullKeyword':
2211
+ return 'null';
2212
+ case 'NumericLiteral':
2213
+ case 'StringLiteral':
2214
+ return node.extra.raw;
2215
+ case 'TSUndefinedKeyword':
2216
+ return 'undefined';
2217
+ case 'TSVoidKeyword':
2218
+ return 'void';
2219
+ case 'TSThisType':
2220
+ return 'this';
2221
+ case 'ObjectKeyword':
2222
+ return {
2223
+ type: 'object',
2224
+ properties: {}
2225
+ };
2226
+ case 'ParenthesizedType':
2227
+ return toSourceBabelTS(node.type);
2228
+ case 'LastTypeNode':
2229
+ return toSourceBabelTS(node.qualifier);
2230
+ default:
2231
+ console.warn('toSourceBabelTS> unhandled type', node.type, node);
2232
+ debugger;
2233
+ }
2234
+ }
2235
+
2236
+ export { Asserter, Stringifier, addTypeChecks, ast2json, ast2jsonForComparison, code2ast2code, expandType, expandTypeBabelTS, expandTypeDepFree, extractCurlyContent, extractNameAndOptionality, nodeIsFunction, parseJSDoc, parseJSDocSetter, parseJSDocTypedef, parseType, parseTypeBabelTS, simplifyType, toSourceBabelTS, toSourceTS, trimEndSpaces };