@runtime-type-inspector/transpiler 3.3.7 → 4.0.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/index.cjs +357 -29
- package/index.mjs +333 -30
- package/package.json +2 -2
package/index.cjs
CHANGED
|
@@ -320,11 +320,14 @@
|
|
|
320
320
|
* This function handles various TypeScript AST node types and converts them into a string
|
|
321
321
|
* or an object representing the type.
|
|
322
322
|
*
|
|
323
|
-
* @param {ts.TypeNode|ts.Identifier} node - The TypeScript AST node to convert.
|
|
323
|
+
* @param {ts.TypeNode|ts.Identifier|ts.QualifiedName|undefined} node - The TypeScript AST node to convert.
|
|
324
324
|
* @returns {string | number | boolean | {type: string, [key: string]: any} | undefined} The source string/number,
|
|
325
325
|
* or an object with type information based on the node, or `undefined` if the node kind is not handled.
|
|
326
326
|
*/
|
|
327
327
|
function toSourceTS(node) {
|
|
328
|
+
if (!node) {
|
|
329
|
+
return 'undefined';
|
|
330
|
+
}
|
|
328
331
|
var typeArguments = node.typeArguments,
|
|
329
332
|
typeName = node.typeName;
|
|
330
333
|
var kind_ = ts.SyntaxKind[node.kind];
|
|
@@ -333,6 +336,7 @@
|
|
|
333
336
|
ArrayType = _ts$SyntaxKind.ArrayType,
|
|
334
337
|
BooleanKeyword = _ts$SyntaxKind.BooleanKeyword,
|
|
335
338
|
FunctionType = _ts$SyntaxKind.FunctionType,
|
|
339
|
+
JSDocFunctionType = _ts$SyntaxKind.JSDocFunctionType,
|
|
336
340
|
Identifier = _ts$SyntaxKind.Identifier,
|
|
337
341
|
IntersectionType = _ts$SyntaxKind.IntersectionType,
|
|
338
342
|
JSDocAllType = _ts$SyntaxKind.JSDocAllType,
|
|
@@ -371,7 +375,8 @@
|
|
|
371
375
|
ConstructorType = _ts$SyntaxKind.ConstructorType,
|
|
372
376
|
NamedTupleMember = _ts$SyntaxKind.NamedTupleMember,
|
|
373
377
|
MappedType = _ts$SyntaxKind.MappedType,
|
|
374
|
-
TypeParameter = _ts$SyntaxKind.TypeParameter
|
|
378
|
+
TypeParameter = _ts$SyntaxKind.TypeParameter,
|
|
379
|
+
QualifiedName = _ts$SyntaxKind.QualifiedName;
|
|
375
380
|
// console.log({typeArguments, typeName, kind_, node});
|
|
376
381
|
switch (node.kind) {
|
|
377
382
|
case BigIntKeyword:
|
|
@@ -410,23 +415,36 @@
|
|
|
410
415
|
if (!ts.isConstructorTypeNode(node)) {
|
|
411
416
|
throw Error("Impossible");
|
|
412
417
|
}
|
|
413
|
-
var
|
|
418
|
+
var parameters = node.parameters.map(toSourceTS);
|
|
414
419
|
var _ret = toSourceTS(node.type);
|
|
415
420
|
return {
|
|
416
421
|
type: 'new',
|
|
417
|
-
parameters:
|
|
422
|
+
parameters: parameters,
|
|
418
423
|
ret: _ret
|
|
419
424
|
};
|
|
420
425
|
}
|
|
421
426
|
case FunctionType:
|
|
422
|
-
|
|
423
|
-
|
|
427
|
+
{
|
|
428
|
+
if (!ts.isFunctionTypeNode(node)) {
|
|
429
|
+
throw Error("Impossible");
|
|
430
|
+
}
|
|
431
|
+
var _parameters = node.parameters.map(toSourceTS);
|
|
432
|
+
return {
|
|
433
|
+
type: 'function',
|
|
434
|
+
parameters: _parameters
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
case JSDocFunctionType:
|
|
438
|
+
{
|
|
439
|
+
if (!ts.isJSDocFunctionType(node)) {
|
|
440
|
+
throw Error("Impossible");
|
|
441
|
+
}
|
|
442
|
+
var _parameters2 = node.parameters.map(toSourceTS);
|
|
443
|
+
return {
|
|
444
|
+
type: 'function',
|
|
445
|
+
parameters: _parameters2
|
|
446
|
+
};
|
|
424
447
|
}
|
|
425
|
-
var parameters = node.parameters.map(toSourceTS);
|
|
426
|
-
return {
|
|
427
|
-
type: 'function',
|
|
428
|
-
parameters: parameters
|
|
429
|
-
};
|
|
430
448
|
case IndexedAccessType:
|
|
431
449
|
if (!ts.isIndexedAccessTypeNode(node)) {
|
|
432
450
|
throw Error("Impossible");
|
|
@@ -721,6 +739,14 @@
|
|
|
721
739
|
}
|
|
722
740
|
// fall-through for parentheses
|
|
723
741
|
return toSourceTS(node.type);
|
|
742
|
+
// toSourceTS(parseType("import('abc').x.y.z"))
|
|
743
|
+
case QualifiedName:
|
|
744
|
+
if (!ts.isQualifiedName(node)) {
|
|
745
|
+
throw Error("Impossible");
|
|
746
|
+
}
|
|
747
|
+
var l = toSourceTS(node.left);
|
|
748
|
+
var r = toSourceTS(node.right);
|
|
749
|
+
return "".concat(l, ".").concat(r);
|
|
724
750
|
case ImportType:
|
|
725
751
|
if (!ts.isImportTypeNode(node)) {
|
|
726
752
|
throw Error("Impossible");
|
|
@@ -1235,6 +1261,16 @@
|
|
|
1235
1261
|
stat.unchecked = 0;
|
|
1236
1262
|
}
|
|
1237
1263
|
|
|
1264
|
+
/**
|
|
1265
|
+
* @example
|
|
1266
|
+
* capitalize("hello"); // Outputs: Hello
|
|
1267
|
+
* @param {string} _ - The input string.
|
|
1268
|
+
* @returns {string} The capitalized output string.
|
|
1269
|
+
*/
|
|
1270
|
+
function capitalize(_) {
|
|
1271
|
+
return _[0].toUpperCase() + _.slice(1);
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1238
1274
|
/**
|
|
1239
1275
|
* @example
|
|
1240
1276
|
* trimEndSpaces('test \n '); // Returns: 'test \n'
|
|
@@ -1263,8 +1299,13 @@
|
|
|
1263
1299
|
_defineProperty(this, "forceCurly", false);
|
|
1264
1300
|
/** @type {Node[]} */
|
|
1265
1301
|
_defineProperty(this, "parents", []);
|
|
1302
|
+
/**
|
|
1303
|
+
* If we encounter JSX elements, we add React's createElement as import.
|
|
1304
|
+
*/
|
|
1305
|
+
_defineProperty(this, "addReactImport", false);
|
|
1266
1306
|
_defineProperty(this, "lastCommentBlockIndex", -1);
|
|
1267
1307
|
_defineProperty(this, "lastCommentLineIndex", -1);
|
|
1308
|
+
_defineProperty(this, "encounteredFragment", false);
|
|
1268
1309
|
_defineProperty(this, "numSpaces", 0);
|
|
1269
1310
|
}
|
|
1270
1311
|
_createClass(Stringifier, [{
|
|
@@ -1519,6 +1560,21 @@
|
|
|
1519
1560
|
}
|
|
1520
1561
|
return out;
|
|
1521
1562
|
}
|
|
1563
|
+
}, {
|
|
1564
|
+
key: "getHeader",
|
|
1565
|
+
value:
|
|
1566
|
+
/**
|
|
1567
|
+
* @returns {string} The header.
|
|
1568
|
+
*/
|
|
1569
|
+
function getHeader() {
|
|
1570
|
+
if (!this.addReactImport) {
|
|
1571
|
+
return '';
|
|
1572
|
+
}
|
|
1573
|
+
if (this.encounteredFragment) {
|
|
1574
|
+
return "import {createElement, Fragment} from 'react';\n";
|
|
1575
|
+
}
|
|
1576
|
+
return "import {createElement} from 'react';\n";
|
|
1577
|
+
}
|
|
1522
1578
|
}, {
|
|
1523
1579
|
key: "parent",
|
|
1524
1580
|
get: function get() {
|
|
@@ -1901,7 +1957,10 @@
|
|
|
1901
1957
|
out += ' * ';
|
|
1902
1958
|
}
|
|
1903
1959
|
out += this.FunctionDeclarationParams(params);
|
|
1904
|
-
out += ' =>
|
|
1960
|
+
out += ' =>';
|
|
1961
|
+
if (body.type !== 'BlockStatement') {
|
|
1962
|
+
out += ' ';
|
|
1963
|
+
}
|
|
1905
1964
|
out += this.toSource(body);
|
|
1906
1965
|
return out;
|
|
1907
1966
|
}
|
|
@@ -2535,6 +2594,219 @@
|
|
|
2535
2594
|
// createMesh: createMesh$1\n
|
|
2536
2595
|
return "".concat(spaces).concat(right, " as ").concat(left);
|
|
2537
2596
|
}
|
|
2597
|
+
/**
|
|
2598
|
+
* @param {import("@babel/types").JSXAttribute} node - The Babel AST node.
|
|
2599
|
+
* @returns {string} Stringification of the node.
|
|
2600
|
+
*/
|
|
2601
|
+
}, {
|
|
2602
|
+
key: "JSXAttribute",
|
|
2603
|
+
value: function JSXAttribute(node) {
|
|
2604
|
+
var name = node.name,
|
|
2605
|
+
value = node.value;
|
|
2606
|
+
// console.log("JSXAttribute", {name, value});
|
|
2607
|
+
var keySource = this.toSource(name);
|
|
2608
|
+
// E.g. <audio controls/>
|
|
2609
|
+
if (value === null) {
|
|
2610
|
+
return "".concat(this.spaces).concat(keySource, ": true");
|
|
2611
|
+
}
|
|
2612
|
+
var valSource = this.toSource(value);
|
|
2613
|
+
if (keySource === valSource) {
|
|
2614
|
+
return this.spaces + keySource;
|
|
2615
|
+
}
|
|
2616
|
+
return "".concat(this.spaces).concat(keySource, ": ").concat(valSource);
|
|
2617
|
+
}
|
|
2618
|
+
/**
|
|
2619
|
+
* @param {import("@babel/types").JSXElement} node - The Babel AST node.
|
|
2620
|
+
* @returns {string} Stringification of the node.
|
|
2621
|
+
*/
|
|
2622
|
+
}, {
|
|
2623
|
+
key: "JSXElement",
|
|
2624
|
+
value: function JSXElement(node) {
|
|
2625
|
+
var _this4 = this;
|
|
2626
|
+
this.addReactImport = true;
|
|
2627
|
+
var openingElement = node.openingElement;
|
|
2628
|
+
node.closingElement;
|
|
2629
|
+
var children = node.children;
|
|
2630
|
+
// console.log("JSXElement", {openingElement, closingElement, children});
|
|
2631
|
+
if (openingElement.type !== 'JSXOpeningElement') {
|
|
2632
|
+
debugger;
|
|
2633
|
+
}
|
|
2634
|
+
var spaces = this.spaces;
|
|
2635
|
+
var name = openingElement.name,
|
|
2636
|
+
attributes = openingElement.attributes;
|
|
2637
|
+
var out = '';
|
|
2638
|
+
out += 'createElement(';
|
|
2639
|
+
this.numSpaces++;
|
|
2640
|
+
spaces = this.spaces;
|
|
2641
|
+
out += '\n';
|
|
2642
|
+
out += spaces;
|
|
2643
|
+
var sourceName = this.toSource(name);
|
|
2644
|
+
if (sourceName[0] === sourceName[0].toLowerCase()) {
|
|
2645
|
+
// If something like 'div', it has to become "'div'"
|
|
2646
|
+
sourceName = JSON.stringify(sourceName);
|
|
2647
|
+
}
|
|
2648
|
+
out += sourceName;
|
|
2649
|
+
out += ',';
|
|
2650
|
+
if (attributes.length) {
|
|
2651
|
+
out += '\n';
|
|
2652
|
+
out += spaces;
|
|
2653
|
+
out += '{\n';
|
|
2654
|
+
this.numSpaces++;
|
|
2655
|
+
out += attributes.map(function (attr) {
|
|
2656
|
+
return _this4.toSource(attr) + ',\n';
|
|
2657
|
+
}).join('');
|
|
2658
|
+
this.numSpaces--;
|
|
2659
|
+
out += spaces;
|
|
2660
|
+
out += '}';
|
|
2661
|
+
} else {
|
|
2662
|
+
out += '\n';
|
|
2663
|
+
out += spaces;
|
|
2664
|
+
out += 'null';
|
|
2665
|
+
}
|
|
2666
|
+
if (children.length) {
|
|
2667
|
+
out += ',\n';
|
|
2668
|
+
var _iterator2 = _createForOfIteratorHelper(children),
|
|
2669
|
+
_step2;
|
|
2670
|
+
try {
|
|
2671
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
2672
|
+
var child = _step2.value;
|
|
2673
|
+
var source = this.toSource(child);
|
|
2674
|
+
if (!source.length) {
|
|
2675
|
+
continue;
|
|
2676
|
+
}
|
|
2677
|
+
out += spaces;
|
|
2678
|
+
out += source;
|
|
2679
|
+
out += ',\n';
|
|
2680
|
+
}
|
|
2681
|
+
} catch (err) {
|
|
2682
|
+
_iterator2.e(err);
|
|
2683
|
+
} finally {
|
|
2684
|
+
_iterator2.f();
|
|
2685
|
+
}
|
|
2686
|
+
} else {
|
|
2687
|
+
out += '\n';
|
|
2688
|
+
}
|
|
2689
|
+
this.numSpaces--;
|
|
2690
|
+
out += this.spaces;
|
|
2691
|
+
out += ')';
|
|
2692
|
+
return out;
|
|
2693
|
+
}
|
|
2694
|
+
/**
|
|
2695
|
+
* @param {import("@babel/types").JSXFragment} node - The Babel AST node.
|
|
2696
|
+
* @returns {string} Stringification of the node.
|
|
2697
|
+
*/
|
|
2698
|
+
}, {
|
|
2699
|
+
key: "JSXFragment",
|
|
2700
|
+
value: function JSXFragment(node) {
|
|
2701
|
+
var children = node.children;
|
|
2702
|
+
this.encounteredFragment = true;
|
|
2703
|
+
// console.log('JSXFragment', {openingFragment, closingFragment, children});
|
|
2704
|
+
var spaces = this.spaces;
|
|
2705
|
+
var out = 'createElement(\n';
|
|
2706
|
+
this.numSpaces++;
|
|
2707
|
+
spaces = this.spaces;
|
|
2708
|
+
out += spaces;
|
|
2709
|
+
out += 'Fragment,\n';
|
|
2710
|
+
out += spaces;
|
|
2711
|
+
out += 'null';
|
|
2712
|
+
// Same code for children as in JSXElement
|
|
2713
|
+
if (children.length) {
|
|
2714
|
+
out += ',\n';
|
|
2715
|
+
var _iterator3 = _createForOfIteratorHelper(children),
|
|
2716
|
+
_step3;
|
|
2717
|
+
try {
|
|
2718
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
2719
|
+
var child = _step3.value;
|
|
2720
|
+
var source = this.toSource(child);
|
|
2721
|
+
if (!source.length) {
|
|
2722
|
+
continue;
|
|
2723
|
+
}
|
|
2724
|
+
out += spaces;
|
|
2725
|
+
out += source;
|
|
2726
|
+
out += ',\n';
|
|
2727
|
+
}
|
|
2728
|
+
} catch (err) {
|
|
2729
|
+
_iterator3.e(err);
|
|
2730
|
+
} finally {
|
|
2731
|
+
_iterator3.f();
|
|
2732
|
+
}
|
|
2733
|
+
} else {
|
|
2734
|
+
out += '\n';
|
|
2735
|
+
}
|
|
2736
|
+
this.numSpaces--;
|
|
2737
|
+
out += this.spaces;
|
|
2738
|
+
out += ')';
|
|
2739
|
+
return out;
|
|
2740
|
+
}
|
|
2741
|
+
/**
|
|
2742
|
+
* @param {import("@babel/types").JSXIdentifier} node - The Babel AST node.
|
|
2743
|
+
* @returns {string} Stringification of the node.
|
|
2744
|
+
*/
|
|
2745
|
+
}, {
|
|
2746
|
+
key: "JSXIdentifier",
|
|
2747
|
+
value: function JSXIdentifier(node) {
|
|
2748
|
+
var name = node.name;
|
|
2749
|
+
// console.log('JSXIdentifier', {name});
|
|
2750
|
+
// https://github.com/kungfooman/RuntimeTypeInspector.js/issues/201
|
|
2751
|
+
// https://stackoverflow.com/questions/38998987/using-aria-attributes-on-elements-in-react
|
|
2752
|
+
if (name.includes('-')) {
|
|
2753
|
+
return JSON.stringify(name);
|
|
2754
|
+
}
|
|
2755
|
+
return name;
|
|
2756
|
+
}
|
|
2757
|
+
/**
|
|
2758
|
+
* @param {import("@babel/types").JSXNamespacedName} node - The Babel AST node.
|
|
2759
|
+
* @returns {string} Stringification of the node.
|
|
2760
|
+
*/
|
|
2761
|
+
}, {
|
|
2762
|
+
key: "JSXNamespacedName",
|
|
2763
|
+
value: function JSXNamespacedName(node) {
|
|
2764
|
+
var namespace = node.namespace,
|
|
2765
|
+
name = node.name;
|
|
2766
|
+
var a = this.toSource(namespace);
|
|
2767
|
+
var b = capitalize(this.toSource(name));
|
|
2768
|
+
return a + b;
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* @param {import("@babel/types").JSXExpressionContainer} node - The Babel AST node.
|
|
2772
|
+
* @returns {string} Stringification of the node.
|
|
2773
|
+
*/
|
|
2774
|
+
}, {
|
|
2775
|
+
key: "JSXExpressionContainer",
|
|
2776
|
+
value: function JSXExpressionContainer(node) {
|
|
2777
|
+
var expression = node.expression;
|
|
2778
|
+
// console.log('JSXExpressionContainer', {expression});
|
|
2779
|
+
return this.toSource(expression);
|
|
2780
|
+
}
|
|
2781
|
+
/**
|
|
2782
|
+
* @param {import("@babel/types").JSXMemberExpression} node - The Babel AST node.
|
|
2783
|
+
* @returns {string} Stringification of the node.
|
|
2784
|
+
*/
|
|
2785
|
+
}, {
|
|
2786
|
+
key: "JSXMemberExpression",
|
|
2787
|
+
value: function JSXMemberExpression(node) {
|
|
2788
|
+
var object = node.object,
|
|
2789
|
+
property = node.property;
|
|
2790
|
+
// console.log('JSXMemberExpression', 'object', object, 'property', property);
|
|
2791
|
+
var o = this.toSource(object);
|
|
2792
|
+
var p = this.toSource(property);
|
|
2793
|
+
return "".concat(o, ".").concat(p);
|
|
2794
|
+
}
|
|
2795
|
+
/**
|
|
2796
|
+
* @param {import("@babel/types").JSXText} node - The Babel AST node.
|
|
2797
|
+
* @returns {string} Stringification of the node.
|
|
2798
|
+
*/
|
|
2799
|
+
}, {
|
|
2800
|
+
key: "JSXText",
|
|
2801
|
+
value: function JSXText(node) {
|
|
2802
|
+
node.extra;
|
|
2803
|
+
var value = node.value;
|
|
2804
|
+
// console.log('JSXText', {extra, value});
|
|
2805
|
+
if (!value.trim().length) {
|
|
2806
|
+
return '';
|
|
2807
|
+
}
|
|
2808
|
+
return JSON.stringify(value);
|
|
2809
|
+
}
|
|
2538
2810
|
/**
|
|
2539
2811
|
* @param {import("@babel/types").Super} node - The Babel AST node.
|
|
2540
2812
|
* @returns {string} Stringification of the node.
|
|
@@ -2927,6 +3199,22 @@
|
|
|
2927
3199
|
value: function Import(node) {
|
|
2928
3200
|
return 'import';
|
|
2929
3201
|
}
|
|
3202
|
+
/**
|
|
3203
|
+
* @param {import("@babel/types").ImportExpression} node - The Babel AST node.
|
|
3204
|
+
* @returns {string} Stringification of the node.
|
|
3205
|
+
*/
|
|
3206
|
+
}, {
|
|
3207
|
+
key: "ImportExpression",
|
|
3208
|
+
value: function ImportExpression(node) {
|
|
3209
|
+
var source = node.source,
|
|
3210
|
+
options = node.options;
|
|
3211
|
+
var out = "import(" + this.toSource(source);
|
|
3212
|
+
if (options) {
|
|
3213
|
+
out += ', ' + this.toSource(options);
|
|
3214
|
+
}
|
|
3215
|
+
out += ')';
|
|
3216
|
+
return out;
|
|
3217
|
+
}
|
|
2930
3218
|
/**
|
|
2931
3219
|
* @param {import("@babel/types").ImportDeclaration} node - The Babel AST node.
|
|
2932
3220
|
* @returns {string} Stringification of the node.
|
|
@@ -2939,15 +3227,39 @@
|
|
|
2939
3227
|
// ImportNamespaceSpecifier: import * as a from "b";
|
|
2940
3228
|
// ImportDefaultSpecifier : import a from "b";
|
|
2941
3229
|
// ImportSpecifier : import { a } from "b";
|
|
2942
|
-
var
|
|
2943
|
-
var b = this.toSource(source);
|
|
3230
|
+
var from = this.toSource(source);
|
|
2944
3231
|
if (specifiers.length === 0) {
|
|
2945
|
-
return "import ".concat(
|
|
3232
|
+
return "import ".concat(from);
|
|
2946
3233
|
}
|
|
2947
|
-
|
|
2948
|
-
|
|
3234
|
+
var out = 'import ';
|
|
3235
|
+
var n = specifiers.length;
|
|
3236
|
+
var inImportSpecifier = false;
|
|
3237
|
+
var i = 0;
|
|
3238
|
+
var _iterator4 = _createForOfIteratorHelper(specifiers),
|
|
3239
|
+
_step4;
|
|
3240
|
+
try {
|
|
3241
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
3242
|
+
var specifier = _step4.value;
|
|
3243
|
+
if (specifier.type === 'ImportSpecifier' && !inImportSpecifier) {
|
|
3244
|
+
out += "{";
|
|
3245
|
+
inImportSpecifier = true;
|
|
3246
|
+
}
|
|
3247
|
+
out += this.toSource(specifier);
|
|
3248
|
+
if (i !== n - 1) {
|
|
3249
|
+
out += ', ';
|
|
3250
|
+
}
|
|
3251
|
+
i++;
|
|
3252
|
+
}
|
|
3253
|
+
} catch (err) {
|
|
3254
|
+
_iterator4.e(err);
|
|
3255
|
+
} finally {
|
|
3256
|
+
_iterator4.f();
|
|
2949
3257
|
}
|
|
2950
|
-
|
|
3258
|
+
if (inImportSpecifier) {
|
|
3259
|
+
out += '}';
|
|
3260
|
+
}
|
|
3261
|
+
out += " from ".concat(from, ";");
|
|
3262
|
+
return out;
|
|
2951
3263
|
}
|
|
2952
3264
|
/**
|
|
2953
3265
|
* @param {import("@babel/types").ImportSpecifier} node - The Babel AST node.
|
|
@@ -3216,7 +3528,11 @@
|
|
|
3216
3528
|
} else {
|
|
3217
3529
|
out += ' {\n';
|
|
3218
3530
|
out += this.generateTypeChecks(node);
|
|
3531
|
+
var spaces = this.spaces;
|
|
3532
|
+
this.numSpaces++;
|
|
3219
3533
|
out += this.spaces + 'return ' + this.toSource(body) + ';\n';
|
|
3534
|
+
this.numSpaces--;
|
|
3535
|
+
out += spaces;
|
|
3220
3536
|
out += '}';
|
|
3221
3537
|
}
|
|
3222
3538
|
return out;
|
|
@@ -3262,6 +3578,7 @@
|
|
|
3262
3578
|
* @todo
|
|
3263
3579
|
* Once we went over every node, we can see if we really require registerTypef, registerClass etc.
|
|
3264
3580
|
* @returns {string} The import declaration header for importing RTI.
|
|
3581
|
+
* @override
|
|
3265
3582
|
*/
|
|
3266
3583
|
}, {
|
|
3267
3584
|
key: "getHeader",
|
|
@@ -3269,7 +3586,8 @@
|
|
|
3269
3586
|
if (!this.addHeader) {
|
|
3270
3587
|
return '';
|
|
3271
3588
|
}
|
|
3272
|
-
var header =
|
|
3589
|
+
var header = _get(_getPrototypeOf(Asserter.prototype), "getHeader", this).call(this);
|
|
3590
|
+
header += "import {inspectType, inspectTypeWithTemplates, youCanAddABreakpointHere, registerVariable";
|
|
3273
3591
|
if (this.validateDivision) {
|
|
3274
3592
|
header += ", validateDivision";
|
|
3275
3593
|
}
|
|
@@ -4001,6 +4319,17 @@
|
|
|
4001
4319
|
return Asserter;
|
|
4002
4320
|
}(Stringifier);
|
|
4003
4321
|
|
|
4322
|
+
/**
|
|
4323
|
+
* We use the same options in different places, so it's nice to keep them in sync without
|
|
4324
|
+
* changing them in multiple locations.
|
|
4325
|
+
* @type {import('@babel/parser').ParserOptions}
|
|
4326
|
+
*/
|
|
4327
|
+
var parserOptions = {
|
|
4328
|
+
sourceType: 'module',
|
|
4329
|
+
createParenthesizedExpressions: true,
|
|
4330
|
+
plugins: ['jsx']
|
|
4331
|
+
};
|
|
4332
|
+
|
|
4004
4333
|
/**
|
|
4005
4334
|
* Simple facade which does all the processing. Processes the input
|
|
4006
4335
|
* source string, adding runtime type checks based on JSDoc comments.
|
|
@@ -4020,11 +4349,10 @@
|
|
|
4020
4349
|
function addTypeChecks(src, options) {
|
|
4021
4350
|
try {
|
|
4022
4351
|
var asserter = new Asserter(options);
|
|
4023
|
-
var ast = parser.parse(src,
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
var out = asserter.getHeader() + asserter.toSource(ast);
|
|
4352
|
+
var ast = parser.parse(src, parserOptions);
|
|
4353
|
+
// Must be called before getHeader since it's keeping an eye open for JSX elements.
|
|
4354
|
+
var source = asserter.toSource(ast);
|
|
4355
|
+
var out = asserter.getHeader() + source;
|
|
4028
4356
|
return out;
|
|
4029
4357
|
} catch (e) {
|
|
4030
4358
|
console.error(e);
|
|
@@ -4072,15 +4400,13 @@
|
|
|
4072
4400
|
* @returns {string | undefined} The new and once parsed and stringified code.
|
|
4073
4401
|
*/
|
|
4074
4402
|
function code2ast2code(code) {
|
|
4075
|
-
var
|
|
4076
|
-
var ast = parser.parse(code, {
|
|
4077
|
-
sourceType: 'module'
|
|
4078
|
-
});
|
|
4403
|
+
var ast = parser.parse(code, parserOptions);
|
|
4079
4404
|
if (!ast) {
|
|
4080
4405
|
return;
|
|
4081
4406
|
}
|
|
4407
|
+
var stringifier = new Stringifier();
|
|
4082
4408
|
var out = stringifier.toSource(ast);
|
|
4083
|
-
return out;
|
|
4409
|
+
return stringifier.getHeader() + out;
|
|
4084
4410
|
}
|
|
4085
4411
|
|
|
4086
4412
|
/**
|
|
@@ -4347,6 +4673,7 @@
|
|
|
4347
4673
|
exports.addTypeChecks = addTypeChecks;
|
|
4348
4674
|
exports.ast2json = ast2json;
|
|
4349
4675
|
exports.ast2jsonForComparison = ast2jsonForComparison;
|
|
4676
|
+
exports.capitalize = capitalize;
|
|
4350
4677
|
exports.code2ast2code = code2ast2code;
|
|
4351
4678
|
exports.compareAST = compareAST;
|
|
4352
4679
|
exports.expandType = expandType;
|
|
@@ -4361,6 +4688,7 @@
|
|
|
4361
4688
|
exports.parseJSDocTypedef = parseJSDocTypedef;
|
|
4362
4689
|
exports.parseType = parseType;
|
|
4363
4690
|
exports.parseTypeBabelTS = parseTypeBabelTS;
|
|
4691
|
+
exports.parserOptions = parserOptions;
|
|
4364
4692
|
exports.requiredTypeofs = requiredTypeofs;
|
|
4365
4693
|
exports.simplifyType = simplifyType;
|
|
4366
4694
|
exports.toSourceBabelTS = toSourceBabelTS;
|
package/index.mjs
CHANGED
|
@@ -63,11 +63,14 @@ const requiredTypeofs = {};
|
|
|
63
63
|
* This function handles various TypeScript AST node types and converts them into a string
|
|
64
64
|
* or an object representing the type.
|
|
65
65
|
*
|
|
66
|
-
* @param {ts.TypeNode|ts.Identifier} node - The TypeScript AST node to convert.
|
|
66
|
+
* @param {ts.TypeNode|ts.Identifier|ts.QualifiedName|undefined} node - The TypeScript AST node to convert.
|
|
67
67
|
* @returns {string | number | boolean | {type: string, [key: string]: any} | undefined} The source string/number,
|
|
68
68
|
* or an object with type information based on the node, or `undefined` if the node kind is not handled.
|
|
69
69
|
*/
|
|
70
70
|
function toSourceTS(node) {
|
|
71
|
+
if (!node) {
|
|
72
|
+
return 'undefined';
|
|
73
|
+
}
|
|
71
74
|
const {
|
|
72
75
|
typeArguments,
|
|
73
76
|
typeName
|
|
@@ -82,6 +85,8 @@ function toSourceTS(node) {
|
|
|
82
85
|
// parseType("boolean" ).kind === ts.SyntaxKind.BooleanKeyword
|
|
83
86
|
FunctionType,
|
|
84
87
|
// parseType("() => void" ).kind === ts.SyntaxKind.FunctionType
|
|
88
|
+
JSDocFunctionType,
|
|
89
|
+
// parseType("function (number, number): number").kind === ts.SyntaxKind.JSDocFunctionType
|
|
85
90
|
Identifier,
|
|
86
91
|
// parseType("{a: 1, b: 2}" ).members[0].name.kind === ts.SyntaxKind.Identifier
|
|
87
92
|
IntersectionType,
|
|
@@ -158,7 +163,9 @@ function toSourceTS(node) {
|
|
|
158
163
|
// parseType('[a: 1]' ).elements[0].kind === ts.SyntaxKind.NamedTupleMember
|
|
159
164
|
MappedType,
|
|
160
165
|
// parseType('{[K in TaskType]: 123}' ).kind === ts.SyntaxKind.MappedType
|
|
161
|
-
TypeParameter
|
|
166
|
+
TypeParameter,
|
|
167
|
+
// parseType('{[K in TaskType]: 123}' ).typeParameter.kind === ts.SyntaxKind.TypeParameter
|
|
168
|
+
QualifiedName // parseType("import('abc').x.y" ).qualifier.kind === ts.SyntaxKind.QualifiedName
|
|
162
169
|
} = ts.SyntaxKind;
|
|
163
170
|
// console.log({typeArguments, typeName, kind_, node});
|
|
164
171
|
switch (node.kind) {
|
|
@@ -198,23 +205,36 @@ function toSourceTS(node) {
|
|
|
198
205
|
if (!ts.isConstructorTypeNode(node)) {
|
|
199
206
|
throw Error("Impossible");
|
|
200
207
|
}
|
|
201
|
-
const
|
|
208
|
+
const parameters = node.parameters.map(toSourceTS);
|
|
202
209
|
const _ret = toSourceTS(node.type);
|
|
203
210
|
return {
|
|
204
211
|
type: 'new',
|
|
205
|
-
parameters
|
|
212
|
+
parameters,
|
|
206
213
|
ret: _ret
|
|
207
214
|
};
|
|
208
215
|
}
|
|
209
216
|
case FunctionType:
|
|
210
|
-
|
|
211
|
-
|
|
217
|
+
{
|
|
218
|
+
if (!ts.isFunctionTypeNode(node)) {
|
|
219
|
+
throw Error("Impossible");
|
|
220
|
+
}
|
|
221
|
+
const parameters = node.parameters.map(toSourceTS);
|
|
222
|
+
return {
|
|
223
|
+
type: 'function',
|
|
224
|
+
parameters
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
case JSDocFunctionType:
|
|
228
|
+
{
|
|
229
|
+
if (!ts.isJSDocFunctionType(node)) {
|
|
230
|
+
throw Error("Impossible");
|
|
231
|
+
}
|
|
232
|
+
const parameters = node.parameters.map(toSourceTS);
|
|
233
|
+
return {
|
|
234
|
+
type: 'function',
|
|
235
|
+
parameters
|
|
236
|
+
};
|
|
212
237
|
}
|
|
213
|
-
const parameters = node.parameters.map(toSourceTS);
|
|
214
|
-
return {
|
|
215
|
-
type: 'function',
|
|
216
|
-
parameters
|
|
217
|
-
};
|
|
218
238
|
case IndexedAccessType:
|
|
219
239
|
if (!ts.isIndexedAccessTypeNode(node)) {
|
|
220
240
|
throw Error("Impossible");
|
|
@@ -509,6 +529,14 @@ function toSourceTS(node) {
|
|
|
509
529
|
}
|
|
510
530
|
// fall-through for parentheses
|
|
511
531
|
return toSourceTS(node.type);
|
|
532
|
+
// toSourceTS(parseType("import('abc').x.y.z"))
|
|
533
|
+
case QualifiedName:
|
|
534
|
+
if (!ts.isQualifiedName(node)) {
|
|
535
|
+
throw Error("Impossible");
|
|
536
|
+
}
|
|
537
|
+
const l = toSourceTS(node.left);
|
|
538
|
+
const r = toSourceTS(node.right);
|
|
539
|
+
return `${l}.${r}`;
|
|
512
540
|
case ImportType:
|
|
513
541
|
if (!ts.isImportTypeNode(node)) {
|
|
514
542
|
throw Error("Impossible");
|
|
@@ -994,6 +1022,16 @@ function statReset(stat) {
|
|
|
994
1022
|
stat.unchecked = 0;
|
|
995
1023
|
}
|
|
996
1024
|
|
|
1025
|
+
/**
|
|
1026
|
+
* @example
|
|
1027
|
+
* capitalize("hello"); // Outputs: Hello
|
|
1028
|
+
* @param {string} _ - The input string.
|
|
1029
|
+
* @returns {string} The capitalized output string.
|
|
1030
|
+
*/
|
|
1031
|
+
function capitalize(_) {
|
|
1032
|
+
return _[0].toUpperCase() + _.slice(1);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
997
1035
|
/**
|
|
998
1036
|
* @example
|
|
999
1037
|
* trimEndSpaces('test \n '); // Returns: 'test \n'
|
|
@@ -1021,8 +1059,13 @@ class Stringifier {
|
|
|
1021
1059
|
this.forceCurly = false;
|
|
1022
1060
|
/** @type {Node[]} */
|
|
1023
1061
|
this.parents = [];
|
|
1062
|
+
/**
|
|
1063
|
+
* If we encounter JSX elements, we add React's createElement as import.
|
|
1064
|
+
*/
|
|
1065
|
+
this.addReactImport = false;
|
|
1024
1066
|
this.lastCommentBlockIndex = -1;
|
|
1025
1067
|
this.lastCommentLineIndex = -1;
|
|
1068
|
+
this.encounteredFragment = false;
|
|
1026
1069
|
this.numSpaces = 0;
|
|
1027
1070
|
}
|
|
1028
1071
|
/**
|
|
@@ -1258,6 +1301,18 @@ class Stringifier {
|
|
|
1258
1301
|
}
|
|
1259
1302
|
return out;
|
|
1260
1303
|
}
|
|
1304
|
+
/**
|
|
1305
|
+
* @returns {string} The header.
|
|
1306
|
+
*/
|
|
1307
|
+
getHeader() {
|
|
1308
|
+
if (!this.addReactImport) {
|
|
1309
|
+
return '';
|
|
1310
|
+
}
|
|
1311
|
+
if (this.encounteredFragment) {
|
|
1312
|
+
return "import {createElement, Fragment} from 'react';\n";
|
|
1313
|
+
}
|
|
1314
|
+
return "import {createElement} from 'react';\n";
|
|
1315
|
+
}
|
|
1261
1316
|
get parent() {
|
|
1262
1317
|
return this.parents[this.parents.length - 2];
|
|
1263
1318
|
}
|
|
@@ -1618,7 +1673,10 @@ class Stringifier {
|
|
|
1618
1673
|
out += ' * ';
|
|
1619
1674
|
}
|
|
1620
1675
|
out += this.FunctionDeclarationParams(params);
|
|
1621
|
-
out += ' =>
|
|
1676
|
+
out += ' =>';
|
|
1677
|
+
if (body.type !== 'BlockStatement') {
|
|
1678
|
+
out += ' ';
|
|
1679
|
+
}
|
|
1622
1680
|
out += this.toSource(body);
|
|
1623
1681
|
return out;
|
|
1624
1682
|
}
|
|
@@ -2249,6 +2307,204 @@ class Stringifier {
|
|
|
2249
2307
|
// createMesh: createMesh$1\n
|
|
2250
2308
|
return `${spaces}${right} as ${left}`;
|
|
2251
2309
|
}
|
|
2310
|
+
/**
|
|
2311
|
+
* @param {import("@babel/types").JSXAttribute} node - The Babel AST node.
|
|
2312
|
+
* @returns {string} Stringification of the node.
|
|
2313
|
+
*/
|
|
2314
|
+
JSXAttribute(node) {
|
|
2315
|
+
const {
|
|
2316
|
+
name,
|
|
2317
|
+
value
|
|
2318
|
+
} = node;
|
|
2319
|
+
// console.log("JSXAttribute", {name, value});
|
|
2320
|
+
const keySource = this.toSource(name);
|
|
2321
|
+
// E.g. <audio controls/>
|
|
2322
|
+
if (value === null) {
|
|
2323
|
+
return `${this.spaces}${keySource}: true`;
|
|
2324
|
+
}
|
|
2325
|
+
const valSource = this.toSource(value);
|
|
2326
|
+
if (keySource === valSource) {
|
|
2327
|
+
return this.spaces + keySource;
|
|
2328
|
+
}
|
|
2329
|
+
return `${this.spaces}${keySource}: ${valSource}`;
|
|
2330
|
+
}
|
|
2331
|
+
/**
|
|
2332
|
+
* @param {import("@babel/types").JSXElement} node - The Babel AST node.
|
|
2333
|
+
* @returns {string} Stringification of the node.
|
|
2334
|
+
*/
|
|
2335
|
+
JSXElement(node) {
|
|
2336
|
+
this.addReactImport = true;
|
|
2337
|
+
const {
|
|
2338
|
+
openingElement,
|
|
2339
|
+
closingElement,
|
|
2340
|
+
children
|
|
2341
|
+
} = node;
|
|
2342
|
+
// console.log("JSXElement", {openingElement, closingElement, children});
|
|
2343
|
+
if (openingElement.type !== 'JSXOpeningElement') {
|
|
2344
|
+
debugger;
|
|
2345
|
+
}
|
|
2346
|
+
let {
|
|
2347
|
+
spaces
|
|
2348
|
+
} = this;
|
|
2349
|
+
const {
|
|
2350
|
+
name,
|
|
2351
|
+
attributes
|
|
2352
|
+
} = openingElement;
|
|
2353
|
+
let out = '';
|
|
2354
|
+
out += 'createElement(';
|
|
2355
|
+
this.numSpaces++;
|
|
2356
|
+
spaces = this.spaces;
|
|
2357
|
+
out += '\n';
|
|
2358
|
+
out += spaces;
|
|
2359
|
+
let sourceName = this.toSource(name);
|
|
2360
|
+
if (sourceName[0] === sourceName[0].toLowerCase()) {
|
|
2361
|
+
// If something like 'div', it has to become "'div'"
|
|
2362
|
+
sourceName = JSON.stringify(sourceName);
|
|
2363
|
+
}
|
|
2364
|
+
out += sourceName;
|
|
2365
|
+
out += ',';
|
|
2366
|
+
if (attributes.length) {
|
|
2367
|
+
out += '\n';
|
|
2368
|
+
out += spaces;
|
|
2369
|
+
out += '{\n';
|
|
2370
|
+
this.numSpaces++;
|
|
2371
|
+
out += attributes.map(attr => this.toSource(attr) + ',\n').join('');
|
|
2372
|
+
this.numSpaces--;
|
|
2373
|
+
out += spaces;
|
|
2374
|
+
out += '}';
|
|
2375
|
+
} else {
|
|
2376
|
+
out += '\n';
|
|
2377
|
+
out += spaces;
|
|
2378
|
+
out += 'null';
|
|
2379
|
+
}
|
|
2380
|
+
if (children.length) {
|
|
2381
|
+
out += ',\n';
|
|
2382
|
+
for (const child of children) {
|
|
2383
|
+
const source = this.toSource(child);
|
|
2384
|
+
if (!source.length) {
|
|
2385
|
+
continue;
|
|
2386
|
+
}
|
|
2387
|
+
out += spaces;
|
|
2388
|
+
out += source;
|
|
2389
|
+
out += ',\n';
|
|
2390
|
+
}
|
|
2391
|
+
} else {
|
|
2392
|
+
out += '\n';
|
|
2393
|
+
}
|
|
2394
|
+
this.numSpaces--;
|
|
2395
|
+
out += this.spaces;
|
|
2396
|
+
out += ')';
|
|
2397
|
+
return out;
|
|
2398
|
+
}
|
|
2399
|
+
/**
|
|
2400
|
+
* @param {import("@babel/types").JSXFragment} node - The Babel AST node.
|
|
2401
|
+
* @returns {string} Stringification of the node.
|
|
2402
|
+
*/
|
|
2403
|
+
JSXFragment(node) {
|
|
2404
|
+
const {
|
|
2405
|
+
/*openingFragment, closingFragment,*/children
|
|
2406
|
+
} = node;
|
|
2407
|
+
this.encounteredFragment = true;
|
|
2408
|
+
// console.log('JSXFragment', {openingFragment, closingFragment, children});
|
|
2409
|
+
let {
|
|
2410
|
+
spaces
|
|
2411
|
+
} = this;
|
|
2412
|
+
let out = 'createElement(\n';
|
|
2413
|
+
this.numSpaces++;
|
|
2414
|
+
spaces = this.spaces;
|
|
2415
|
+
out += spaces;
|
|
2416
|
+
out += 'Fragment,\n';
|
|
2417
|
+
out += spaces;
|
|
2418
|
+
out += 'null';
|
|
2419
|
+
// Same code for children as in JSXElement
|
|
2420
|
+
if (children.length) {
|
|
2421
|
+
out += ',\n';
|
|
2422
|
+
for (const child of children) {
|
|
2423
|
+
const source = this.toSource(child);
|
|
2424
|
+
if (!source.length) {
|
|
2425
|
+
continue;
|
|
2426
|
+
}
|
|
2427
|
+
out += spaces;
|
|
2428
|
+
out += source;
|
|
2429
|
+
out += ',\n';
|
|
2430
|
+
}
|
|
2431
|
+
} else {
|
|
2432
|
+
out += '\n';
|
|
2433
|
+
}
|
|
2434
|
+
this.numSpaces--;
|
|
2435
|
+
out += this.spaces;
|
|
2436
|
+
out += ')';
|
|
2437
|
+
return out;
|
|
2438
|
+
}
|
|
2439
|
+
/**
|
|
2440
|
+
* @param {import("@babel/types").JSXIdentifier} node - The Babel AST node.
|
|
2441
|
+
* @returns {string} Stringification of the node.
|
|
2442
|
+
*/
|
|
2443
|
+
JSXIdentifier(node) {
|
|
2444
|
+
const {
|
|
2445
|
+
name
|
|
2446
|
+
} = node;
|
|
2447
|
+
// console.log('JSXIdentifier', {name});
|
|
2448
|
+
// https://github.com/kungfooman/RuntimeTypeInspector.js/issues/201
|
|
2449
|
+
// https://stackoverflow.com/questions/38998987/using-aria-attributes-on-elements-in-react
|
|
2450
|
+
if (name.includes('-')) {
|
|
2451
|
+
return JSON.stringify(name);
|
|
2452
|
+
}
|
|
2453
|
+
return name;
|
|
2454
|
+
}
|
|
2455
|
+
/**
|
|
2456
|
+
* @param {import("@babel/types").JSXNamespacedName} node - The Babel AST node.
|
|
2457
|
+
* @returns {string} Stringification of the node.
|
|
2458
|
+
*/
|
|
2459
|
+
JSXNamespacedName(node) {
|
|
2460
|
+
const {
|
|
2461
|
+
namespace,
|
|
2462
|
+
name
|
|
2463
|
+
} = node;
|
|
2464
|
+
const a = this.toSource(namespace);
|
|
2465
|
+
const b = capitalize(this.toSource(name));
|
|
2466
|
+
return a + b;
|
|
2467
|
+
}
|
|
2468
|
+
/**
|
|
2469
|
+
* @param {import("@babel/types").JSXExpressionContainer} node - The Babel AST node.
|
|
2470
|
+
* @returns {string} Stringification of the node.
|
|
2471
|
+
*/
|
|
2472
|
+
JSXExpressionContainer(node) {
|
|
2473
|
+
const {
|
|
2474
|
+
expression
|
|
2475
|
+
} = node;
|
|
2476
|
+
// console.log('JSXExpressionContainer', {expression});
|
|
2477
|
+
return this.toSource(expression);
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* @param {import("@babel/types").JSXMemberExpression} node - The Babel AST node.
|
|
2481
|
+
* @returns {string} Stringification of the node.
|
|
2482
|
+
*/
|
|
2483
|
+
JSXMemberExpression(node) {
|
|
2484
|
+
const {
|
|
2485
|
+
object,
|
|
2486
|
+
property
|
|
2487
|
+
} = node;
|
|
2488
|
+
// console.log('JSXMemberExpression', 'object', object, 'property', property);
|
|
2489
|
+
const o = this.toSource(object);
|
|
2490
|
+
const p = this.toSource(property);
|
|
2491
|
+
return `${o}.${p}`;
|
|
2492
|
+
}
|
|
2493
|
+
/**
|
|
2494
|
+
* @param {import("@babel/types").JSXText} node - The Babel AST node.
|
|
2495
|
+
* @returns {string} Stringification of the node.
|
|
2496
|
+
*/
|
|
2497
|
+
JSXText(node) {
|
|
2498
|
+
const {
|
|
2499
|
+
extra,
|
|
2500
|
+
value
|
|
2501
|
+
} = node;
|
|
2502
|
+
// console.log('JSXText', {extra, value});
|
|
2503
|
+
if (!value.trim().length) {
|
|
2504
|
+
return '';
|
|
2505
|
+
}
|
|
2506
|
+
return JSON.stringify(value);
|
|
2507
|
+
}
|
|
2252
2508
|
/**
|
|
2253
2509
|
* @param {import("@babel/types").Super} node - The Babel AST node.
|
|
2254
2510
|
* @returns {string} Stringification of the node.
|
|
@@ -2647,6 +2903,22 @@ class Stringifier {
|
|
|
2647
2903
|
Import(node) {
|
|
2648
2904
|
return 'import';
|
|
2649
2905
|
}
|
|
2906
|
+
/**
|
|
2907
|
+
* @param {import("@babel/types").ImportExpression} node - The Babel AST node.
|
|
2908
|
+
* @returns {string} Stringification of the node.
|
|
2909
|
+
*/
|
|
2910
|
+
ImportExpression(node) {
|
|
2911
|
+
const {
|
|
2912
|
+
source,
|
|
2913
|
+
options
|
|
2914
|
+
} = node;
|
|
2915
|
+
let out = "import(" + this.toSource(source);
|
|
2916
|
+
if (options) {
|
|
2917
|
+
out += ', ' + this.toSource(options);
|
|
2918
|
+
}
|
|
2919
|
+
out += ')';
|
|
2920
|
+
return out;
|
|
2921
|
+
}
|
|
2650
2922
|
/**
|
|
2651
2923
|
* @param {import("@babel/types").ImportDeclaration} node - The Babel AST node.
|
|
2652
2924
|
* @returns {string} Stringification of the node.
|
|
@@ -2659,15 +2931,30 @@ class Stringifier {
|
|
|
2659
2931
|
// ImportNamespaceSpecifier: import * as a from "b";
|
|
2660
2932
|
// ImportDefaultSpecifier : import a from "b";
|
|
2661
2933
|
// ImportSpecifier : import { a } from "b";
|
|
2662
|
-
const
|
|
2663
|
-
const b = this.toSource(source);
|
|
2934
|
+
const from = this.toSource(source);
|
|
2664
2935
|
if (specifiers.length === 0) {
|
|
2665
|
-
return `import ${
|
|
2936
|
+
return `import ${from}`;
|
|
2937
|
+
}
|
|
2938
|
+
let out = 'import ';
|
|
2939
|
+
const n = specifiers.length;
|
|
2940
|
+
let inImportSpecifier = false;
|
|
2941
|
+
let i = 0;
|
|
2942
|
+
for (const specifier of specifiers) {
|
|
2943
|
+
if (specifier.type === 'ImportSpecifier' && !inImportSpecifier) {
|
|
2944
|
+
out += "{";
|
|
2945
|
+
inImportSpecifier = true;
|
|
2946
|
+
}
|
|
2947
|
+
out += this.toSource(specifier);
|
|
2948
|
+
if (i !== n - 1) {
|
|
2949
|
+
out += ', ';
|
|
2950
|
+
}
|
|
2951
|
+
i++;
|
|
2666
2952
|
}
|
|
2667
|
-
if (
|
|
2668
|
-
|
|
2953
|
+
if (inImportSpecifier) {
|
|
2954
|
+
out += '}';
|
|
2669
2955
|
}
|
|
2670
|
-
|
|
2956
|
+
out += ` from ${from};`;
|
|
2957
|
+
return out;
|
|
2671
2958
|
}
|
|
2672
2959
|
/**
|
|
2673
2960
|
* @param {import("@babel/types").ImportSpecifier} node - The Babel AST node.
|
|
@@ -2917,7 +3204,13 @@ class Asserter extends Stringifier {
|
|
|
2917
3204
|
} else {
|
|
2918
3205
|
out += ' {\n';
|
|
2919
3206
|
out += this.generateTypeChecks(node);
|
|
3207
|
+
const {
|
|
3208
|
+
spaces
|
|
3209
|
+
} = this;
|
|
3210
|
+
this.numSpaces++;
|
|
2920
3211
|
out += this.spaces + 'return ' + this.toSource(body) + ';\n';
|
|
3212
|
+
this.numSpaces--;
|
|
3213
|
+
out += spaces;
|
|
2921
3214
|
out += '}';
|
|
2922
3215
|
}
|
|
2923
3216
|
return out;
|
|
@@ -2959,12 +3252,14 @@ class Asserter extends Stringifier {
|
|
|
2959
3252
|
* @todo
|
|
2960
3253
|
* Once we went over every node, we can see if we really require registerTypef, registerClass etc.
|
|
2961
3254
|
* @returns {string} The import declaration header for importing RTI.
|
|
3255
|
+
* @override
|
|
2962
3256
|
*/
|
|
2963
3257
|
getHeader() {
|
|
2964
3258
|
if (!this.addHeader) {
|
|
2965
3259
|
return '';
|
|
2966
3260
|
}
|
|
2967
|
-
let header =
|
|
3261
|
+
let header = super.getHeader();
|
|
3262
|
+
header += "import {inspectType, inspectTypeWithTemplates, youCanAddABreakpointHere, registerVariable";
|
|
2968
3263
|
if (this.validateDivision) {
|
|
2969
3264
|
header += ", validateDivision";
|
|
2970
3265
|
}
|
|
@@ -3631,6 +3926,17 @@ class Asserter extends Stringifier {
|
|
|
3631
3926
|
}
|
|
3632
3927
|
}
|
|
3633
3928
|
|
|
3929
|
+
/**
|
|
3930
|
+
* We use the same options in different places, so it's nice to keep them in sync without
|
|
3931
|
+
* changing them in multiple locations.
|
|
3932
|
+
* @type {import('@babel/parser').ParserOptions}
|
|
3933
|
+
*/
|
|
3934
|
+
const parserOptions = {
|
|
3935
|
+
sourceType: 'module',
|
|
3936
|
+
createParenthesizedExpressions: true,
|
|
3937
|
+
plugins: ['jsx']
|
|
3938
|
+
};
|
|
3939
|
+
|
|
3634
3940
|
/**
|
|
3635
3941
|
* Simple facade which does all the processing. Processes the input
|
|
3636
3942
|
* source string, adding runtime type checks based on JSDoc comments.
|
|
@@ -3650,11 +3956,10 @@ class Asserter extends Stringifier {
|
|
|
3650
3956
|
function addTypeChecks(src, options) {
|
|
3651
3957
|
try {
|
|
3652
3958
|
const asserter = new Asserter(options);
|
|
3653
|
-
const ast = parse(src,
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
const out = asserter.getHeader() + asserter.toSource(ast);
|
|
3959
|
+
const ast = parse(src, parserOptions);
|
|
3960
|
+
// Must be called before getHeader since it's keeping an eye open for JSX elements.
|
|
3961
|
+
const source = asserter.toSource(ast);
|
|
3962
|
+
const out = asserter.getHeader() + source;
|
|
3658
3963
|
return out;
|
|
3659
3964
|
} catch (e) {
|
|
3660
3965
|
console.error(e);
|
|
@@ -3702,15 +4007,13 @@ function ast2jsonForComparison(ast) {
|
|
|
3702
4007
|
* @returns {string | undefined} The new and once parsed and stringified code.
|
|
3703
4008
|
*/
|
|
3704
4009
|
function code2ast2code(code) {
|
|
3705
|
-
const
|
|
3706
|
-
const ast = parse(code, {
|
|
3707
|
-
sourceType: 'module'
|
|
3708
|
-
});
|
|
4010
|
+
const ast = parse(code, parserOptions);
|
|
3709
4011
|
if (!ast) {
|
|
3710
4012
|
return;
|
|
3711
4013
|
}
|
|
4014
|
+
const stringifier = new Stringifier();
|
|
3712
4015
|
const out = stringifier.toSource(ast);
|
|
3713
|
-
return out;
|
|
4016
|
+
return stringifier.getHeader() + out;
|
|
3714
4017
|
}
|
|
3715
4018
|
|
|
3716
4019
|
/**
|
|
@@ -3972,4 +4275,4 @@ function toSourceBabelTS(node) {
|
|
|
3972
4275
|
}
|
|
3973
4276
|
}
|
|
3974
4277
|
|
|
3975
|
-
export { Asserter, Stringifier, addTypeChecks, ast2json, ast2jsonForComparison, code2ast2code, compareAST, expandType, expandTypeBabelTS, expandTypeDepFree, extractCurlyContent, extractNameAndOptionality, nodeIsFunction, parseJSDoc, parseJSDocSetter, parseJSDocTemplates, parseJSDocTypedef, parseType, parseTypeBabelTS, requiredTypeofs, simplifyType, toSourceBabelTS, toSourceTS, trimEndSpaces };
|
|
4278
|
+
export { Asserter, Stringifier, addTypeChecks, ast2json, ast2jsonForComparison, capitalize, code2ast2code, compareAST, expandType, expandTypeBabelTS, expandTypeDepFree, extractCurlyContent, extractNameAndOptionality, nodeIsFunction, parseJSDoc, parseJSDocSetter, parseJSDocTemplates, parseJSDocTypedef, parseType, parseTypeBabelTS, parserOptions, requiredTypeofs, simplifyType, toSourceBabelTS, toSourceTS, trimEndSpaces };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bin": "bin.js",
|
|
3
3
|
"name": "@runtime-type-inspector/transpiler",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.1",
|
|
5
5
|
"description": "Validating JSDoc types at runtime for high-quality types - Trust is good, control is better.",
|
|
6
6
|
"main": "index.cjs",
|
|
7
7
|
"module": "index.mjs",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"homepage": "https://github.com/kungfooman/RuntimeTypeInspector.js#readme",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@babel/parser": "^7.23.0",
|
|
22
|
-
"@runtime-type-inspector/runtime": "^
|
|
22
|
+
"@runtime-type-inspector/runtime": "^4.0.1",
|
|
23
23
|
"typescript": "^5.1.6"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|