@runtime-type-inspector/transpiler 3.2.6 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +266 -68
- package/index.mjs +309 -76
- package/package.json +2 -2
package/index.cjs
CHANGED
|
@@ -282,24 +282,19 @@
|
|
|
282
282
|
* expandType('typeof Number '); // Outputs:
|
|
283
283
|
* @param {string} type - The type string to be expanded into a structured representation.
|
|
284
284
|
* @todo Share type with expandTypeBabelTS and expandTypeDepFree
|
|
285
|
-
* @returns {string | {type: string, [key: string]: any} | undefined} The structured type
|
|
285
|
+
* @returns {string | number | boolean | {type: string, [key: string]: any} | undefined} The structured type
|
|
286
286
|
* representation obtained from parsing and converting the provided type string.
|
|
287
287
|
*/
|
|
288
288
|
function expandType(type) {
|
|
289
289
|
var ast = parseType(type);
|
|
290
|
+
if (!ast) {
|
|
291
|
+
return 'never';
|
|
292
|
+
}
|
|
290
293
|
return toSourceTS(ast);
|
|
291
294
|
}
|
|
292
|
-
/**
|
|
293
|
-
* @todo I want to use for example: import('typescript').Node
|
|
294
|
-
* But the TS types make no sense to me so far ... need to investigate more.
|
|
295
|
-
* @typedef TypeScriptType
|
|
296
|
-
* @property {object[]|undefined} typeArguments - The type arguments.
|
|
297
|
-
* @property {import('typescript').Node} typeName - The type name.
|
|
298
|
-
* @property {number} kind - The kind for `ts.SyntaxKind[kind]`.
|
|
299
|
-
*/
|
|
300
295
|
/**
|
|
301
296
|
* @param {string} str - The type string.
|
|
302
|
-
* @returns {
|
|
297
|
+
* @returns {ts.TypeNode|undefined} - The node containing all the information about the input type string.
|
|
303
298
|
*/
|
|
304
299
|
function parseType(str) {
|
|
305
300
|
// TS doesn't like ... notation in this context
|
|
@@ -310,7 +305,12 @@
|
|
|
310
305
|
// type tmp = (...string) => 123; to have a function context
|
|
311
306
|
str = "type tmp = ".concat(str, ";");
|
|
312
307
|
var ast = ts.createSourceFile('repl.ts', str, ts.ScriptTarget.Latest, true /*setParentNodes*/);
|
|
313
|
-
|
|
308
|
+
var firstStatement = ast.statements[0];
|
|
309
|
+
if (!ts.isTypeAliasDeclaration(firstStatement)) {
|
|
310
|
+
console.warn('parseType> Expected type alias declaration, got', firstStatement, 'instead.');
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
return firstStatement.type;
|
|
314
314
|
}
|
|
315
315
|
/** @type {Record<string, 'missing'|'found'>} */
|
|
316
316
|
var requiredTypeofs = {};
|
|
@@ -320,7 +320,7 @@
|
|
|
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 {
|
|
323
|
+
* @param {ts.TypeNode|ts.Identifier} 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
|
*/
|
|
@@ -336,7 +336,7 @@
|
|
|
336
336
|
Identifier = _ts$SyntaxKind.Identifier,
|
|
337
337
|
IntersectionType = _ts$SyntaxKind.IntersectionType,
|
|
338
338
|
JSDocAllType = _ts$SyntaxKind.JSDocAllType,
|
|
339
|
-
|
|
339
|
+
ImportType = _ts$SyntaxKind.ImportType,
|
|
340
340
|
LiteralType = _ts$SyntaxKind.LiteralType,
|
|
341
341
|
NullKeyword = _ts$SyntaxKind.NullKeyword,
|
|
342
342
|
NumberKeyword = _ts$SyntaxKind.NumberKeyword,
|
|
@@ -363,6 +363,7 @@
|
|
|
363
363
|
BigIntLiteral = _ts$SyntaxKind.BigIntLiteral,
|
|
364
364
|
ConditionalType = _ts$SyntaxKind.ConditionalType,
|
|
365
365
|
IndexedAccessType = _ts$SyntaxKind.IndexedAccessType,
|
|
366
|
+
IndexSignature = _ts$SyntaxKind.IndexSignature,
|
|
366
367
|
RestType = _ts$SyntaxKind.RestType,
|
|
367
368
|
TypeQuery = _ts$SyntaxKind.TypeQuery,
|
|
368
369
|
TypeOperator = _ts$SyntaxKind.TypeOperator,
|
|
@@ -378,12 +379,18 @@
|
|
|
378
379
|
type: 'bigint'
|
|
379
380
|
};
|
|
380
381
|
case BigIntLiteral:
|
|
382
|
+
if (!ts.isBigIntLiteral(node)) {
|
|
383
|
+
throw Error("Impossible");
|
|
384
|
+
}
|
|
381
385
|
var literal = node.text.slice(0, -1); // Remove the "n"
|
|
382
386
|
return {
|
|
383
387
|
type: 'bigint',
|
|
384
388
|
literal: literal
|
|
385
389
|
};
|
|
386
390
|
case ConditionalType:
|
|
391
|
+
if (!ts.isConditionalTypeNode(node)) {
|
|
392
|
+
throw Error("Impossible");
|
|
393
|
+
}
|
|
387
394
|
// Keys on node:
|
|
388
395
|
// ['pos', 'end', 'flags', 'modifierFlagsCache', 'transformFlags', 'parent', 'kind', 'checkType',
|
|
389
396
|
// 'extendsType', 'trueType', 'falseType', 'locals', 'nextContainer']
|
|
@@ -400,6 +407,9 @@
|
|
|
400
407
|
};
|
|
401
408
|
case ConstructorType:
|
|
402
409
|
{
|
|
410
|
+
if (!ts.isConstructorTypeNode(node)) {
|
|
411
|
+
throw Error("Impossible");
|
|
412
|
+
}
|
|
403
413
|
var _parameters = node.parameters.map(toSourceTS);
|
|
404
414
|
var _ret = toSourceTS(node.type);
|
|
405
415
|
return {
|
|
@@ -409,12 +419,18 @@
|
|
|
409
419
|
};
|
|
410
420
|
}
|
|
411
421
|
case FunctionType:
|
|
422
|
+
if (!ts.isFunctionTypeNode(node)) {
|
|
423
|
+
throw Error("Impossible");
|
|
424
|
+
}
|
|
412
425
|
var parameters = node.parameters.map(toSourceTS);
|
|
413
426
|
return {
|
|
414
427
|
type: 'function',
|
|
415
428
|
parameters: parameters
|
|
416
429
|
};
|
|
417
430
|
case IndexedAccessType:
|
|
431
|
+
if (!ts.isIndexedAccessTypeNode(node)) {
|
|
432
|
+
throw Error("Impossible");
|
|
433
|
+
}
|
|
418
434
|
var index = toSourceTS(node.indexType);
|
|
419
435
|
var object = toSourceTS(node.objectType);
|
|
420
436
|
return {
|
|
@@ -423,12 +439,18 @@
|
|
|
423
439
|
object: object
|
|
424
440
|
};
|
|
425
441
|
case RestType:
|
|
442
|
+
if (!ts.isRestTypeNode(node)) {
|
|
443
|
+
throw Error("Impossible");
|
|
444
|
+
}
|
|
426
445
|
var annotation = toSourceTS(node.type);
|
|
427
446
|
return {
|
|
428
447
|
type: 'rest',
|
|
429
448
|
annotation: annotation
|
|
430
449
|
};
|
|
431
450
|
case JSDocNullableType:
|
|
451
|
+
if (!ts.isJSDocNullableType(node)) {
|
|
452
|
+
throw Error("Impossible");
|
|
453
|
+
}
|
|
432
454
|
var t = toSourceTS(node.type);
|
|
433
455
|
return {
|
|
434
456
|
type: 'union',
|
|
@@ -436,6 +458,9 @@
|
|
|
436
458
|
};
|
|
437
459
|
case MappedType:
|
|
438
460
|
{
|
|
461
|
+
if (!ts.isMappedTypeNode(node)) {
|
|
462
|
+
throw Error("Impossible");
|
|
463
|
+
}
|
|
439
464
|
var result = toSourceTS(node.type);
|
|
440
465
|
var parameter = node.typeParameter;
|
|
441
466
|
if (parameter.kind === TypeParameter) {
|
|
@@ -455,6 +480,9 @@
|
|
|
455
480
|
// todo work out more: const jsdoc = `(...a: ...number) => 123
|
|
456
481
|
// TS even thinks it's two parameters... just go for array/[]
|
|
457
482
|
case Parameter:
|
|
483
|
+
if (!ts.isParameter(node)) {
|
|
484
|
+
throw Error("Impossible");
|
|
485
|
+
}
|
|
458
486
|
var type = node.type ? toSourceTS(node.type) : 'any';
|
|
459
487
|
var name = toSourceTS(node.name);
|
|
460
488
|
var ret = {
|
|
@@ -469,6 +497,9 @@
|
|
|
469
497
|
}
|
|
470
498
|
return ret;
|
|
471
499
|
case TypeQuery:
|
|
500
|
+
if (!ts.isTypeQueryNode(node)) {
|
|
501
|
+
throw Error("Impossible");
|
|
502
|
+
}
|
|
472
503
|
var argument = toSourceTS(node.exprName);
|
|
473
504
|
// Notify Asserter class that we have to register variables with this name
|
|
474
505
|
if (!requiredTypeofs[argument]) {
|
|
@@ -479,6 +510,9 @@
|
|
|
479
510
|
argument: argument
|
|
480
511
|
};
|
|
481
512
|
case TypeOperator:
|
|
513
|
+
if (!ts.isTypeOperatorNode(node)) {
|
|
514
|
+
throw Error("Impossible");
|
|
515
|
+
}
|
|
482
516
|
if (node.operator === KeyOfKeyword) {
|
|
483
517
|
var _argument = toSourceTS(node.type);
|
|
484
518
|
return {
|
|
@@ -489,6 +523,9 @@
|
|
|
489
523
|
console.warn("unimplemented TypeOperator", node);
|
|
490
524
|
case TypeReference:
|
|
491
525
|
{
|
|
526
|
+
if (!ts.isTypeReferenceNode(node)) {
|
|
527
|
+
throw Error("Impossible");
|
|
528
|
+
}
|
|
492
529
|
if ((typeName.text === 'Object' || typeName.text === 'Record') && (typeArguments === null || typeArguments === void 0 ? void 0 : typeArguments.length) === 2) {
|
|
493
530
|
return {
|
|
494
531
|
type: 'record',
|
|
@@ -544,14 +581,16 @@
|
|
|
544
581
|
args: args
|
|
545
582
|
};
|
|
546
583
|
}
|
|
547
|
-
case StringKeyword:
|
|
548
|
-
return node.getText();
|
|
549
|
-
case NumberKeyword:
|
|
550
|
-
return node.getText();
|
|
551
584
|
case NamedTupleMember:
|
|
585
|
+
if (!ts.isNamedTupleMember(node)) {
|
|
586
|
+
throw Error("Impossible");
|
|
587
|
+
}
|
|
552
588
|
return toSourceTS(node.type);
|
|
553
589
|
case IntersectionType:
|
|
554
590
|
{
|
|
591
|
+
if (!ts.isIntersectionTypeNode(node)) {
|
|
592
|
+
throw Error("Impossible");
|
|
593
|
+
}
|
|
555
594
|
var _members = node.types.map(toSourceTS);
|
|
556
595
|
return {
|
|
557
596
|
type: 'intersection',
|
|
@@ -559,35 +598,87 @@
|
|
|
559
598
|
};
|
|
560
599
|
}
|
|
561
600
|
case TupleType:
|
|
601
|
+
if (!ts.isTupleTypeNode(node)) {
|
|
602
|
+
throw Error("Impossible");
|
|
603
|
+
}
|
|
562
604
|
var elements = node.elements.map(toSourceTS);
|
|
563
605
|
return {
|
|
564
606
|
type: 'tuple',
|
|
565
607
|
elements: elements
|
|
566
608
|
};
|
|
567
609
|
case UnionType:
|
|
610
|
+
if (!ts.isUnionTypeNode(node)) {
|
|
611
|
+
throw Error("Impossible");
|
|
612
|
+
}
|
|
568
613
|
var members = node.types.map(toSourceTS);
|
|
569
614
|
return {
|
|
570
615
|
type: 'union',
|
|
571
616
|
members: members
|
|
572
617
|
};
|
|
573
618
|
case TypeLiteral:
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
properties
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
619
|
+
{
|
|
620
|
+
if (!ts.isTypeLiteralNode(node)) {
|
|
621
|
+
throw Error("Impossible");
|
|
622
|
+
}
|
|
623
|
+
var properties = {};
|
|
624
|
+
/** @type {object[]} */
|
|
625
|
+
var indexSignatures;
|
|
626
|
+
node.members.forEach(function (member) {
|
|
627
|
+
if (member.kind === IndexSignature) {
|
|
628
|
+
var _indexSignatures;
|
|
629
|
+
indexSignatures = (_indexSignatures = indexSignatures) !== null && _indexSignatures !== void 0 ? _indexSignatures : [];
|
|
630
|
+
indexSignatures.push(toSourceTS(member));
|
|
631
|
+
} else if (member.kind === PropertySignature) {
|
|
632
|
+
if (!ts.isPropertySignature(member)) {
|
|
633
|
+
throw Error("Impossible");
|
|
634
|
+
}
|
|
635
|
+
var _name2 = toSourceTS(member.name);
|
|
636
|
+
var _type = toSourceTS(member.type);
|
|
637
|
+
properties[_name2] = _type;
|
|
638
|
+
} else {
|
|
639
|
+
console.warn('TypeLiteral: unhandled member', member);
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
var _ret2 = {
|
|
643
|
+
type: 'object'
|
|
644
|
+
};
|
|
645
|
+
if (Object.keys(properties).length) {
|
|
646
|
+
_ret2.properties = properties;
|
|
647
|
+
}
|
|
648
|
+
if (indexSignatures) {
|
|
649
|
+
_ret2.indexSignatures = indexSignatures;
|
|
650
|
+
}
|
|
651
|
+
return _ret2;
|
|
652
|
+
}
|
|
584
653
|
case PropertySignature:
|
|
654
|
+
if (!ts.isPropertySignature(node)) {
|
|
655
|
+
throw Error("Impossible");
|
|
656
|
+
}
|
|
585
657
|
console.warn('toSourceTS> should not happen, handled by TypeLiteral directly');
|
|
586
658
|
return "".concat(toSourceTS(node.name), ": ").concat(toSourceTS(node.type));
|
|
659
|
+
case IndexSignature:
|
|
660
|
+
if (!ts.isIndexSignatureDeclaration(node)) {
|
|
661
|
+
throw Error("Impossible");
|
|
662
|
+
}
|
|
663
|
+
// Only possible modifier I know of, but we don't need it:
|
|
664
|
+
// {readonly [n: number]: string, length: number}
|
|
665
|
+
var indexType = toSourceTS(node.type);
|
|
666
|
+
var indexParameters = node.parameters.map(toSourceTS);
|
|
667
|
+
return {
|
|
668
|
+
type: 'indexSignature',
|
|
669
|
+
indexType: indexType,
|
|
670
|
+
indexParameters: indexParameters
|
|
671
|
+
};
|
|
587
672
|
case Identifier:
|
|
673
|
+
if (!ts.isIdentifier(node)) {
|
|
674
|
+
throw Error("Impossible");
|
|
675
|
+
}
|
|
588
676
|
return node.text;
|
|
589
677
|
case ArrayType:
|
|
590
678
|
{
|
|
679
|
+
if (!ts.isArrayTypeNode(node)) {
|
|
680
|
+
throw Error("Impossible");
|
|
681
|
+
}
|
|
591
682
|
var _elementType4 = toSourceTS(node.elementType);
|
|
592
683
|
return {
|
|
593
684
|
type: 'array',
|
|
@@ -595,18 +686,23 @@
|
|
|
595
686
|
};
|
|
596
687
|
}
|
|
597
688
|
case LiteralType:
|
|
689
|
+
if (!ts.isLiteralTypeNode(node)) {
|
|
690
|
+
throw Error("Impossible");
|
|
691
|
+
}
|
|
598
692
|
return toSourceTS(node.literal);
|
|
599
693
|
case AnyKeyword:
|
|
600
694
|
case BooleanKeyword:
|
|
601
|
-
|
|
602
|
-
case
|
|
695
|
+
case StringKeyword:
|
|
696
|
+
case NeverKeyword:
|
|
603
697
|
case NullKeyword:
|
|
604
|
-
case
|
|
605
|
-
case ThisType:
|
|
698
|
+
case NumberKeyword:
|
|
606
699
|
case UndefinedKeyword:
|
|
607
|
-
case VoidKeyword:
|
|
608
700
|
case UnknownKeyword:
|
|
609
|
-
case
|
|
701
|
+
case VoidKeyword:
|
|
702
|
+
// ts.SyntaxKind[parseType("*").kind] === 'JSDocAllType'
|
|
703
|
+
case JSDocAllType:
|
|
704
|
+
case ThisType:
|
|
705
|
+
case StringLiteral:
|
|
610
706
|
return node.getText();
|
|
611
707
|
case TrueKeyword:
|
|
612
708
|
return true;
|
|
@@ -620,9 +716,16 @@
|
|
|
620
716
|
properties: {}
|
|
621
717
|
};
|
|
622
718
|
case ParenthesizedType:
|
|
719
|
+
if (!ts.isParenthesizedTypeNode(node)) {
|
|
720
|
+
throw Error("Impossible");
|
|
721
|
+
}
|
|
623
722
|
// fall-through for parentheses
|
|
624
723
|
return toSourceTS(node.type);
|
|
625
|
-
case
|
|
724
|
+
case ImportType:
|
|
725
|
+
if (!ts.isImportTypeNode(node)) {
|
|
726
|
+
throw Error("Impossible");
|
|
727
|
+
}
|
|
728
|
+
/** @todo Handle case without any qualifier like `import('test')` */
|
|
626
729
|
return toSourceTS(node.qualifier);
|
|
627
730
|
default:
|
|
628
731
|
// const test = {};
|
|
@@ -844,19 +947,26 @@
|
|
|
844
947
|
return type;
|
|
845
948
|
}
|
|
846
949
|
|
|
950
|
+
/**
|
|
951
|
+
* @typedef {ReturnType<typeof parseJSDoc>} ParseJSDocReturnType
|
|
952
|
+
*/
|
|
953
|
+
/**
|
|
954
|
+
* @typedef {typeof expandTypeDepFree} ExpandType
|
|
955
|
+
* @typedef {ReturnType<ExpandType>} ExpandTypeReturnType
|
|
956
|
+
*/
|
|
847
957
|
/**
|
|
848
958
|
* Parses JSDoc comments to extract parameter type information.
|
|
849
959
|
*
|
|
850
960
|
* @param {string} src - The JSDoc comment string to parse.
|
|
851
|
-
* @param {
|
|
852
|
-
* @returns {Record<string,
|
|
961
|
+
* @param {ExpandType} [expandType] - An optional function to process the types found in the JSDoc.
|
|
962
|
+
* @returns {Record<string, ExpandTypeReturnType> | undefined} An object mapping parameter names to their parsed types, or undefined if no parameters are found.
|
|
853
963
|
*/
|
|
854
964
|
function parseJSDoc(src) {
|
|
855
965
|
var expandType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : expandTypeDepFree;
|
|
856
966
|
// Parse something like: @param {Object} [kwargs={}] Optional arguments.
|
|
857
967
|
var regex = /@param \{(.*?)\} ([\[\]a-zA-Z0-9_$=\{\}\.'" ]+)/g;
|
|
858
968
|
var matches = _toConsumableArray(src.matchAll(regex));
|
|
859
|
-
/** @type {Record<string,
|
|
969
|
+
/** @type {Record<string, ExpandTypeReturnType>} */
|
|
860
970
|
var params = Object.create(null);
|
|
861
971
|
matches.forEach(function (_) {
|
|
862
972
|
var type = expandType(_[1].trim());
|
|
@@ -884,7 +994,6 @@
|
|
|
884
994
|
try {
|
|
885
995
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
886
996
|
var part = _step.value;
|
|
887
|
-
/** @type {object} */
|
|
888
997
|
var toptype = properties[part];
|
|
889
998
|
if (!toptype) {
|
|
890
999
|
// No toptype means we resolved as far as possible, now we can add `simplifiedType`.
|
|
@@ -939,6 +1048,35 @@
|
|
|
939
1048
|
}
|
|
940
1049
|
}
|
|
941
1050
|
|
|
1051
|
+
/**
|
|
1052
|
+
* @typedef {typeof expandTypeDepFree} ExpandType
|
|
1053
|
+
* @typedef {ReturnType<ExpandType>} ExpandTypeReturnType
|
|
1054
|
+
*/
|
|
1055
|
+
/**
|
|
1056
|
+
* Parses JSDoc comments to extract parameter type information.
|
|
1057
|
+
*
|
|
1058
|
+
* @param {string} src - The JSDoc comment string to parse.
|
|
1059
|
+
* @param {ExpandType} [expandType] - An optional function to process the types found in the JSDoc.
|
|
1060
|
+
* @returns {Record<string, ExpandTypeReturnType> | undefined} An object mapping template names to their parsed types,
|
|
1061
|
+
* or `undefined` if no template tags were found.
|
|
1062
|
+
*/
|
|
1063
|
+
function parseJSDocTemplates(src) {
|
|
1064
|
+
var expandType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : expandTypeDepFree;
|
|
1065
|
+
var regexTemplateTyped = /@template \{(.*?)\} ([a-zA-Z0-9_$=]+)/g;
|
|
1066
|
+
var matches = _toConsumableArray(src.matchAll(regexTemplateTyped));
|
|
1067
|
+
if (!matches.length) {
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
/** @type {Record<string, ExpandTypeReturnType>} */
|
|
1071
|
+
var templates = Object.create(null);
|
|
1072
|
+
matches.forEach(function (_) {
|
|
1073
|
+
var type = expandType(_[1].trim());
|
|
1074
|
+
var name = _[2].trim();
|
|
1075
|
+
templates[name] = type;
|
|
1076
|
+
});
|
|
1077
|
+
return templates;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
942
1080
|
/**
|
|
943
1081
|
* Extracts the parameter name and its optionality from a JSDoc parameter string.
|
|
944
1082
|
*
|
|
@@ -2943,14 +3081,14 @@
|
|
|
2943
3081
|
}();
|
|
2944
3082
|
|
|
2945
3083
|
/** @typedef {import('@babel/types').Node } Node */
|
|
2946
|
-
/** @typedef {import(
|
|
2947
|
-
/** @typedef {import(
|
|
2948
|
-
/** @typedef {import('./stat.js').Stat
|
|
3084
|
+
/** @typedef {import('@babel/types').ClassMethod } ClassMethod */
|
|
3085
|
+
/** @typedef {import('@babel/types').ClassPrivateMethod} ClassPrivateMethod */
|
|
3086
|
+
/** @typedef {import('./stat.js').Stat } Stat */
|
|
2949
3087
|
/**
|
|
2950
3088
|
* @typedef {object} Options
|
|
2951
3089
|
* @property {boolean} [forceCurly] - Determines whether curly braces are enforced in Stringifier.
|
|
2952
3090
|
* @property {boolean} [validateDivision] - Indicates whether division operations should be validated.
|
|
2953
|
-
* @property {
|
|
3091
|
+
* @property {import('./parseJSDoc.js').ExpandType} [expandType] - A function that expands shorthand types into full descriptions.
|
|
2954
3092
|
* @property {string} [filename] - The name of a file to which the instance pertains.
|
|
2955
3093
|
* @property {boolean} [addHeader] - Whether to add import declarations headers. Defaults to true.
|
|
2956
3094
|
* @property {string[]} [ignoreLocations] - Ignore these locations because they are known false-positives.
|
|
@@ -3227,11 +3365,11 @@
|
|
|
3227
3365
|
}
|
|
3228
3366
|
/**
|
|
3229
3367
|
* @param {Node} node - The Babel AST node.
|
|
3230
|
-
* @returns {undefined
|
|
3368
|
+
* @returns {string|undefined} The JSDoc comment of `node`.
|
|
3231
3369
|
*/
|
|
3232
3370
|
}, {
|
|
3233
|
-
key: "
|
|
3234
|
-
value: function
|
|
3371
|
+
key: "getLeadingComment",
|
|
3372
|
+
value: function getLeadingComment(node) {
|
|
3235
3373
|
if (node.type === 'BlockStatement') {
|
|
3236
3374
|
node = this.parent;
|
|
3237
3375
|
}
|
|
@@ -3256,26 +3394,61 @@
|
|
|
3256
3394
|
if (leadingComments && leadingComments.length) {
|
|
3257
3395
|
var lastComment = leadingComments[leadingComments.length - 1];
|
|
3258
3396
|
if (lastComment.type === "CommentBlock") {
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3397
|
+
return lastComment.value;
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
/**
|
|
3402
|
+
* @param {Node} node - The Babel AST node.
|
|
3403
|
+
* @todo ESLint problem:
|
|
3404
|
+
* returns {import('./parseJSDoc.js').ParseJSDocReturnType} The return value of `parseJSDoc`
|
|
3405
|
+
* returns {Record<string, import('./parseJSDoc.js').ExpandTypeReturnType> | undefined} The
|
|
3406
|
+
* return value of `parseJSDoc`.
|
|
3407
|
+
* @returns {Record<string, any>|undefined} asd
|
|
3408
|
+
*/
|
|
3409
|
+
}, {
|
|
3410
|
+
key: "getJSDoc",
|
|
3411
|
+
value: function getJSDoc(node) {
|
|
3412
|
+
var comment = this.getLeadingComment(node);
|
|
3413
|
+
if (!comment) {
|
|
3414
|
+
return;
|
|
3415
|
+
}
|
|
3416
|
+
if (comment.includes('@event')) {
|
|
3417
|
+
return;
|
|
3418
|
+
}
|
|
3419
|
+
if (comment.includes('@ignoreRTI')) {
|
|
3420
|
+
return;
|
|
3421
|
+
}
|
|
3422
|
+
// Need to do same resolving as in: this.getLeadingComment(node)
|
|
3423
|
+
if (node.type === 'BlockStatement') {
|
|
3424
|
+
node = this.parent;
|
|
3425
|
+
}
|
|
3426
|
+
if (node.type === 'ClassMethod') {
|
|
3427
|
+
if (node.kind === 'get') {
|
|
3428
|
+
// JSDoc on a getter is just some documentation.
|
|
3429
|
+
return;
|
|
3430
|
+
} else if (node.kind === 'set') {
|
|
3431
|
+
if (node.params.length !== 1) {
|
|
3432
|
+
this.warn("getJSDoc> setters require exactly one argument");
|
|
3272
3433
|
}
|
|
3273
|
-
|
|
3434
|
+
var setterType = parseJSDocSetter(comment, this.expandType);
|
|
3435
|
+
if (!setterType) {
|
|
3274
3436
|
return;
|
|
3275
3437
|
}
|
|
3276
|
-
|
|
3438
|
+
var paramName = this.getNameOfParam(node.params[0]);
|
|
3439
|
+
var _params = _defineProperty({}, paramName, setterType);
|
|
3440
|
+
return {
|
|
3441
|
+
templates: undefined,
|
|
3442
|
+
params: _params
|
|
3443
|
+
};
|
|
3277
3444
|
}
|
|
3278
3445
|
}
|
|
3446
|
+
var templates = parseJSDocTemplates(comment);
|
|
3447
|
+
var params = parseJSDoc(comment, this.expandType);
|
|
3448
|
+
return {
|
|
3449
|
+
templates: templates,
|
|
3450
|
+
params: params
|
|
3451
|
+
};
|
|
3279
3452
|
}
|
|
3280
3453
|
/**
|
|
3281
3454
|
* Retrieves the name of a parameter from a Babel AST node.
|
|
@@ -3296,8 +3469,7 @@
|
|
|
3296
3469
|
return param.left.name;
|
|
3297
3470
|
}
|
|
3298
3471
|
}
|
|
3299
|
-
|
|
3300
|
-
this.warn("unable to extra name from param in specified way - may contain too much information");
|
|
3472
|
+
this.warn("Unable to retrieve name from param in specified way - may contain too much information.");
|
|
3301
3473
|
return this.toSource(param);
|
|
3302
3474
|
}
|
|
3303
3475
|
}, {
|
|
@@ -3414,6 +3586,15 @@
|
|
|
3414
3586
|
stat.unchecked++;
|
|
3415
3587
|
return '';
|
|
3416
3588
|
}
|
|
3589
|
+
var templates = jsdoc.templates,
|
|
3590
|
+
params = jsdoc.params;
|
|
3591
|
+
if (!params) {
|
|
3592
|
+
console.warn("This should never happen, please check your input code.", this.getLeadingComment(node), {
|
|
3593
|
+
jsdoc: jsdoc
|
|
3594
|
+
});
|
|
3595
|
+
stat.unchecked++;
|
|
3596
|
+
return '';
|
|
3597
|
+
}
|
|
3417
3598
|
stat.checked++;
|
|
3418
3599
|
var spaces = this.spaces;
|
|
3419
3600
|
var out = '';
|
|
@@ -3422,17 +3603,21 @@
|
|
|
3422
3603
|
if (this.ignoreLocations.includes(loc)) {
|
|
3423
3604
|
return '// IGNORE RTI TYPE VALIDATIONS, KNOWN ISSUES\n';
|
|
3424
3605
|
}
|
|
3606
|
+
if (templates) {
|
|
3607
|
+
var tmp = JSON.stringify(templates, null, 2).replaceAll('\n', '\n' + spaces);
|
|
3608
|
+
out += "\n".concat(spaces, "const rtiTemplates = ").concat(tmp, ";");
|
|
3609
|
+
}
|
|
3425
3610
|
//out += `${spaces}/*${spaces} node.type=${node.type}\n${spaces}
|
|
3426
3611
|
// ${JSON.stringify(jsdoc)}\n${parent}\n${spaces}*/\n`;
|
|
3427
3612
|
var _loop = function _loop(name) {
|
|
3428
|
-
var type =
|
|
3613
|
+
var type = params[name];
|
|
3429
3614
|
var hasParam = _this2.nodeHasParamName(node, name);
|
|
3430
3615
|
if (!hasParam) {
|
|
3431
3616
|
var testNode = node;
|
|
3432
3617
|
if (node.type === 'BlockStatement') {
|
|
3433
3618
|
testNode = _this2.parent;
|
|
3434
3619
|
}
|
|
3435
|
-
var paramIndex = Object.keys(
|
|
3620
|
+
var paramIndex = Object.keys(params).findIndex(function (_) {
|
|
3436
3621
|
return _ === name;
|
|
3437
3622
|
});
|
|
3438
3623
|
var param = testNode.params[paramIndex];
|
|
@@ -3468,7 +3653,11 @@
|
|
|
3468
3653
|
continue;
|
|
3469
3654
|
}
|
|
3470
3655
|
var _t = JSON.stringify(type.elementType, null, 2).replaceAll('\n', '\n' + spaces);
|
|
3471
|
-
|
|
3656
|
+
if (templates) {
|
|
3657
|
+
out += "".concat(spaces, "if (!inspectTypeWithTemplates(").concat(element.name, ", ").concat(_t, ", '").concat(_loc, "', '").concat(name, "', rtiTemplates)) {\n");
|
|
3658
|
+
} else {
|
|
3659
|
+
out += "".concat(spaces, "if (!inspectType(").concat(element.name, ", ").concat(_t, ", '").concat(_loc, "', '").concat(name, "')) {\n");
|
|
3660
|
+
}
|
|
3472
3661
|
out += "".concat(spaces, " youCanAddABreakpointHere();\n").concat(spaces, "}\n");
|
|
3473
3662
|
}
|
|
3474
3663
|
} catch (err) {
|
|
@@ -3499,7 +3688,11 @@
|
|
|
3499
3688
|
continue;
|
|
3500
3689
|
}
|
|
3501
3690
|
var _t2 = JSON.stringify(subType, null, 2).replaceAll('\n', '\n' + spaces);
|
|
3502
|
-
|
|
3691
|
+
if (templates) {
|
|
3692
|
+
out += "".concat(spaces, "if (!inspectTypeWithTemplates(").concat(keyName, ", ").concat(_t2, ", '").concat(_loc, "', '").concat(name, "', rtiTemplates)) {\n");
|
|
3693
|
+
} else {
|
|
3694
|
+
out += "".concat(spaces, "if (!inspectType(").concat(keyName, ", ").concat(_t2, ", '").concat(_loc, "', '").concat(name, "')) {\n");
|
|
3695
|
+
}
|
|
3503
3696
|
out += "".concat(spaces, " youCanAddABreakpointHere();\n").concat(spaces, "}\n");
|
|
3504
3697
|
}
|
|
3505
3698
|
} catch (err) {
|
|
@@ -3537,11 +3730,15 @@
|
|
|
3537
3730
|
out += '\n';
|
|
3538
3731
|
first = false;
|
|
3539
3732
|
}
|
|
3540
|
-
|
|
3733
|
+
if (templates) {
|
|
3734
|
+
out += "".concat(spaces, "if (").concat(prevCheck, "!inspectTypeWithTemplates(").concat(name, ", ").concat(t, ", '").concat(loc, "', '").concat(name, "', rtiTemplates)) {\n");
|
|
3735
|
+
} else {
|
|
3736
|
+
out += "".concat(spaces, "if (").concat(prevCheck, "!inspectType(").concat(name, ", ").concat(t, ", '").concat(loc, "', '").concat(name, "')) {\n");
|
|
3737
|
+
}
|
|
3541
3738
|
out += "".concat(spaces, " youCanAddABreakpointHere();\n").concat(spaces, "}\n");
|
|
3542
3739
|
},
|
|
3543
3740
|
_ret;
|
|
3544
|
-
for (var name in
|
|
3741
|
+
for (var name in params) {
|
|
3545
3742
|
_ret = _loop(name);
|
|
3546
3743
|
if (_ret === 0) continue;
|
|
3547
3744
|
}
|
|
@@ -4119,6 +4316,7 @@
|
|
|
4119
4316
|
exports.nodeIsFunction = nodeIsFunction;
|
|
4120
4317
|
exports.parseJSDoc = parseJSDoc;
|
|
4121
4318
|
exports.parseJSDocSetter = parseJSDocSetter;
|
|
4319
|
+
exports.parseJSDocTemplates = parseJSDocTemplates;
|
|
4122
4320
|
exports.parseJSDocTypedef = parseJSDocTypedef;
|
|
4123
4321
|
exports.parseType = parseType;
|
|
4124
4322
|
exports.parseTypeBabelTS = parseTypeBabelTS;
|
package/index.mjs
CHANGED
|
@@ -25,24 +25,19 @@ import ts from 'typescript';
|
|
|
25
25
|
* expandType('typeof Number '); // Outputs:
|
|
26
26
|
* @param {string} type - The type string to be expanded into a structured representation.
|
|
27
27
|
* @todo Share type with expandTypeBabelTS and expandTypeDepFree
|
|
28
|
-
* @returns {string | {type: string, [key: string]: any} | undefined} The structured type
|
|
28
|
+
* @returns {string | number | boolean | {type: string, [key: string]: any} | undefined} The structured type
|
|
29
29
|
* representation obtained from parsing and converting the provided type string.
|
|
30
30
|
*/
|
|
31
31
|
function expandType(type) {
|
|
32
32
|
const ast = parseType(type);
|
|
33
|
+
if (!ast) {
|
|
34
|
+
return 'never';
|
|
35
|
+
}
|
|
33
36
|
return toSourceTS(ast);
|
|
34
37
|
}
|
|
35
|
-
/**
|
|
36
|
-
* @todo I want to use for example: import('typescript').Node
|
|
37
|
-
* But the TS types make no sense to me so far ... need to investigate more.
|
|
38
|
-
* @typedef TypeScriptType
|
|
39
|
-
* @property {object[]|undefined} typeArguments - The type arguments.
|
|
40
|
-
* @property {import('typescript').Node} typeName - The type name.
|
|
41
|
-
* @property {number} kind - The kind for `ts.SyntaxKind[kind]`.
|
|
42
|
-
*/
|
|
43
38
|
/**
|
|
44
39
|
* @param {string} str - The type string.
|
|
45
|
-
* @returns {
|
|
40
|
+
* @returns {ts.TypeNode|undefined} - The node containing all the information about the input type string.
|
|
46
41
|
*/
|
|
47
42
|
function parseType(str) {
|
|
48
43
|
// TS doesn't like ... notation in this context
|
|
@@ -53,7 +48,12 @@ function parseType(str) {
|
|
|
53
48
|
// type tmp = (...string) => 123; to have a function context
|
|
54
49
|
str = `type tmp = ${str};`;
|
|
55
50
|
const ast = ts.createSourceFile('repl.ts', str, ts.ScriptTarget.Latest, true /*setParentNodes*/);
|
|
56
|
-
|
|
51
|
+
const firstStatement = ast.statements[0];
|
|
52
|
+
if (!ts.isTypeAliasDeclaration(firstStatement)) {
|
|
53
|
+
console.warn('parseType> Expected type alias declaration, got', firstStatement, 'instead.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
return firstStatement.type;
|
|
57
57
|
}
|
|
58
58
|
/** @type {Record<string, 'missing'|'found'>} */
|
|
59
59
|
const requiredTypeofs = {};
|
|
@@ -63,7 +63,7 @@ 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 {
|
|
66
|
+
* @param {ts.TypeNode|ts.Identifier} 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
|
*/
|
|
@@ -75,52 +75,90 @@ function toSourceTS(node) {
|
|
|
75
75
|
const kind_ = ts.SyntaxKind[node.kind];
|
|
76
76
|
const {
|
|
77
77
|
AnyKeyword,
|
|
78
|
+
// parseType('any' ).kind === ts.SyntaxKind.AnyKeyword && toSourceTS(parseType('any')) === 'any'
|
|
78
79
|
ArrayType,
|
|
80
|
+
// parseType('number[]' ).kind === ts.SyntaxKind.ArrayType // todo toSourceTS(parseType('number[]')) === {type: 'array etc.
|
|
79
81
|
BooleanKeyword,
|
|
82
|
+
// parseType("boolean" ).kind === ts.SyntaxKind.BooleanKeyword
|
|
80
83
|
FunctionType,
|
|
84
|
+
// parseType("() => void" ).kind === ts.SyntaxKind.FunctionType
|
|
81
85
|
Identifier,
|
|
86
|
+
// parseType("{a: 1, b: 2}" ).members[0].name.kind === ts.SyntaxKind.Identifier
|
|
82
87
|
IntersectionType,
|
|
88
|
+
// parseType("1 & 2" ).kind === ts.SyntaxKind.IntersectionType
|
|
83
89
|
JSDocAllType,
|
|
84
|
-
|
|
90
|
+
// parseType("*" ).kind === ts.SyntaxKind.JSDocAllType
|
|
91
|
+
ImportType,
|
|
92
|
+
// parseType('import("test").Test' ).kind === ts.SyntaxKind.ImportType
|
|
85
93
|
LiteralType,
|
|
94
|
+
// parseType("123" ).kind === ts.SyntaxKind.LiteralType
|
|
86
95
|
NullKeyword,
|
|
96
|
+
// parseType("null" ).literal.kind === ts.SyntaxKind.NullKeyword
|
|
87
97
|
NumberKeyword,
|
|
98
|
+
// parseType("number" ).kind === ts.SyntaxKind.NumberKeyword
|
|
88
99
|
NumericLiteral,
|
|
100
|
+
// parseType("123" ).literal.kind === ts.SyntaxKind.NumericLiteral
|
|
89
101
|
ObjectKeyword,
|
|
102
|
+
// parseType("object" ).kind === ts.SyntaxKind.ObjectKeyword
|
|
90
103
|
Parameter,
|
|
104
|
+
// parseType("(a) => void" ).parameters[0].kind === ts.SyntaxKind.Parameter
|
|
91
105
|
ParenthesizedType,
|
|
106
|
+
// parseType("(SomeType)" ).kind === ts.SyntaxKind.ParenthesizedType
|
|
92
107
|
PropertySignature,
|
|
108
|
+
// parseType("{a: 1, b: 2}" ).members[0].kind === ts.SyntaxKind.PropertySignature
|
|
93
109
|
StringKeyword,
|
|
110
|
+
// parseType("string" ).kind === ts.SyntaxKind.StringKeyword
|
|
94
111
|
StringLiteral,
|
|
112
|
+
// parseType("'test'" ).literal.kind === ts.SyntaxKind.StringLiteral
|
|
95
113
|
ThisType,
|
|
114
|
+
// parseType("this" ).kind === ts.SyntaxKind.ThisType
|
|
96
115
|
TupleType,
|
|
116
|
+
// parseType("[1, 2, 3]" ).kind === ts.SyntaxKind.TupleType
|
|
97
117
|
TypeLiteral,
|
|
118
|
+
// parseType("{a: 1, b: 2}" ).kind === ts.SyntaxKind.TypeLiteral
|
|
98
119
|
TypeReference,
|
|
120
|
+
// parseType("SomeOtherType" ).kind === ts.SyntaxKind.TypeReference
|
|
99
121
|
UndefinedKeyword,
|
|
122
|
+
// parseType("undefined" ).kind === ts.SyntaxKind.UndefinedKeyword
|
|
100
123
|
UnionType,
|
|
124
|
+
// parseType("1|2" ).kind === ts.SyntaxKind.UnionType
|
|
101
125
|
JSDocNullableType,
|
|
126
|
+
// parseType("?lol?" ).kind === ts.SyntaxKind.JSDocNullableType
|
|
102
127
|
TrueKeyword,
|
|
128
|
+
// parseType("true" ).literal.kind === ts.SyntaxKind.TrueKeyword
|
|
103
129
|
FalseKeyword,
|
|
130
|
+
// parseType("false" ).literal.kind === ts.SyntaxKind.FalseKeyword
|
|
104
131
|
VoidKeyword,
|
|
132
|
+
// parseType("void" ).kind === ts.SyntaxKind.VoidKeyword
|
|
105
133
|
UnknownKeyword,
|
|
134
|
+
// parseType("unknown" ).kind === ts.SyntaxKind.UnknownKeyword
|
|
106
135
|
NeverKeyword,
|
|
136
|
+
// parseType("never" ).kind === ts.SyntaxKind.NeverKeyword
|
|
107
137
|
BigIntKeyword,
|
|
138
|
+
// parseType("bigint" ).kind === ts.SyntaxKind.BigIntKeyword
|
|
108
139
|
BigIntLiteral,
|
|
140
|
+
// parseType("123n" ).literal.kind === ts.SyntaxKind.BigIntLiteral
|
|
109
141
|
ConditionalType,
|
|
142
|
+
// parseType("1 extends number ? true : false").kind === ts.SyntaxKind.ConditionalType
|
|
110
143
|
IndexedAccessType,
|
|
144
|
+
// parseType('Test[123]' ).kind === ts.SyntaxKind.IndexedAccessType
|
|
145
|
+
IndexSignature,
|
|
146
|
+
// parseType('{[n: number]: string}' ).members[0].kind === ts.SyntaxKind.IndexSignature
|
|
111
147
|
RestType,
|
|
148
|
+
// parseType("[...number]" ).elements[0].kind === ts.SyntaxKind.RestType
|
|
112
149
|
TypeQuery,
|
|
113
|
-
// parseType('typeof Number')
|
|
150
|
+
// parseType('typeof Number' ).kind === ts.SyntaxKind.TypeQuery
|
|
114
151
|
TypeOperator,
|
|
115
|
-
// parseType('keyof typeof obj')
|
|
152
|
+
// parseType('keyof typeof obj' ).kind === ts.SyntaxKind.TypeOperator
|
|
116
153
|
KeyOfKeyword,
|
|
117
|
-
//
|
|
154
|
+
// parseType('keyof typeof obj' ).operator === ts.SyntaxKind.KeyOfKeyword
|
|
118
155
|
ConstructorType,
|
|
119
|
-
// parseType('new (...args: any[]) => any')
|
|
156
|
+
// parseType('new (...args: any[]) => any' ).kind === ts.SyntaxKind.ConstructorType
|
|
120
157
|
NamedTupleMember,
|
|
158
|
+
// parseType('[a: 1]' ).elements[0].kind === ts.SyntaxKind.NamedTupleMember
|
|
121
159
|
MappedType,
|
|
122
|
-
// parseType('{[K in TaskType]:
|
|
123
|
-
TypeParameter //
|
|
160
|
+
// parseType('{[K in TaskType]: 123}' ).kind === ts.SyntaxKind.MappedType
|
|
161
|
+
TypeParameter // parseType('{[K in TaskType]: 123}' ).typeParameter.kind === ts.SyntaxKind.TypeParameter
|
|
124
162
|
} = ts.SyntaxKind;
|
|
125
163
|
// console.log({typeArguments, typeName, kind_, node});
|
|
126
164
|
switch (node.kind) {
|
|
@@ -129,12 +167,18 @@ function toSourceTS(node) {
|
|
|
129
167
|
type: 'bigint'
|
|
130
168
|
};
|
|
131
169
|
case BigIntLiteral:
|
|
170
|
+
if (!ts.isBigIntLiteral(node)) {
|
|
171
|
+
throw Error("Impossible");
|
|
172
|
+
}
|
|
132
173
|
const literal = node.text.slice(0, -1); // Remove the "n"
|
|
133
174
|
return {
|
|
134
175
|
type: 'bigint',
|
|
135
176
|
literal
|
|
136
177
|
};
|
|
137
178
|
case ConditionalType:
|
|
179
|
+
if (!ts.isConditionalTypeNode(node)) {
|
|
180
|
+
throw Error("Impossible");
|
|
181
|
+
}
|
|
138
182
|
// Keys on node:
|
|
139
183
|
// ['pos', 'end', 'flags', 'modifierFlagsCache', 'transformFlags', 'parent', 'kind', 'checkType',
|
|
140
184
|
// 'extendsType', 'trueType', 'falseType', 'locals', 'nextContainer']
|
|
@@ -151,6 +195,9 @@ function toSourceTS(node) {
|
|
|
151
195
|
};
|
|
152
196
|
case ConstructorType:
|
|
153
197
|
{
|
|
198
|
+
if (!ts.isConstructorTypeNode(node)) {
|
|
199
|
+
throw Error("Impossible");
|
|
200
|
+
}
|
|
154
201
|
const _parameters = node.parameters.map(toSourceTS);
|
|
155
202
|
const _ret = toSourceTS(node.type);
|
|
156
203
|
return {
|
|
@@ -160,12 +207,18 @@ function toSourceTS(node) {
|
|
|
160
207
|
};
|
|
161
208
|
}
|
|
162
209
|
case FunctionType:
|
|
210
|
+
if (!ts.isFunctionTypeNode(node)) {
|
|
211
|
+
throw Error("Impossible");
|
|
212
|
+
}
|
|
163
213
|
const parameters = node.parameters.map(toSourceTS);
|
|
164
214
|
return {
|
|
165
215
|
type: 'function',
|
|
166
216
|
parameters
|
|
167
217
|
};
|
|
168
218
|
case IndexedAccessType:
|
|
219
|
+
if (!ts.isIndexedAccessTypeNode(node)) {
|
|
220
|
+
throw Error("Impossible");
|
|
221
|
+
}
|
|
169
222
|
const index = toSourceTS(node.indexType);
|
|
170
223
|
const object = toSourceTS(node.objectType);
|
|
171
224
|
return {
|
|
@@ -174,12 +227,18 @@ function toSourceTS(node) {
|
|
|
174
227
|
object
|
|
175
228
|
};
|
|
176
229
|
case RestType:
|
|
230
|
+
if (!ts.isRestTypeNode(node)) {
|
|
231
|
+
throw Error("Impossible");
|
|
232
|
+
}
|
|
177
233
|
const annotation = toSourceTS(node.type);
|
|
178
234
|
return {
|
|
179
235
|
type: 'rest',
|
|
180
236
|
annotation
|
|
181
237
|
};
|
|
182
238
|
case JSDocNullableType:
|
|
239
|
+
if (!ts.isJSDocNullableType(node)) {
|
|
240
|
+
throw Error("Impossible");
|
|
241
|
+
}
|
|
183
242
|
const t = toSourceTS(node.type);
|
|
184
243
|
return {
|
|
185
244
|
type: 'union',
|
|
@@ -187,6 +246,9 @@ function toSourceTS(node) {
|
|
|
187
246
|
};
|
|
188
247
|
case MappedType:
|
|
189
248
|
{
|
|
249
|
+
if (!ts.isMappedTypeNode(node)) {
|
|
250
|
+
throw Error("Impossible");
|
|
251
|
+
}
|
|
190
252
|
const result = toSourceTS(node.type);
|
|
191
253
|
const parameter = node.typeParameter;
|
|
192
254
|
if (parameter.kind === TypeParameter) {
|
|
@@ -206,6 +268,9 @@ function toSourceTS(node) {
|
|
|
206
268
|
// todo work out more: const jsdoc = `(...a: ...number) => 123
|
|
207
269
|
// TS even thinks it's two parameters... just go for array/[]
|
|
208
270
|
case Parameter:
|
|
271
|
+
if (!ts.isParameter(node)) {
|
|
272
|
+
throw Error("Impossible");
|
|
273
|
+
}
|
|
209
274
|
const type = node.type ? toSourceTS(node.type) : 'any';
|
|
210
275
|
const name = toSourceTS(node.name);
|
|
211
276
|
const ret = {
|
|
@@ -220,6 +285,9 @@ function toSourceTS(node) {
|
|
|
220
285
|
}
|
|
221
286
|
return ret;
|
|
222
287
|
case TypeQuery:
|
|
288
|
+
if (!ts.isTypeQueryNode(node)) {
|
|
289
|
+
throw Error("Impossible");
|
|
290
|
+
}
|
|
223
291
|
const argument = toSourceTS(node.exprName);
|
|
224
292
|
// Notify Asserter class that we have to register variables with this name
|
|
225
293
|
if (!requiredTypeofs[argument]) {
|
|
@@ -230,6 +298,9 @@ function toSourceTS(node) {
|
|
|
230
298
|
argument
|
|
231
299
|
};
|
|
232
300
|
case TypeOperator:
|
|
301
|
+
if (!ts.isTypeOperatorNode(node)) {
|
|
302
|
+
throw Error("Impossible");
|
|
303
|
+
}
|
|
233
304
|
if (node.operator === KeyOfKeyword) {
|
|
234
305
|
const _argument = toSourceTS(node.type);
|
|
235
306
|
return {
|
|
@@ -240,6 +311,9 @@ function toSourceTS(node) {
|
|
|
240
311
|
console.warn("unimplemented TypeOperator", node);
|
|
241
312
|
case TypeReference:
|
|
242
313
|
{
|
|
314
|
+
if (!ts.isTypeReferenceNode(node)) {
|
|
315
|
+
throw Error("Impossible");
|
|
316
|
+
}
|
|
243
317
|
if ((typeName.text === 'Object' || typeName.text === 'Record') && (typeArguments == null ? void 0 : typeArguments.length) === 2) {
|
|
244
318
|
return {
|
|
245
319
|
type: 'record',
|
|
@@ -295,14 +369,16 @@ function toSourceTS(node) {
|
|
|
295
369
|
args
|
|
296
370
|
};
|
|
297
371
|
}
|
|
298
|
-
case StringKeyword:
|
|
299
|
-
return node.getText();
|
|
300
|
-
case NumberKeyword:
|
|
301
|
-
return node.getText();
|
|
302
372
|
case NamedTupleMember:
|
|
373
|
+
if (!ts.isNamedTupleMember(node)) {
|
|
374
|
+
throw Error("Impossible");
|
|
375
|
+
}
|
|
303
376
|
return toSourceTS(node.type);
|
|
304
377
|
case IntersectionType:
|
|
305
378
|
{
|
|
379
|
+
if (!ts.isIntersectionTypeNode(node)) {
|
|
380
|
+
throw Error("Impossible");
|
|
381
|
+
}
|
|
306
382
|
const _members = node.types.map(toSourceTS);
|
|
307
383
|
return {
|
|
308
384
|
type: 'intersection',
|
|
@@ -310,35 +386,87 @@ function toSourceTS(node) {
|
|
|
310
386
|
};
|
|
311
387
|
}
|
|
312
388
|
case TupleType:
|
|
389
|
+
if (!ts.isTupleTypeNode(node)) {
|
|
390
|
+
throw Error("Impossible");
|
|
391
|
+
}
|
|
313
392
|
const elements = node.elements.map(toSourceTS);
|
|
314
393
|
return {
|
|
315
394
|
type: 'tuple',
|
|
316
395
|
elements
|
|
317
396
|
};
|
|
318
397
|
case UnionType:
|
|
398
|
+
if (!ts.isUnionTypeNode(node)) {
|
|
399
|
+
throw Error("Impossible");
|
|
400
|
+
}
|
|
319
401
|
const members = node.types.map(toSourceTS);
|
|
320
402
|
return {
|
|
321
403
|
type: 'union',
|
|
322
404
|
members
|
|
323
405
|
};
|
|
324
406
|
case TypeLiteral:
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
properties
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
407
|
+
{
|
|
408
|
+
if (!ts.isTypeLiteralNode(node)) {
|
|
409
|
+
throw Error("Impossible");
|
|
410
|
+
}
|
|
411
|
+
const properties = {};
|
|
412
|
+
/** @type {object[]} */
|
|
413
|
+
let indexSignatures;
|
|
414
|
+
node.members.forEach(member => {
|
|
415
|
+
if (member.kind === IndexSignature) {
|
|
416
|
+
var _indexSignatures;
|
|
417
|
+
indexSignatures = (_indexSignatures = indexSignatures) != null ? _indexSignatures : [];
|
|
418
|
+
indexSignatures.push(toSourceTS(member));
|
|
419
|
+
} else if (member.kind === PropertySignature) {
|
|
420
|
+
if (!ts.isPropertySignature(member)) {
|
|
421
|
+
throw Error("Impossible");
|
|
422
|
+
}
|
|
423
|
+
const name = toSourceTS(member.name);
|
|
424
|
+
const type = toSourceTS(member.type);
|
|
425
|
+
properties[name] = type;
|
|
426
|
+
} else {
|
|
427
|
+
console.warn('TypeLiteral: unhandled member', member);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
const _ret2 = {
|
|
431
|
+
type: 'object'
|
|
432
|
+
};
|
|
433
|
+
if (Object.keys(properties).length) {
|
|
434
|
+
_ret2.properties = properties;
|
|
435
|
+
}
|
|
436
|
+
if (indexSignatures) {
|
|
437
|
+
_ret2.indexSignatures = indexSignatures;
|
|
438
|
+
}
|
|
439
|
+
return _ret2;
|
|
440
|
+
}
|
|
335
441
|
case PropertySignature:
|
|
442
|
+
if (!ts.isPropertySignature(node)) {
|
|
443
|
+
throw Error("Impossible");
|
|
444
|
+
}
|
|
336
445
|
console.warn('toSourceTS> should not happen, handled by TypeLiteral directly');
|
|
337
446
|
return `${toSourceTS(node.name)}: ${toSourceTS(node.type)}`;
|
|
447
|
+
case IndexSignature:
|
|
448
|
+
if (!ts.isIndexSignatureDeclaration(node)) {
|
|
449
|
+
throw Error("Impossible");
|
|
450
|
+
}
|
|
451
|
+
// Only possible modifier I know of, but we don't need it:
|
|
452
|
+
// {readonly [n: number]: string, length: number}
|
|
453
|
+
const indexType = toSourceTS(node.type);
|
|
454
|
+
const indexParameters = node.parameters.map(toSourceTS);
|
|
455
|
+
return {
|
|
456
|
+
type: 'indexSignature',
|
|
457
|
+
indexType,
|
|
458
|
+
indexParameters
|
|
459
|
+
};
|
|
338
460
|
case Identifier:
|
|
461
|
+
if (!ts.isIdentifier(node)) {
|
|
462
|
+
throw Error("Impossible");
|
|
463
|
+
}
|
|
339
464
|
return node.text;
|
|
340
465
|
case ArrayType:
|
|
341
466
|
{
|
|
467
|
+
if (!ts.isArrayTypeNode(node)) {
|
|
468
|
+
throw Error("Impossible");
|
|
469
|
+
}
|
|
342
470
|
const elementType = toSourceTS(node.elementType);
|
|
343
471
|
return {
|
|
344
472
|
type: 'array',
|
|
@@ -346,18 +474,23 @@ function toSourceTS(node) {
|
|
|
346
474
|
};
|
|
347
475
|
}
|
|
348
476
|
case LiteralType:
|
|
477
|
+
if (!ts.isLiteralTypeNode(node)) {
|
|
478
|
+
throw Error("Impossible");
|
|
479
|
+
}
|
|
349
480
|
return toSourceTS(node.literal);
|
|
350
481
|
case AnyKeyword:
|
|
351
482
|
case BooleanKeyword:
|
|
352
|
-
|
|
353
|
-
case
|
|
483
|
+
case StringKeyword:
|
|
484
|
+
case NeverKeyword:
|
|
354
485
|
case NullKeyword:
|
|
355
|
-
case
|
|
356
|
-
case ThisType:
|
|
486
|
+
case NumberKeyword:
|
|
357
487
|
case UndefinedKeyword:
|
|
358
|
-
case VoidKeyword:
|
|
359
488
|
case UnknownKeyword:
|
|
360
|
-
case
|
|
489
|
+
case VoidKeyword:
|
|
490
|
+
// ts.SyntaxKind[parseType("*").kind] === 'JSDocAllType'
|
|
491
|
+
case JSDocAllType:
|
|
492
|
+
case ThisType:
|
|
493
|
+
case StringLiteral:
|
|
361
494
|
return node.getText();
|
|
362
495
|
case TrueKeyword:
|
|
363
496
|
return true;
|
|
@@ -371,9 +504,16 @@ function toSourceTS(node) {
|
|
|
371
504
|
properties: {}
|
|
372
505
|
};
|
|
373
506
|
case ParenthesizedType:
|
|
507
|
+
if (!ts.isParenthesizedTypeNode(node)) {
|
|
508
|
+
throw Error("Impossible");
|
|
509
|
+
}
|
|
374
510
|
// fall-through for parentheses
|
|
375
511
|
return toSourceTS(node.type);
|
|
376
|
-
case
|
|
512
|
+
case ImportType:
|
|
513
|
+
if (!ts.isImportTypeNode(node)) {
|
|
514
|
+
throw Error("Impossible");
|
|
515
|
+
}
|
|
516
|
+
/** @todo Handle case without any qualifier like `import('test')` */
|
|
377
517
|
return toSourceTS(node.qualifier);
|
|
378
518
|
default:
|
|
379
519
|
// const test = {};
|
|
@@ -588,18 +728,25 @@ function simplifyType(type, optional) {
|
|
|
588
728
|
return type;
|
|
589
729
|
}
|
|
590
730
|
|
|
731
|
+
/**
|
|
732
|
+
* @typedef {ReturnType<typeof parseJSDoc>} ParseJSDocReturnType
|
|
733
|
+
*/
|
|
734
|
+
/**
|
|
735
|
+
* @typedef {typeof expandTypeDepFree} ExpandType
|
|
736
|
+
* @typedef {ReturnType<ExpandType>} ExpandTypeReturnType
|
|
737
|
+
*/
|
|
591
738
|
/**
|
|
592
739
|
* Parses JSDoc comments to extract parameter type information.
|
|
593
740
|
*
|
|
594
741
|
* @param {string} src - The JSDoc comment string to parse.
|
|
595
|
-
* @param {
|
|
596
|
-
* @returns {Record<string,
|
|
742
|
+
* @param {ExpandType} [expandType] - An optional function to process the types found in the JSDoc.
|
|
743
|
+
* @returns {Record<string, ExpandTypeReturnType> | undefined} An object mapping parameter names to their parsed types, or undefined if no parameters are found.
|
|
597
744
|
*/
|
|
598
745
|
function parseJSDoc(src, expandType = expandTypeDepFree) {
|
|
599
746
|
// Parse something like: @param {Object} [kwargs={}] Optional arguments.
|
|
600
747
|
const regex = /@param \{(.*?)\} ([\[\]a-zA-Z0-9_$=\{\}\.'" ]+)/g;
|
|
601
748
|
const matches = [...src.matchAll(regex)];
|
|
602
|
-
/** @type {Record<string,
|
|
749
|
+
/** @type {Record<string, ExpandTypeReturnType>} */
|
|
603
750
|
const params = Object.create(null);
|
|
604
751
|
matches.forEach(_ => {
|
|
605
752
|
const type = expandType(_[1].trim());
|
|
@@ -623,7 +770,6 @@ function parseJSDoc(src, expandType = expandTypeDepFree) {
|
|
|
623
770
|
const parts = name.split(/[\[\]]*\./);
|
|
624
771
|
let properties = params;
|
|
625
772
|
for (const part of parts) {
|
|
626
|
-
/** @type {object} */
|
|
627
773
|
const toptype = properties[part];
|
|
628
774
|
if (!toptype) {
|
|
629
775
|
// No toptype means we resolved as far as possible, now we can add `simplifiedType`.
|
|
@@ -670,6 +816,34 @@ function parseJSDocSetter(src, expandType = expandTypeDepFree) {
|
|
|
670
816
|
}
|
|
671
817
|
}
|
|
672
818
|
|
|
819
|
+
/**
|
|
820
|
+
* @typedef {typeof expandTypeDepFree} ExpandType
|
|
821
|
+
* @typedef {ReturnType<ExpandType>} ExpandTypeReturnType
|
|
822
|
+
*/
|
|
823
|
+
/**
|
|
824
|
+
* Parses JSDoc comments to extract parameter type information.
|
|
825
|
+
*
|
|
826
|
+
* @param {string} src - The JSDoc comment string to parse.
|
|
827
|
+
* @param {ExpandType} [expandType] - An optional function to process the types found in the JSDoc.
|
|
828
|
+
* @returns {Record<string, ExpandTypeReturnType> | undefined} An object mapping template names to their parsed types,
|
|
829
|
+
* or `undefined` if no template tags were found.
|
|
830
|
+
*/
|
|
831
|
+
function parseJSDocTemplates(src, expandType = expandTypeDepFree) {
|
|
832
|
+
const regexTemplateTyped = /@template \{(.*?)\} ([a-zA-Z0-9_$=]+)/g;
|
|
833
|
+
const matches = [...src.matchAll(regexTemplateTyped)];
|
|
834
|
+
if (!matches.length) {
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
/** @type {Record<string, ExpandTypeReturnType>} */
|
|
838
|
+
const templates = Object.create(null);
|
|
839
|
+
matches.forEach(_ => {
|
|
840
|
+
const type = expandType(_[1].trim());
|
|
841
|
+
const name = _[2].trim();
|
|
842
|
+
templates[name] = type;
|
|
843
|
+
});
|
|
844
|
+
return templates;
|
|
845
|
+
}
|
|
846
|
+
|
|
673
847
|
/**
|
|
674
848
|
* Extracts the parameter name and its optionality from a JSDoc parameter string.
|
|
675
849
|
*
|
|
@@ -2619,14 +2793,14 @@ class Stringifier {
|
|
|
2619
2793
|
}
|
|
2620
2794
|
|
|
2621
2795
|
/** @typedef {import('@babel/types').Node } Node */
|
|
2622
|
-
/** @typedef {import(
|
|
2623
|
-
/** @typedef {import(
|
|
2624
|
-
/** @typedef {import('./stat.js').Stat
|
|
2796
|
+
/** @typedef {import('@babel/types').ClassMethod } ClassMethod */
|
|
2797
|
+
/** @typedef {import('@babel/types').ClassPrivateMethod} ClassPrivateMethod */
|
|
2798
|
+
/** @typedef {import('./stat.js').Stat } Stat */
|
|
2625
2799
|
/**
|
|
2626
2800
|
* @typedef {object} Options
|
|
2627
2801
|
* @property {boolean} [forceCurly] - Determines whether curly braces are enforced in Stringifier.
|
|
2628
2802
|
* @property {boolean} [validateDivision] - Indicates whether division operations should be validated.
|
|
2629
|
-
* @property {
|
|
2803
|
+
* @property {import('./parseJSDoc.js').ExpandType} [expandType] - A function that expands shorthand types into full descriptions.
|
|
2630
2804
|
* @property {string} [filename] - The name of a file to which the instance pertains.
|
|
2631
2805
|
* @property {boolean} [addHeader] - Whether to add import declarations headers. Defaults to true.
|
|
2632
2806
|
* @property {string[]} [ignoreLocations] - Ignore these locations because they are known false-positives.
|
|
@@ -2879,9 +3053,9 @@ class Asserter extends Stringifier {
|
|
|
2879
3053
|
}
|
|
2880
3054
|
/**
|
|
2881
3055
|
* @param {Node} node - The Babel AST node.
|
|
2882
|
-
* @returns {undefined
|
|
3056
|
+
* @returns {string|undefined} The JSDoc comment of `node`.
|
|
2883
3057
|
*/
|
|
2884
|
-
|
|
3058
|
+
getLeadingComment(node) {
|
|
2885
3059
|
if (node.type === 'BlockStatement') {
|
|
2886
3060
|
node = this.parent;
|
|
2887
3061
|
}
|
|
@@ -2907,28 +3081,61 @@ class Asserter extends Stringifier {
|
|
|
2907
3081
|
if (leadingComments && leadingComments.length) {
|
|
2908
3082
|
const lastComment = leadingComments[leadingComments.length - 1];
|
|
2909
3083
|
if (lastComment.type === "CommentBlock") {
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
3084
|
+
return lastComment.value;
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
/**
|
|
3089
|
+
* @param {Node} node - The Babel AST node.
|
|
3090
|
+
* @todo ESLint problem:
|
|
3091
|
+
* returns {import('./parseJSDoc.js').ParseJSDocReturnType} The return value of `parseJSDoc`
|
|
3092
|
+
* returns {Record<string, import('./parseJSDoc.js').ExpandTypeReturnType> | undefined} The
|
|
3093
|
+
* return value of `parseJSDoc`.
|
|
3094
|
+
* @returns {Record<string, any>|undefined} asd
|
|
3095
|
+
*/
|
|
3096
|
+
getJSDoc(node) {
|
|
3097
|
+
const comment = this.getLeadingComment(node);
|
|
3098
|
+
if (!comment) {
|
|
3099
|
+
return;
|
|
3100
|
+
}
|
|
3101
|
+
if (comment.includes('@event')) {
|
|
3102
|
+
return;
|
|
3103
|
+
}
|
|
3104
|
+
if (comment.includes('@ignoreRTI')) {
|
|
3105
|
+
return;
|
|
3106
|
+
}
|
|
3107
|
+
// Need to do same resolving as in: this.getLeadingComment(node)
|
|
3108
|
+
if (node.type === 'BlockStatement') {
|
|
3109
|
+
node = this.parent;
|
|
3110
|
+
}
|
|
3111
|
+
if (node.type === 'ClassMethod') {
|
|
3112
|
+
if (node.kind === 'get') {
|
|
3113
|
+
// JSDoc on a getter is just some documentation.
|
|
3114
|
+
return;
|
|
3115
|
+
} else if (node.kind === 'set') {
|
|
3116
|
+
if (node.params.length !== 1) {
|
|
3117
|
+
this.warn("getJSDoc> setters require exactly one argument");
|
|
2925
3118
|
}
|
|
2926
|
-
|
|
3119
|
+
const setterType = parseJSDocSetter(comment, this.expandType);
|
|
3120
|
+
if (!setterType) {
|
|
2927
3121
|
return;
|
|
2928
3122
|
}
|
|
2929
|
-
|
|
3123
|
+
const paramName = this.getNameOfParam(node.params[0]);
|
|
3124
|
+
const _params = {
|
|
3125
|
+
[paramName]: setterType
|
|
3126
|
+
};
|
|
3127
|
+
return {
|
|
3128
|
+
templates: undefined,
|
|
3129
|
+
params: _params
|
|
3130
|
+
};
|
|
2930
3131
|
}
|
|
2931
3132
|
}
|
|
3133
|
+
const templates = parseJSDocTemplates(comment);
|
|
3134
|
+
const params = parseJSDoc(comment, this.expandType);
|
|
3135
|
+
return {
|
|
3136
|
+
templates,
|
|
3137
|
+
params
|
|
3138
|
+
};
|
|
2932
3139
|
}
|
|
2933
3140
|
/**
|
|
2934
3141
|
* Retrieves the name of a parameter from a Babel AST node.
|
|
@@ -2947,8 +3154,7 @@ class Asserter extends Stringifier {
|
|
|
2947
3154
|
return param.left.name;
|
|
2948
3155
|
}
|
|
2949
3156
|
}
|
|
2950
|
-
|
|
2951
|
-
this.warn("unable to extra name from param in specified way - may contain too much information");
|
|
3157
|
+
this.warn("Unable to retrieve name from param in specified way - may contain too much information.");
|
|
2952
3158
|
return this.toSource(param);
|
|
2953
3159
|
}
|
|
2954
3160
|
statsReset() {
|
|
@@ -3067,6 +3273,17 @@ class Asserter extends Stringifier {
|
|
|
3067
3273
|
stat.unchecked++;
|
|
3068
3274
|
return '';
|
|
3069
3275
|
}
|
|
3276
|
+
const {
|
|
3277
|
+
templates,
|
|
3278
|
+
params
|
|
3279
|
+
} = jsdoc;
|
|
3280
|
+
if (!params) {
|
|
3281
|
+
console.warn("This should never happen, please check your input code.", this.getLeadingComment(node), {
|
|
3282
|
+
jsdoc
|
|
3283
|
+
});
|
|
3284
|
+
stat.unchecked++;
|
|
3285
|
+
return '';
|
|
3286
|
+
}
|
|
3070
3287
|
stat.checked++;
|
|
3071
3288
|
const {
|
|
3072
3289
|
spaces
|
|
@@ -3077,17 +3294,21 @@ class Asserter extends Stringifier {
|
|
|
3077
3294
|
if (this.ignoreLocations.includes(loc)) {
|
|
3078
3295
|
return '// IGNORE RTI TYPE VALIDATIONS, KNOWN ISSUES\n';
|
|
3079
3296
|
}
|
|
3297
|
+
if (templates) {
|
|
3298
|
+
const tmp = JSON.stringify(templates, null, 2).replaceAll('\n', '\n' + spaces);
|
|
3299
|
+
out += `\n${spaces}const rtiTemplates = ${tmp};`;
|
|
3300
|
+
}
|
|
3080
3301
|
//out += `${spaces}/*${spaces} node.type=${node.type}\n${spaces}
|
|
3081
3302
|
// ${JSON.stringify(jsdoc)}\n${parent}\n${spaces}*/\n`;
|
|
3082
|
-
for (let name in
|
|
3083
|
-
const type =
|
|
3303
|
+
for (let name in params) {
|
|
3304
|
+
const type = params[name];
|
|
3084
3305
|
const hasParam = this.nodeHasParamName(node, name);
|
|
3085
3306
|
if (!hasParam) {
|
|
3086
3307
|
let testNode = node;
|
|
3087
3308
|
if (node.type === 'BlockStatement') {
|
|
3088
3309
|
testNode = this.parent;
|
|
3089
3310
|
}
|
|
3090
|
-
const paramIndex = Object.keys(
|
|
3311
|
+
const paramIndex = Object.keys(params).findIndex(_ => _ === name);
|
|
3091
3312
|
const param = testNode.params[paramIndex];
|
|
3092
3313
|
if (param) {
|
|
3093
3314
|
const isObjectPattern = param.type === 'ObjectPattern';
|
|
@@ -3117,7 +3338,11 @@ class Asserter extends Stringifier {
|
|
|
3117
3338
|
continue;
|
|
3118
3339
|
}
|
|
3119
3340
|
const _t = JSON.stringify(type.elementType, null, 2).replaceAll('\n', '\n' + spaces);
|
|
3120
|
-
|
|
3341
|
+
if (templates) {
|
|
3342
|
+
out += `${spaces}if (!inspectTypeWithTemplates(${element.name}, ${_t}, '${_loc}', '${name}', rtiTemplates)) {\n`;
|
|
3343
|
+
} else {
|
|
3344
|
+
out += `${spaces}if (!inspectType(${element.name}, ${_t}, '${_loc}', '${name}')) {\n`;
|
|
3345
|
+
}
|
|
3121
3346
|
out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`;
|
|
3122
3347
|
}
|
|
3123
3348
|
continue;
|
|
@@ -3139,7 +3364,11 @@ class Asserter extends Stringifier {
|
|
|
3139
3364
|
continue;
|
|
3140
3365
|
}
|
|
3141
3366
|
const _t2 = JSON.stringify(subType, null, 2).replaceAll('\n', '\n' + spaces);
|
|
3142
|
-
|
|
3367
|
+
if (templates) {
|
|
3368
|
+
out += `${spaces}if (!inspectTypeWithTemplates(${keyName}, ${_t2}, '${_loc}', '${name}', rtiTemplates)) {\n`;
|
|
3369
|
+
} else {
|
|
3370
|
+
out += `${spaces}if (!inspectType(${keyName}, ${_t2}, '${_loc}', '${name}')) {\n`;
|
|
3371
|
+
}
|
|
3143
3372
|
out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`;
|
|
3144
3373
|
}
|
|
3145
3374
|
continue;
|
|
@@ -3172,7 +3401,11 @@ class Asserter extends Stringifier {
|
|
|
3172
3401
|
out += '\n';
|
|
3173
3402
|
first = false;
|
|
3174
3403
|
}
|
|
3175
|
-
|
|
3404
|
+
if (templates) {
|
|
3405
|
+
out += `${spaces}if (${prevCheck}!inspectTypeWithTemplates(${name}, ${t}, '${_loc3}', '${name}', rtiTemplates)) {\n`;
|
|
3406
|
+
} else {
|
|
3407
|
+
out += `${spaces}if (${prevCheck}!inspectType(${name}, ${t}, '${_loc3}', '${name}')) {\n`;
|
|
3408
|
+
}
|
|
3176
3409
|
out += `${spaces} youCanAddABreakpointHere();\n${spaces}}\n`;
|
|
3177
3410
|
}
|
|
3178
3411
|
return out;
|
|
@@ -3698,4 +3931,4 @@ function toSourceBabelTS(node) {
|
|
|
3698
3931
|
}
|
|
3699
3932
|
}
|
|
3700
3933
|
|
|
3701
|
-
export { Asserter, Stringifier, addTypeChecks, ast2json, ast2jsonForComparison, code2ast2code, compareAST, expandType, expandTypeBabelTS, expandTypeDepFree, extractCurlyContent, extractNameAndOptionality, nodeIsFunction, parseJSDoc, parseJSDocSetter, parseJSDocTypedef, parseType, parseTypeBabelTS, requiredTypeofs, simplifyType, toSourceBabelTS, toSourceTS, trimEndSpaces };
|
|
3934
|
+
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 };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bin": "bin.js",
|
|
3
3
|
"name": "@runtime-type-inspector/transpiler",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.3.0",
|
|
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": "^3.
|
|
22
|
+
"@runtime-type-inspector/runtime": "^3.3.0",
|
|
23
23
|
"typescript": "^5.1.6"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|