@runtime-type-inspector/transpiler 2.2.2 → 2.2.3
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 +1068 -35
- package/index.mjs +1063 -33
- package/package.json +2 -2
- package/types.d.ts +0 -970
package/index.cjs
CHANGED
|
@@ -258,11 +258,47 @@
|
|
|
258
258
|
return typeof key === "symbol" ? key : String(key);
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
/**
|
|
262
|
+
* @todo expandTypeDepFree doesn't support "complicated" types.
|
|
263
|
+
* For actual builds, we use expandType() anyway (which is based on TypeScript).
|
|
264
|
+
* But since TypeScript is a huge dependency, I'm looking into BabelFlow/BabelTypescript parser.
|
|
265
|
+
* Comparing AST's like this usually helps to find bugs or potential issues,
|
|
266
|
+
* while we can benchmark for best performance too.
|
|
267
|
+
* @example
|
|
268
|
+
* const tooComplex = 'Array<string|{chunks?: undefined|Array<{language: string|null, timestamp: Array<number|null>, text: string}>}>';
|
|
269
|
+
* console.log(expandTypeDepFree(tooComplex));
|
|
270
|
+
*/
|
|
271
|
+
/**
|
|
272
|
+
* @typedef {object} ExpandTypeReturnValue
|
|
273
|
+
* @property {'array' | 'union' | 'record' | 'tuple' | 'object' | 'promise' | 'typeof'} type - The type.
|
|
274
|
+
* @property {object | string} [elementType] - For Array.
|
|
275
|
+
* @property {object | string} [key] - For Record<key, val>
|
|
276
|
+
* @property {object | string} [val] - For Record<key, val>
|
|
277
|
+
* @property {(object | string)[]} [members] - For unions.
|
|
278
|
+
* @property {object | string} [properties] - For objects.
|
|
279
|
+
* @property {(object | string)[]} [elements] - For tuples.
|
|
280
|
+
* @property {object | string} [argument] - For typeof.
|
|
281
|
+
*/
|
|
282
|
+
/**
|
|
283
|
+
* 'DepFree' refers to the fact that this function has no dependencies,
|
|
284
|
+
* while `expandType` depends on TypeScript itself for maximum compatibility.
|
|
285
|
+
* @example
|
|
286
|
+
* expandTypeDepFree('(123) '); // Outputs: '123'
|
|
287
|
+
* expandTypeDepFree('Array<number> '); // Outputs: { type: 'array', elementType: 'number' }
|
|
288
|
+
* expandTypeDepFree('Array<(123) > '); // Outputs: { type: 'array', elementType: '123' }
|
|
289
|
+
* expandTypeDepFree(' ( ( 123 ) ) '); // Outputs: '123'
|
|
290
|
+
* expandTypeDepFree(' (string ) |(number ) '); // Outputs: { type: 'union', members: ['string', 'number'] }
|
|
291
|
+
* expandTypeDepFree(' (( Object ) ) '); // Outputs: { type: 'object', properties: {} }
|
|
292
|
+
* @param {string} type - The input type to expand.
|
|
293
|
+
* @returns {string | ExpandTypeReturnValue} Object containing parsed information from type string.
|
|
294
|
+
*/
|
|
261
295
|
function expandTypeDepFree(type) {
|
|
262
296
|
type = type.trim();
|
|
297
|
+
// '(123)' -> '123'
|
|
263
298
|
while (!type.includes('|') && type[0] === '(' && type[type.length - 1] === ')') {
|
|
264
299
|
type = type.slice(1, -1).trim();
|
|
265
300
|
}
|
|
301
|
+
// (1) Rest parameters like ...string
|
|
266
302
|
if (type[0] === '.' && type[1] === '.' && type[2] === '.') {
|
|
267
303
|
var elementType = type.slice(3);
|
|
268
304
|
return {
|
|
@@ -270,6 +306,8 @@
|
|
|
270
306
|
elementType: elementType
|
|
271
307
|
};
|
|
272
308
|
}
|
|
309
|
+
// (2)
|
|
310
|
+
// Array<...>
|
|
273
311
|
if (type.startsWith("Array<") && type.endsWith('>')) {
|
|
274
312
|
var typeSlice = type.slice(6, -1);
|
|
275
313
|
var _elementType = expandTypeDepFree(typeSlice);
|
|
@@ -278,6 +316,7 @@
|
|
|
278
316
|
elementType: _elementType
|
|
279
317
|
};
|
|
280
318
|
}
|
|
319
|
+
// Promise<...>
|
|
281
320
|
if (type.startsWith("Promise<") && type.endsWith('>')) {
|
|
282
321
|
var _typeSlice = type.slice(8, -1);
|
|
283
322
|
var _elementType2 = expandTypeDepFree(_typeSlice);
|
|
@@ -286,6 +325,7 @@
|
|
|
286
325
|
elementType: _elementType2
|
|
287
326
|
};
|
|
288
327
|
}
|
|
328
|
+
// (3) Object<...> or Record<...>
|
|
289
329
|
if ((type.startsWith("Object<") || type.startsWith("Record<")) && type.endsWith('>')) {
|
|
290
330
|
var recordSlice = type.slice(7, -1);
|
|
291
331
|
var firstComma = recordSlice.indexOf(',');
|
|
@@ -300,8 +340,9 @@
|
|
|
300
340
|
val: expandTypeDepFree(val)
|
|
301
341
|
};
|
|
302
342
|
}
|
|
343
|
+
// (4) {...}
|
|
303
344
|
if (type[0] === '{' && type[type.length - 1] === '}') {
|
|
304
|
-
var propertiesArray = type.slice(1, -1).split(',');
|
|
345
|
+
var propertiesArray = type.slice(1, -1).split(','); // ['entity: Entity', ' app: AppBase']
|
|
305
346
|
var properties = {};
|
|
306
347
|
propertiesArray.forEach(function (_) {
|
|
307
348
|
var _$split$map = _.split(":").map(function (_) {
|
|
@@ -321,6 +362,7 @@
|
|
|
321
362
|
properties: properties
|
|
322
363
|
};
|
|
323
364
|
}
|
|
365
|
+
// (5) expand unions
|
|
324
366
|
var members = type.split("|");
|
|
325
367
|
if (members.length >= 2) {
|
|
326
368
|
members.forEach(function (_, i) {
|
|
@@ -331,6 +373,8 @@
|
|
|
331
373
|
members: members.map(expandTypeDepFree)
|
|
332
374
|
};
|
|
333
375
|
}
|
|
376
|
+
// (6) expand [] Arrays
|
|
377
|
+
// Test arrays: new pc.Mat3().set([1, 2, 3, "asd"])
|
|
334
378
|
if (type.endsWith("[]")) {
|
|
335
379
|
var _typeSlice2 = type.slice(0, -2);
|
|
336
380
|
return {
|
|
@@ -338,13 +382,15 @@
|
|
|
338
382
|
elementType: expandTypeDepFree(_typeSlice2)
|
|
339
383
|
};
|
|
340
384
|
}
|
|
385
|
+
// (7) expand tuples
|
|
341
386
|
if (type[0] === '[' && type[type.length - 1] === ']') {
|
|
342
|
-
var elements = type.slice(1, -1).split(',');
|
|
387
|
+
var elements = type.slice(1, -1).split(','); // ['null', ' Texture', ' Texture', ' Texture', ' Texture', ' Texture', ' Texture']
|
|
343
388
|
return {
|
|
344
389
|
type: 'tuple',
|
|
345
390
|
elements: elements.map(expandTypeDepFree)
|
|
346
391
|
};
|
|
347
392
|
}
|
|
393
|
+
// (8) expand typeof expressions
|
|
348
394
|
if (type.startsWith('typeof ')) {
|
|
349
395
|
var argument = expandTypeDepFree(type.substring(7));
|
|
350
396
|
return {
|
|
@@ -361,6 +407,14 @@
|
|
|
361
407
|
return type;
|
|
362
408
|
}
|
|
363
409
|
|
|
410
|
+
/** @typedef {import('@babel/types').Node} Node */
|
|
411
|
+
/** @typedef {import('@babel/types').Function} Function */
|
|
412
|
+
/**
|
|
413
|
+
* Checks if the provided node is a function-like structure.
|
|
414
|
+
*
|
|
415
|
+
* @param {Node} node - The Babel AST node to be tested.
|
|
416
|
+
* @returns {node is Function} - `true` if the node is a function-like structure, otherwise `false`.
|
|
417
|
+
*/
|
|
364
418
|
function nodeIsFunction(node) {
|
|
365
419
|
switch (node.type) {
|
|
366
420
|
case 'ArrowFunctionExpression':
|
|
@@ -374,12 +428,23 @@
|
|
|
374
428
|
return false;
|
|
375
429
|
}
|
|
376
430
|
|
|
431
|
+
/**
|
|
432
|
+
* @typedef DocType
|
|
433
|
+
* @property {boolean} optional - Type is optional.
|
|
434
|
+
*/
|
|
435
|
+
/**
|
|
436
|
+
* @param {string | DocType} type - The type.
|
|
437
|
+
* @param {boolean} optional - Optionality
|
|
438
|
+
* @returns {string | DocType} The simplified type.
|
|
439
|
+
*/
|
|
377
440
|
function simplifyType(type, optional) {
|
|
441
|
+
// If it's already an object, just set optionality.
|
|
378
442
|
if (type instanceof Object) {
|
|
379
443
|
type.optional = optional;
|
|
380
444
|
} else if (typeof type === 'string') {
|
|
381
445
|
type = type.trim();
|
|
382
446
|
if (type !== 'object' && type !== 'object[]' && type !== 'union' && !optional) {
|
|
447
|
+
// console.log("simplify", type);
|
|
383
448
|
return type;
|
|
384
449
|
}
|
|
385
450
|
type = {
|
|
@@ -392,46 +457,68 @@
|
|
|
392
457
|
}
|
|
393
458
|
if (type.type === 'object' && type.properties && Object.keys(type.properties).length === 0) {
|
|
394
459
|
delete type.properties;
|
|
460
|
+
// console.log("delete empty", type);
|
|
395
461
|
}
|
|
462
|
+
|
|
396
463
|
return type;
|
|
397
464
|
}
|
|
398
465
|
|
|
466
|
+
/**
|
|
467
|
+
* Parses JSDoc comments to extract parameter type information.
|
|
468
|
+
*
|
|
469
|
+
* @param {string} src - The JSDoc comment string to parse.
|
|
470
|
+
* @param {Function} [expandType] - An optional function to process the types found in the JSDoc.
|
|
471
|
+
* @returns {Record<string, any> | undefined} An object mapping parameter names to their parsed types, or undefined if no parameters are found.
|
|
472
|
+
*/
|
|
399
473
|
function parseJSDoc(src) {
|
|
400
474
|
var expandType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : expandTypeDepFree;
|
|
475
|
+
// Parse something like: @param {Object} [kwargs={}] Optional arguments.
|
|
401
476
|
var regex = /@param \{(.*?)\} ([\[\]a-zA-Z0-9_$=\{\}\.'" ]+)/g;
|
|
402
477
|
var matches = _toConsumableArray(src.matchAll(regex));
|
|
478
|
+
/** @type {Record<string, any>} */
|
|
403
479
|
var params = Object.create(null);
|
|
404
480
|
matches.forEach(function (_) {
|
|
405
481
|
var type = expandType(_[1].trim());
|
|
406
482
|
var name = _[2].trim();
|
|
407
483
|
var optional = false;
|
|
484
|
+
// Examples:
|
|
485
|
+
// name: [kwargs={}] The configuration parameters.
|
|
486
|
+
// name: [d = 1.0] Sample spacing
|
|
408
487
|
if (name[0] === '[') {
|
|
488
|
+
// Possible improvement: counting opening/closing brackets for perfect match
|
|
409
489
|
var closer = name.lastIndexOf(']');
|
|
490
|
+
// Afterwards name will be: d = 1.0
|
|
410
491
|
name = name.substring(1, closer);
|
|
492
|
+
// mark it for the type:
|
|
411
493
|
optional = true;
|
|
412
494
|
}
|
|
495
|
+
// Strip the rest (either leftover of optional value or description)
|
|
413
496
|
name = name.split(' ')[0].split('=')[0].trim();
|
|
414
497
|
var simplifiedType = simplifyType(type, optional);
|
|
415
498
|
var parts = name.split(".");
|
|
416
499
|
if (parts.length === 3) {
|
|
417
|
-
|
|
418
|
-
var
|
|
419
|
-
var
|
|
500
|
+
// Something like: @param {number[]} settings.render.skyboxRotation - Rotation of skybox.
|
|
501
|
+
var parts0 = parts[0]; // settings
|
|
502
|
+
var parts1 = parts[1]; // render
|
|
503
|
+
var parts2 = parts[2]; // skyboxRotation
|
|
420
504
|
var toptype = params[parts0];
|
|
421
505
|
toptype.properties[parts1].properties = toptype.properties[parts1].properties || {};
|
|
422
506
|
toptype.properties[parts1].properties[parts2] = simplifiedType;
|
|
423
507
|
} else if (parts.length === 2) {
|
|
424
|
-
|
|
425
|
-
var
|
|
508
|
+
// Something like: @param {number} description[].components
|
|
509
|
+
var _parts = parts[0]; // description[]
|
|
510
|
+
var _parts2 = parts[1]; // components
|
|
426
511
|
if (_parts.endsWith('[]')) {
|
|
427
|
-
_parts = _parts.slice(0, -2);
|
|
512
|
+
_parts = _parts.slice(0, -2); // description[] -> description
|
|
428
513
|
}
|
|
514
|
+
|
|
429
515
|
var _toptype = params[_parts];
|
|
430
516
|
if ((_toptype === null || _toptype === void 0 ? void 0 : _toptype.type) === "union") {
|
|
431
517
|
var typeObject = _toptype.members.find(function (_) {
|
|
432
518
|
return (_ === null || _ === void 0 ? void 0 : _.type) === 'object';
|
|
433
519
|
});
|
|
434
520
|
typeObject.properties[_parts2] = simplifiedType;
|
|
521
|
+
//typeObject.properties = simplifiedType; // todo add test case
|
|
435
522
|
} else if ((_toptype === null || _toptype === void 0 ? void 0 : _toptype.type) === "array") {
|
|
436
523
|
_toptype.elementType.properties[_parts2] = simplifiedType;
|
|
437
524
|
} else if ((_toptype === null || _toptype === void 0 ? void 0 : _toptype.type) === "object") {
|
|
@@ -456,6 +543,12 @@
|
|
|
456
543
|
return params;
|
|
457
544
|
}
|
|
458
545
|
|
|
546
|
+
/**
|
|
547
|
+
* @param {string} src - JSDoc comment of the setter.
|
|
548
|
+
* @param {Function} expandType - The expandType function.
|
|
549
|
+
* @returns {string | DocType | undefined} The parsed and possibly expanded type from
|
|
550
|
+
* the JSDoc comment, or undefined if parsing fails to find `@type`.
|
|
551
|
+
*/
|
|
459
552
|
function parseJSDocSetter(src) {
|
|
460
553
|
var expandType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : expandTypeDepFree;
|
|
461
554
|
var regex = /@type \{(.*?)\}/g;
|
|
@@ -463,23 +556,49 @@
|
|
|
463
556
|
if (matches.length === 1) {
|
|
464
557
|
var match = matches[0];
|
|
465
558
|
var type = expandType(match[1]);
|
|
466
|
-
var simplifiedType = simplifyType(type, false);
|
|
559
|
+
var simplifiedType = simplifyType(type, /* optional */false);
|
|
467
560
|
return simplifiedType;
|
|
468
561
|
}
|
|
469
562
|
}
|
|
470
563
|
|
|
564
|
+
/**
|
|
565
|
+
* Extracts the parameter name and its optionality from a JSDoc parameter string.
|
|
566
|
+
*
|
|
567
|
+
* This function takes a rest parameter string from a JSDoc comment, trims it, and determines the parameter's
|
|
568
|
+
* name and whether it is optional. The optionality is inferred based on the presence of square brackets around
|
|
569
|
+
* the parameter name.
|
|
570
|
+
*
|
|
571
|
+
* @param {string} rest - The rest part of a JSDoc parameter string to parse.
|
|
572
|
+
* @returns {[string, boolean]} A tuple where the first element is the name of the parameter,
|
|
573
|
+
* and the second element is a boolean indicating if the parameter is optional.
|
|
574
|
+
*/
|
|
471
575
|
function extractNameAndOptionality(rest) {
|
|
472
576
|
rest = rest.trim();
|
|
473
577
|
var optional = false;
|
|
578
|
+
// Examples:
|
|
579
|
+
// name: [kwargs={}] The configuration parameters.
|
|
580
|
+
// name: [d = 1.0] Sample spacing
|
|
474
581
|
if (rest[0] === '[') {
|
|
582
|
+
// Possible improvement: counting opening/closing brackets for perfect match
|
|
475
583
|
var closer = rest.lastIndexOf(']');
|
|
584
|
+
// Afterwards name will be: d = 1.0
|
|
476
585
|
rest = rest.substring(1, closer);
|
|
586
|
+
// mark it for the type:
|
|
477
587
|
optional = true;
|
|
478
588
|
}
|
|
589
|
+
// Strip the rest (either leftover of optional value or description)
|
|
479
590
|
var name = rest.split(' ')[0].split('=')[0].trim();
|
|
480
591
|
return [name, optional];
|
|
481
592
|
}
|
|
482
593
|
|
|
594
|
+
/**
|
|
595
|
+
* Extracts the content of a string that is delimited by curly braces.
|
|
596
|
+
* @example
|
|
597
|
+
* extractCurlyContent('{ {inner} }'); // Returns: {content: ' {inner} ', nextIndex: 11}
|
|
598
|
+
* @param {string} line - The string to extract from.
|
|
599
|
+
* @returns {{content: string, nextIndex: number}} An object containing the extracted content,
|
|
600
|
+
* and the index of the character immediately following the closing curly brace.
|
|
601
|
+
*/
|
|
483
602
|
function extractCurlyContent(line) {
|
|
484
603
|
var firstCurly = line.indexOf('{');
|
|
485
604
|
var k = firstCurly + 1;
|
|
@@ -501,6 +620,17 @@
|
|
|
501
620
|
nextIndex: k + 1
|
|
502
621
|
};
|
|
503
622
|
}
|
|
623
|
+
/**
|
|
624
|
+
* Parses JSDoc comments to extract and expand typedefs and their associated properties.
|
|
625
|
+
*
|
|
626
|
+
* It iterates through the lines of a `CommentBlock` from the Babel AST, looking for `@typedef` and `@property`
|
|
627
|
+
* annotations. When it finds a typedef, it stores it in the `typedefs` record. When it finds a property,
|
|
628
|
+
* it adds it to the last found typedef if it is an object type.
|
|
629
|
+
* @param {Record<string, object>} typedefs - An object to store typedefs, mapping type names to their expanded definitions.
|
|
630
|
+
* @param {Console["warn"]} warn - A warn function used for emitting warnings about non-extensible types.
|
|
631
|
+
* @param {import("@babel/types").Comment} comment - A comment extracted from Babel's AST, expected to be a CommentBlock containing type definitions.
|
|
632
|
+
* @param {Function} expandType - A function that takes a type expression as a string and returns a structured representation of the type.
|
|
633
|
+
*/
|
|
504
634
|
function parseJSDocTypedef(typedefs, warn, comment, expandType) {
|
|
505
635
|
var type = comment.type,
|
|
506
636
|
value = comment.value;
|
|
@@ -523,13 +653,16 @@
|
|
|
523
653
|
def = _extractCurlyContent.content,
|
|
524
654
|
nextIndex = _extractCurlyContent.nextIndex;
|
|
525
655
|
var name = line.substring(nextIndex).trim();
|
|
656
|
+
// Drop description
|
|
526
657
|
name = name.split(' ')[0];
|
|
527
658
|
lastTypedef = expandType(def);
|
|
659
|
+
// Ignore @typedef's that only refer to themselves in another file (see typedef-overwrite test)
|
|
528
660
|
if (lastTypedef !== name) {
|
|
529
661
|
typedefs[name] = lastTypedef;
|
|
530
662
|
}
|
|
531
663
|
} else if (line.startsWith('@property')) {
|
|
532
664
|
var _lastTypedef;
|
|
665
|
+
// class @property
|
|
533
666
|
if (!lastTypedef) {
|
|
534
667
|
continue;
|
|
535
668
|
}
|
|
@@ -542,6 +675,7 @@
|
|
|
542
675
|
_extractNameAndOption2 = _slicedToArray(_extractNameAndOption, 2),
|
|
543
676
|
_name = _extractNameAndOption2[0],
|
|
544
677
|
optional = _extractNameAndOption2[1];
|
|
678
|
+
// console.log({name, optional, propType});
|
|
545
679
|
var finalType = simplifyType(propType, optional);
|
|
546
680
|
if (((_lastTypedef = lastTypedef) === null || _lastTypedef === void 0 ? void 0 : _lastTypedef.type) === 'object') {
|
|
547
681
|
lastTypedef.properties[_name] = finalType;
|
|
@@ -560,23 +694,46 @@
|
|
|
560
694
|
}
|
|
561
695
|
}
|
|
562
696
|
|
|
697
|
+
/**
|
|
698
|
+
* @typedef Stat
|
|
699
|
+
* @property {number} checked - How often assertions were added to this kind of node.
|
|
700
|
+
* @property {number} unchecked - How often no assertions were added to this kind of node.
|
|
701
|
+
*/
|
|
702
|
+
/**
|
|
703
|
+
* @param {Stat} stat - the Stat.
|
|
704
|
+
*/
|
|
563
705
|
function statReset(stat) {
|
|
564
706
|
stat.checked = 0;
|
|
565
707
|
stat.unchecked = 0;
|
|
566
708
|
}
|
|
567
709
|
|
|
710
|
+
/**
|
|
711
|
+
* @example
|
|
712
|
+
* trimEndSpaces('test \n '); // Returns: 'test \n'
|
|
713
|
+
* @param {string} str - The input string.
|
|
714
|
+
* @returns {string} Output string without spaces at the end.
|
|
715
|
+
*/
|
|
568
716
|
function trimEndSpaces(str) {
|
|
569
717
|
var i = str.length - 1;
|
|
718
|
+
// decrement index while character is a space
|
|
570
719
|
while (str[i] === ' ') {
|
|
571
720
|
i--;
|
|
572
721
|
}
|
|
722
|
+
// return string from 0 to non-space character
|
|
573
723
|
return str.slice(0, i + 1);
|
|
574
724
|
}
|
|
575
725
|
|
|
576
|
-
|
|
726
|
+
/**
|
|
727
|
+
* @typedef {import("@babel/types").Node} Node
|
|
728
|
+
*/
|
|
729
|
+
/**
|
|
730
|
+
* Class for converting AST into string.
|
|
731
|
+
*/
|
|
732
|
+
var Stringifier = /*#__PURE__*/function () {
|
|
577
733
|
function Stringifier() {
|
|
578
734
|
_classCallCheck(this, Stringifier);
|
|
579
735
|
_defineProperty(this, "forceCurly", false);
|
|
736
|
+
/** @type {Node[]} */
|
|
580
737
|
_defineProperty(this, "parents", []);
|
|
581
738
|
_defineProperty(this, "lastCommentBlockIndex", -1);
|
|
582
739
|
_defineProperty(this, "lastCommentLineIndex", -1);
|
|
@@ -584,9 +741,19 @@
|
|
|
584
741
|
}
|
|
585
742
|
_createClass(Stringifier, [{
|
|
586
743
|
key: "toSource",
|
|
587
|
-
value:
|
|
744
|
+
value:
|
|
745
|
+
/**
|
|
746
|
+
* @param {Node} node - The Babel AST node.
|
|
747
|
+
* @returns {string} Stringification of the node.
|
|
748
|
+
*/
|
|
749
|
+
function toSource(node) {
|
|
588
750
|
var _node$extra;
|
|
751
|
+
// handle this case only temporarily
|
|
589
752
|
if (node === null) {
|
|
753
|
+
// Contexts like:
|
|
754
|
+
// Object.assign(Channel3d.prototype, {
|
|
755
|
+
// setPosition: function /*null*/(position) {
|
|
756
|
+
//return '/*null*/';
|
|
590
757
|
return '';
|
|
591
758
|
}
|
|
592
759
|
var leadingComments = node.leadingComments,
|
|
@@ -598,6 +765,7 @@
|
|
|
598
765
|
var out = '';
|
|
599
766
|
var comments = '';
|
|
600
767
|
if (leadingComments) {
|
|
768
|
+
// comments += this.mapToSource(leadingComments).join('');
|
|
601
769
|
comments = this.leadingCommentsToSource(leadingComments);
|
|
602
770
|
}
|
|
603
771
|
if (node !== null && node !== void 0 && (_node$extra = node.extra) !== null && _node$extra !== void 0 && _node$extra.parenthesized) {
|
|
@@ -608,9 +776,17 @@
|
|
|
608
776
|
if (trailingComments) {
|
|
609
777
|
out += this.trailingCommentsToSource(trailingComments);
|
|
610
778
|
}
|
|
779
|
+
// leadingComments and trailingComments lead to duplicates, not always tho
|
|
780
|
+
//if (node && node.trailingComments) {
|
|
781
|
+
// out += this.mapToSource(node.trailingComments).join('\n') + '\n';
|
|
782
|
+
//}
|
|
611
783
|
this.parents.pop();
|
|
612
784
|
return out;
|
|
613
785
|
}
|
|
786
|
+
/**
|
|
787
|
+
* @param {Node} node - The Babel AST node.
|
|
788
|
+
* @returns {string} Stringification of the node.
|
|
789
|
+
*/
|
|
614
790
|
}, {
|
|
615
791
|
key: "toSource_",
|
|
616
792
|
value: function toSource_(node) {
|
|
@@ -637,21 +813,30 @@
|
|
|
637
813
|
}, {
|
|
638
814
|
key: "parentProvidesSpaces",
|
|
639
815
|
value: function parentProvidesSpaces(reverseIndex) {
|
|
816
|
+
// May look like: .../ArrayExpression/StringLiteral/CommentLine
|
|
640
817
|
var parents = this.parents;
|
|
641
818
|
var parent = parents[parents.length - reverseIndex];
|
|
819
|
+
// console.log("Got parent", parent.type);
|
|
642
820
|
return (parent === null || parent === void 0 ? void 0 : parent.type) === 'ArrayExpression';
|
|
643
821
|
}
|
|
644
822
|
}, {
|
|
645
823
|
key: "CommentBlock",
|
|
646
|
-
value:
|
|
824
|
+
value:
|
|
825
|
+
/**
|
|
826
|
+
* @param {import("@babel/types").CommentBlock} node - The Babel AST node.
|
|
827
|
+
* @returns {string} Stringification of the node.
|
|
828
|
+
*/
|
|
829
|
+
function CommentBlock(node) {
|
|
647
830
|
var loc = node.loc;
|
|
648
831
|
var value = node.value;
|
|
649
832
|
if (this.lastCommentBlockIndex === loc.start.index) {
|
|
833
|
+
// console.log("CommentBlock> ignore double");
|
|
650
834
|
return '';
|
|
651
835
|
}
|
|
652
836
|
this.lastCommentBlockIndex = loc.start.index;
|
|
653
837
|
var spaces = this.spaces;
|
|
654
838
|
var out = '';
|
|
839
|
+
/** @todo add option for number-of-spaces */
|
|
655
840
|
var dedicatedLine = spaces.length === loc.start.column;
|
|
656
841
|
if (dedicatedLine) {
|
|
657
842
|
out += spaces;
|
|
@@ -659,6 +844,7 @@
|
|
|
659
844
|
var multiLine = loc.start.line !== loc.end.line;
|
|
660
845
|
if (multiLine) {
|
|
661
846
|
var _this$parents$at;
|
|
847
|
+
// console.log(this.parents.at(-2)?.type === 'AssignmentExpression');
|
|
662
848
|
if (((_this$parents$at = this.parents.at(-2)) === null || _this$parents$at === void 0 ? void 0 : _this$parents$at.type) === 'AssignmentExpression') {
|
|
663
849
|
spaces += ' ';
|
|
664
850
|
}
|
|
@@ -666,9 +852,13 @@
|
|
|
666
852
|
}
|
|
667
853
|
out += '/*';
|
|
668
854
|
if (value.includes('\n')) {
|
|
855
|
+
// A bit tricky to handle multiline comments,
|
|
856
|
+
// we have to remove the given indentation level.
|
|
669
857
|
value = trimEndSpaces(value.replace(/^\s*\*/gm, '*')).split('\n').filter(function (_) {
|
|
670
858
|
return _.length;
|
|
671
|
-
})
|
|
859
|
+
}) // skip empty lines
|
|
860
|
+
// Skip spaces in first line for /**
|
|
861
|
+
.map(function (line, i) {
|
|
672
862
|
return (i ? spaces + ' ' : '') + line;
|
|
673
863
|
}).join('\n');
|
|
674
864
|
out += "".concat(value, "\n").concat(spaces, " */");
|
|
@@ -684,10 +874,16 @@
|
|
|
684
874
|
}
|
|
685
875
|
}, {
|
|
686
876
|
key: "CommentLine",
|
|
687
|
-
value:
|
|
877
|
+
value:
|
|
878
|
+
/**
|
|
879
|
+
* @param {import("@babel/types").CommentLine} node - The Babel AST node.
|
|
880
|
+
* @returns {string} Stringification of the node.
|
|
881
|
+
*/
|
|
882
|
+
function CommentLine(node) {
|
|
688
883
|
var value = node.value,
|
|
689
884
|
loc = node.loc;
|
|
690
885
|
if (this.lastCommentLineIndex === loc.start.index) {
|
|
886
|
+
// console.log("CommentLine> ignore double");
|
|
691
887
|
return '';
|
|
692
888
|
}
|
|
693
889
|
this.lastCommentLineIndex = loc.start.index;
|
|
@@ -712,6 +908,8 @@
|
|
|
712
908
|
var out = leadingComments.map(function (_) {
|
|
713
909
|
return _this.commentToSource(_, 'leading');
|
|
714
910
|
}).join('');
|
|
911
|
+
// The comments "took" the spaces, which e.g. ArrayExpression added,
|
|
912
|
+
// so we have to add them back now for parents that provide spaces.
|
|
715
913
|
if (this.parentProvidesSpaces(2)) {
|
|
716
914
|
out += this.spaces;
|
|
717
915
|
}
|
|
@@ -729,6 +927,7 @@
|
|
|
729
927
|
if (trailingComment.type === 'CommentBlock') {
|
|
730
928
|
var loc = trailingComment.loc;
|
|
731
929
|
var dedicatedLine = this.spaces.length === loc.start.column;
|
|
930
|
+
// out += ` /*dedicatedLine=${dedicatedLine}*/ `;
|
|
732
931
|
if (dedicatedLine) {
|
|
733
932
|
out += '\n';
|
|
734
933
|
} else {
|
|
@@ -744,10 +943,16 @@
|
|
|
744
943
|
}
|
|
745
944
|
return out;
|
|
746
945
|
}
|
|
946
|
+
/**
|
|
947
|
+
* @param {*} comment - The comment "node" (not a real Babel Node node though, hence this special treatment)
|
|
948
|
+
* @param {'leading'|'trailing'} pos - The position, either 'leading' or 'trailing'.
|
|
949
|
+
* @returns {string} The comment "node" as a string.
|
|
950
|
+
*/
|
|
747
951
|
}, {
|
|
748
952
|
key: "commentToSource",
|
|
749
953
|
value: function commentToSource(comment, pos) {
|
|
750
954
|
if (comment.type === 'CommentBlock') {
|
|
955
|
+
//if (pos === 'leading') {}
|
|
751
956
|
return this.CommentBlock(comment);
|
|
752
957
|
} else if (comment.type === 'CommentLine') {
|
|
753
958
|
return this.CommentLine(comment);
|
|
@@ -756,6 +961,12 @@
|
|
|
756
961
|
debugger;
|
|
757
962
|
return '';
|
|
758
963
|
}
|
|
964
|
+
/**
|
|
965
|
+
* Only add { and } when requested (e.g. for Asserter).
|
|
966
|
+
* showAST("if (true) 2;") vs showAST("if (true) {2}")
|
|
967
|
+
* @param {Node} node - The Babel AST node.
|
|
968
|
+
* @returns {string} Stringification of the node.
|
|
969
|
+
*/
|
|
759
970
|
}, {
|
|
760
971
|
key: "toSourceCurly",
|
|
761
972
|
value: function toSourceCurly(node) {
|
|
@@ -768,7 +979,10 @@
|
|
|
768
979
|
var out = '';
|
|
769
980
|
if (needCurly) {
|
|
770
981
|
out += ' {\n';
|
|
982
|
+
//out += spaces + `/* toSourceCurly> needCurly=${needCurly} type=${type}
|
|
983
|
+
//parents=${parents.map(_=>_.type).join('->')}*/\n`;
|
|
771
984
|
}
|
|
985
|
+
|
|
772
986
|
out += this.toSource(node);
|
|
773
987
|
if (needCurly) {
|
|
774
988
|
out += '\n';
|
|
@@ -794,6 +1008,10 @@
|
|
|
794
1008
|
var t = this.parentType;
|
|
795
1009
|
return t !== "ForStatement" && t !== "ForInStatement" && t !== "ForOfStatement";
|
|
796
1010
|
}
|
|
1011
|
+
/**
|
|
1012
|
+
* @param {Node[]} arr - Array of nodes to convert.
|
|
1013
|
+
* @returns {string[]} Array of strings for each node.
|
|
1014
|
+
*/
|
|
797
1015
|
}, {
|
|
798
1016
|
key: "mapToSource",
|
|
799
1017
|
value: function mapToSource(arr) {
|
|
@@ -802,6 +1020,16 @@
|
|
|
802
1020
|
return _this2.toSource(_);
|
|
803
1021
|
});
|
|
804
1022
|
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Generates a string representing type checks for a given Babel AST node.
|
|
1025
|
+
*
|
|
1026
|
+
* Note: This method serves as a stub and should be overridden in subclasses.
|
|
1027
|
+
* The actual implementation is expected to be provided in Asserter.mjs, where
|
|
1028
|
+
* it would create runtime type assertions based on the AST node provided.
|
|
1029
|
+
*
|
|
1030
|
+
* @param {Node} node - The Babel AST node for which to generate type checks.
|
|
1031
|
+
* @returns {string} A placeholder string, as this stub implementation does nothing; expected to be overridden.
|
|
1032
|
+
*/
|
|
805
1033
|
}, {
|
|
806
1034
|
key: "generateTypeChecks",
|
|
807
1035
|
value: function generateTypeChecks(node) {
|
|
@@ -809,7 +1037,11 @@
|
|
|
809
1037
|
}
|
|
810
1038
|
}, {
|
|
811
1039
|
key: "spaces",
|
|
812
|
-
get:
|
|
1040
|
+
get:
|
|
1041
|
+
/**
|
|
1042
|
+
* @type {string} A string of two spaces per indentation.
|
|
1043
|
+
*/
|
|
1044
|
+
function get() {
|
|
813
1045
|
return ' '.repeat(this.numSpaces);
|
|
814
1046
|
}
|
|
815
1047
|
}, {
|
|
@@ -823,18 +1055,32 @@
|
|
|
823
1055
|
}).join('/');
|
|
824
1056
|
return "".concat(spaces, "// got ").concat(n, " spaces for ").concat(path, "\n");
|
|
825
1057
|
}
|
|
1058
|
+
/**
|
|
1059
|
+
* > await something();
|
|
1060
|
+
*
|
|
1061
|
+
* @param {import("@babel/types").AwaitExpression} node - The Babel AST node.
|
|
1062
|
+
* @returns {string} Stringification of the node.
|
|
1063
|
+
*/
|
|
826
1064
|
}, {
|
|
827
1065
|
key: "AwaitExpression",
|
|
828
1066
|
value: function AwaitExpression(node) {
|
|
829
1067
|
var argument = node.argument;
|
|
830
1068
|
return "await ".concat(this.toSource(argument));
|
|
831
1069
|
}
|
|
1070
|
+
/**
|
|
1071
|
+
* @param {import("@babel/types").ClassBody} node - The Babel AST node.
|
|
1072
|
+
* @returns {string} Stringification of the node.
|
|
1073
|
+
*/
|
|
832
1074
|
}, {
|
|
833
1075
|
key: "ClassBody",
|
|
834
1076
|
value: function ClassBody(node) {
|
|
835
1077
|
var body = node.body;
|
|
836
1078
|
return this.mapToSource(body).join('\n');
|
|
837
1079
|
}
|
|
1080
|
+
/**
|
|
1081
|
+
* @param {import("@babel/types").ClassMethod} node - The Babel AST node.
|
|
1082
|
+
* @returns {string} Stringification of the node.
|
|
1083
|
+
*/
|
|
838
1084
|
}, {
|
|
839
1085
|
key: "ClassMethod",
|
|
840
1086
|
value: function ClassMethod(node) {
|
|
@@ -876,6 +1122,10 @@
|
|
|
876
1122
|
out += this.toSource(body);
|
|
877
1123
|
return out;
|
|
878
1124
|
}
|
|
1125
|
+
/**
|
|
1126
|
+
* @param {import("@babel/types").ClassExpression} node - The Babel AST node.
|
|
1127
|
+
* @returns {string} Stringification of the node.
|
|
1128
|
+
*/
|
|
879
1129
|
}, {
|
|
880
1130
|
key: "ClassExpression",
|
|
881
1131
|
value: function ClassExpression(node) {
|
|
@@ -884,6 +1134,7 @@
|
|
|
884
1134
|
body = node.body;
|
|
885
1135
|
var out = 'class ';
|
|
886
1136
|
if (id !== null) {
|
|
1137
|
+
// Babel: strange API, either null or undefined... pick a type, maybe oversight/bug
|
|
887
1138
|
out += this.toSource(id) + ' ';
|
|
888
1139
|
}
|
|
889
1140
|
if (superClass !== null) {
|
|
@@ -894,6 +1145,10 @@
|
|
|
894
1145
|
out += "{\n".concat(c, "\n}");
|
|
895
1146
|
return out;
|
|
896
1147
|
}
|
|
1148
|
+
/**
|
|
1149
|
+
* @param {import("@babel/types").ClassDeclaration} node - The Babel AST node.
|
|
1150
|
+
* @returns {string} Stringification of the node.
|
|
1151
|
+
*/
|
|
897
1152
|
}, {
|
|
898
1153
|
key: "ClassDeclaration",
|
|
899
1154
|
value: function ClassDeclaration(node) {
|
|
@@ -915,6 +1170,10 @@
|
|
|
915
1170
|
out += '\n}\n';
|
|
916
1171
|
return out;
|
|
917
1172
|
}
|
|
1173
|
+
/**
|
|
1174
|
+
* @param {import("@babel/types").ClassPrivateMethod} node - The Babel AST node.
|
|
1175
|
+
* @returns {string} Stringification of the node.
|
|
1176
|
+
*/
|
|
918
1177
|
}, {
|
|
919
1178
|
key: "ClassPrivateMethod",
|
|
920
1179
|
value: function ClassPrivateMethod(node) {
|
|
@@ -951,6 +1210,15 @@
|
|
|
951
1210
|
out += this.toSource(body);
|
|
952
1211
|
return out;
|
|
953
1212
|
}
|
|
1213
|
+
/**
|
|
1214
|
+
* > asd;
|
|
1215
|
+
* > asd = 1;
|
|
1216
|
+
* > static asd;
|
|
1217
|
+
* > static asd = 1;
|
|
1218
|
+
*
|
|
1219
|
+
* @param {import("@babel/types").ClassProperty} node - The Babel AST node.
|
|
1220
|
+
* @returns {string} Stringification of the node.
|
|
1221
|
+
*/
|
|
954
1222
|
}, {
|
|
955
1223
|
key: "ClassProperty",
|
|
956
1224
|
value: function ClassProperty(node) {
|
|
@@ -958,7 +1226,7 @@
|
|
|
958
1226
|
computed = node.computed,
|
|
959
1227
|
value = node.value;
|
|
960
1228
|
node.leadingComments;
|
|
961
|
-
var static_ = node.static;
|
|
1229
|
+
var static_ = node.static; // JS keyword is problematic in object destructuring
|
|
962
1230
|
var a = this.toSource(key);
|
|
963
1231
|
var b = this.toSource(value);
|
|
964
1232
|
var out = this.spaces;
|
|
@@ -976,6 +1244,10 @@
|
|
|
976
1244
|
out += ';';
|
|
977
1245
|
return out;
|
|
978
1246
|
}
|
|
1247
|
+
/**
|
|
1248
|
+
* @param {import("@babel/types").ClassPrivateProperty} node - The Babel AST node.
|
|
1249
|
+
* @returns {string} Stringification of the node.
|
|
1250
|
+
*/
|
|
979
1251
|
}, {
|
|
980
1252
|
key: "ClassPrivateProperty",
|
|
981
1253
|
value: function ClassPrivateProperty(node) {
|
|
@@ -993,6 +1265,10 @@
|
|
|
993
1265
|
out += ';';
|
|
994
1266
|
return out;
|
|
995
1267
|
}
|
|
1268
|
+
/**
|
|
1269
|
+
* @param {import("@babel/types").ContinueStatement} node - The Babel AST node.
|
|
1270
|
+
* @returns {string} Stringification of the node.
|
|
1271
|
+
*/
|
|
996
1272
|
}, {
|
|
997
1273
|
key: "ContinueStatement",
|
|
998
1274
|
value: function ContinueStatement(node) {
|
|
@@ -1004,11 +1280,24 @@
|
|
|
1004
1280
|
out += ';';
|
|
1005
1281
|
return out;
|
|
1006
1282
|
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Converts an array of Babel AST nodes representing function parameters into a comma-separated string.
|
|
1285
|
+
*
|
|
1286
|
+
* Each parameter node is converted to its source representation and combined into a single
|
|
1287
|
+
* string suitable for inserting into a function declaration's parentheses.
|
|
1288
|
+
*
|
|
1289
|
+
* @param {Node[]} params - An array of Babel AST nodes representing the function parameters to be stringified.
|
|
1290
|
+
* @returns {string} A string representing the serialized parameters, enclosed in parentheses.
|
|
1291
|
+
*/
|
|
1007
1292
|
}, {
|
|
1008
1293
|
key: "FunctionDeclarationParams",
|
|
1009
1294
|
value: function FunctionDeclarationParams(params) {
|
|
1010
1295
|
return '(' + this.mapToSource(params).join(', ') + ')';
|
|
1011
1296
|
}
|
|
1297
|
+
/**
|
|
1298
|
+
* @param {import("@babel/types").FunctionDeclaration} node - The Babel AST node.
|
|
1299
|
+
* @returns {string} Stringification of the node.
|
|
1300
|
+
*/
|
|
1012
1301
|
}, {
|
|
1013
1302
|
key: "FunctionDeclaration",
|
|
1014
1303
|
value: function FunctionDeclaration(node) {
|
|
@@ -1030,9 +1319,14 @@
|
|
|
1030
1319
|
out += this.toSource(body);
|
|
1031
1320
|
return out;
|
|
1032
1321
|
}
|
|
1322
|
+
/**
|
|
1323
|
+
* @param {import("@babel/types").FunctionExpression} node - The Babel AST node.
|
|
1324
|
+
* @returns {string} Stringification of the node.
|
|
1325
|
+
*/
|
|
1033
1326
|
}, {
|
|
1034
1327
|
key: "FunctionExpression",
|
|
1035
1328
|
value: function FunctionExpression(node) {
|
|
1329
|
+
// Leading comments for asd=function(){} are in ExpressionStatement
|
|
1036
1330
|
var async = node.async,
|
|
1037
1331
|
body = node.body,
|
|
1038
1332
|
generator = node.generator,
|
|
@@ -1056,6 +1350,10 @@
|
|
|
1056
1350
|
}
|
|
1057
1351
|
return out;
|
|
1058
1352
|
}
|
|
1353
|
+
/**
|
|
1354
|
+
* @param {import("@babel/types").ArrowFunctionExpression} node - The Babel AST node.
|
|
1355
|
+
* @returns {string} Stringification of the node.
|
|
1356
|
+
*/
|
|
1059
1357
|
}, {
|
|
1060
1358
|
key: "ArrowFunctionExpression",
|
|
1061
1359
|
value: function ArrowFunctionExpression(node) {
|
|
@@ -1075,6 +1373,10 @@
|
|
|
1075
1373
|
out += this.toSource(body);
|
|
1076
1374
|
return out;
|
|
1077
1375
|
}
|
|
1376
|
+
/**
|
|
1377
|
+
* @param {import("@babel/types").BigIntLiteral} node - The Babel AST node.
|
|
1378
|
+
* @returns {string} Stringification of the node.
|
|
1379
|
+
*/
|
|
1078
1380
|
}, {
|
|
1079
1381
|
key: "BigIntLiteral",
|
|
1080
1382
|
value: function BigIntLiteral(node) {
|
|
@@ -1082,6 +1384,10 @@
|
|
|
1082
1384
|
node.value;
|
|
1083
1385
|
return extra.raw;
|
|
1084
1386
|
}
|
|
1387
|
+
/**
|
|
1388
|
+
* @param {import("@babel/types").BlockStatement} node - The Babel AST node.
|
|
1389
|
+
* @returns {string} Stringification of the node.
|
|
1390
|
+
*/
|
|
1085
1391
|
}, {
|
|
1086
1392
|
key: "BlockStatement",
|
|
1087
1393
|
value: function BlockStatement(node) {
|
|
@@ -1091,6 +1397,7 @@
|
|
|
1091
1397
|
var out = '';
|
|
1092
1398
|
out += ' {';
|
|
1093
1399
|
this.numSpaces++;
|
|
1400
|
+
// Handle Directive/DirectiveLiteral like 'use strict';
|
|
1094
1401
|
if (directives && directives.length) {
|
|
1095
1402
|
out += '\n';
|
|
1096
1403
|
out += this.mapToSource(directives).join('\n') + '\n';
|
|
@@ -1098,8 +1405,10 @@
|
|
|
1098
1405
|
out += this.generateTypeChecks(node);
|
|
1099
1406
|
if (body.length) {
|
|
1100
1407
|
if (out.length === 2) {
|
|
1408
|
+
// 2 is ' {'
|
|
1101
1409
|
out += '\n';
|
|
1102
1410
|
}
|
|
1411
|
+
// out += '/*'+out.length+'*/';
|
|
1103
1412
|
out += this.mapToSource(body).join('\n') + '\n';
|
|
1104
1413
|
out += spaces;
|
|
1105
1414
|
}
|
|
@@ -1107,12 +1416,24 @@
|
|
|
1107
1416
|
out += '}';
|
|
1108
1417
|
return out;
|
|
1109
1418
|
}
|
|
1419
|
+
/**
|
|
1420
|
+
* > 'use strict';
|
|
1421
|
+
*
|
|
1422
|
+
* @param {import("@babel/types").Directive} node - The Babel AST node.
|
|
1423
|
+
* @returns {string} Stringification of the node.
|
|
1424
|
+
*/
|
|
1110
1425
|
}, {
|
|
1111
1426
|
key: "Directive",
|
|
1112
1427
|
value: function Directive(node) {
|
|
1113
1428
|
var value = node.value;
|
|
1114
1429
|
return this.toSource(value);
|
|
1115
1430
|
}
|
|
1431
|
+
/**
|
|
1432
|
+
* > 'use strict';
|
|
1433
|
+
*
|
|
1434
|
+
* @param {import("@babel/types").DirectiveLiteral} node - The Babel AST node.
|
|
1435
|
+
* @returns {string} Stringification of the node.
|
|
1436
|
+
*/
|
|
1116
1437
|
}, {
|
|
1117
1438
|
key: "DirectiveLiteral",
|
|
1118
1439
|
value: function DirectiveLiteral(node) {
|
|
@@ -1121,6 +1442,10 @@
|
|
|
1121
1442
|
var spaces = this.spaces;
|
|
1122
1443
|
return "".concat(spaces).concat(extra.raw, ";");
|
|
1123
1444
|
}
|
|
1445
|
+
/**
|
|
1446
|
+
* @param {import("@babel/types").ReturnStatement} node - The Babel AST node.
|
|
1447
|
+
* @returns {string} Stringification of the node.
|
|
1448
|
+
*/
|
|
1124
1449
|
}, {
|
|
1125
1450
|
key: "ReturnStatement",
|
|
1126
1451
|
value: function ReturnStatement(node) {
|
|
@@ -1131,11 +1456,19 @@
|
|
|
1131
1456
|
}
|
|
1132
1457
|
return spaces + 'return ' + this.toSource(argument) + ';';
|
|
1133
1458
|
}
|
|
1459
|
+
/**
|
|
1460
|
+
* @param {import("@babel/types").Identifier} node - The Babel AST node.
|
|
1461
|
+
* @returns {string} Stringification of the node.
|
|
1462
|
+
*/
|
|
1134
1463
|
}, {
|
|
1135
1464
|
key: "Identifier",
|
|
1136
1465
|
value: function Identifier(node) {
|
|
1137
1466
|
return node.name;
|
|
1138
1467
|
}
|
|
1468
|
+
/**
|
|
1469
|
+
* @param {import("@babel/types").IfStatement} node - The Babel AST node.
|
|
1470
|
+
* @returns {string} Stringification of the node.
|
|
1471
|
+
*/
|
|
1139
1472
|
}, {
|
|
1140
1473
|
key: "IfStatement",
|
|
1141
1474
|
value: function IfStatement(node) {
|
|
@@ -1144,7 +1477,10 @@
|
|
|
1144
1477
|
test = node.test;
|
|
1145
1478
|
var spaces = this.spaces;
|
|
1146
1479
|
var out = '';
|
|
1480
|
+
//if (this.parentType !== "IfStatement")
|
|
1481
|
+
//{
|
|
1147
1482
|
out += spaces;
|
|
1483
|
+
//}
|
|
1148
1484
|
out += "if (".concat(this.toSource(test), ")");
|
|
1149
1485
|
out += this.toSourceCurly(consequent);
|
|
1150
1486
|
if (alternate) {
|
|
@@ -1152,6 +1488,10 @@
|
|
|
1152
1488
|
}
|
|
1153
1489
|
return out;
|
|
1154
1490
|
}
|
|
1491
|
+
/**
|
|
1492
|
+
* @param {import("@babel/types").LabeledStatement} node - The Babel AST node.
|
|
1493
|
+
* @returns {string} Stringification of the node.
|
|
1494
|
+
*/
|
|
1155
1495
|
}, {
|
|
1156
1496
|
key: "LabeledStatement",
|
|
1157
1497
|
value: function LabeledStatement(node) {
|
|
@@ -1164,6 +1504,15 @@
|
|
|
1164
1504
|
out += spaces + this.toSource(body);
|
|
1165
1505
|
return out;
|
|
1166
1506
|
}
|
|
1507
|
+
/**
|
|
1508
|
+
* @example
|
|
1509
|
+
* ts = require("typescript");
|
|
1510
|
+
* ts.createSourceFile("repl.ts", "a = 1", ts.ScriptTarget.Latest);
|
|
1511
|
+
* ts.createSourceFile("repl.ts", "!!(a = 1 + 2)", ts.ScriptTarget.Latest);
|
|
1512
|
+
* showAST('!!(a = 1)');
|
|
1513
|
+
* @param {import("@babel/types").UnaryExpression} node - The Babel AST node.
|
|
1514
|
+
* @returns {string} Stringification of the node.
|
|
1515
|
+
*/
|
|
1167
1516
|
}, {
|
|
1168
1517
|
key: "UnaryExpression",
|
|
1169
1518
|
value: function UnaryExpression(node) {
|
|
@@ -1174,6 +1523,7 @@
|
|
|
1174
1523
|
if (!prefix) {
|
|
1175
1524
|
console.warn("Stringifier#UnaryExpression> never considered !prefix", node);
|
|
1176
1525
|
}
|
|
1526
|
+
// Add a space for: typeof/delete/void
|
|
1177
1527
|
var c = operator.charCodeAt(0);
|
|
1178
1528
|
var op = operator;
|
|
1179
1529
|
if (c >= 97 && c <= 122) {
|
|
@@ -1183,6 +1533,10 @@
|
|
|
1183
1533
|
out += this.toSource(argument);
|
|
1184
1534
|
return out;
|
|
1185
1535
|
}
|
|
1536
|
+
/**
|
|
1537
|
+
* @param {import("@babel/types").MemberExpression} node - The Babel AST node.
|
|
1538
|
+
* @returns {string} Stringification of the node.
|
|
1539
|
+
*/
|
|
1186
1540
|
}, {
|
|
1187
1541
|
key: "MemberExpression",
|
|
1188
1542
|
value: function MemberExpression(node) {
|
|
@@ -1194,6 +1548,10 @@
|
|
|
1194
1548
|
}
|
|
1195
1549
|
return "".concat(this.toSource(object), ".").concat(this.toSource(property));
|
|
1196
1550
|
}
|
|
1551
|
+
/**
|
|
1552
|
+
* @param {import("@babel/types").MetaProperty} node - The Babel AST node.
|
|
1553
|
+
* @returns {string} Stringification of the node.
|
|
1554
|
+
*/
|
|
1197
1555
|
}, {
|
|
1198
1556
|
key: "MetaProperty",
|
|
1199
1557
|
value: function MetaProperty(node) {
|
|
@@ -1203,12 +1561,26 @@
|
|
|
1203
1561
|
var rhs = this.toSource(property);
|
|
1204
1562
|
return "".concat(lhs, ".").concat(rhs);
|
|
1205
1563
|
}
|
|
1564
|
+
/**
|
|
1565
|
+
* @param {import("@babel/types").ExpressionStatement} node - The Babel AST node.
|
|
1566
|
+
* @returns {string} Stringification of the node.
|
|
1567
|
+
*/
|
|
1206
1568
|
}, {
|
|
1207
1569
|
key: "ExpressionStatement",
|
|
1208
1570
|
value: function ExpressionStatement(node) {
|
|
1209
1571
|
var expression = node.expression;
|
|
1572
|
+
/**
|
|
1573
|
+
* Not just a fall-through, adds a semicolon when it has semantic meaning.
|
|
1574
|
+
* E.g. invalid:
|
|
1575
|
+
* (function() {})()
|
|
1576
|
+
* (function() {})()
|
|
1577
|
+
*/
|
|
1210
1578
|
return this.spaces + this.toSource(expression) + ';';
|
|
1211
1579
|
}
|
|
1580
|
+
/**
|
|
1581
|
+
* @param {import("@babel/types").CallExpression} node - The Babel AST node.
|
|
1582
|
+
* @returns {string} Stringification of the node.
|
|
1583
|
+
*/
|
|
1212
1584
|
}, {
|
|
1213
1585
|
key: "CallExpression",
|
|
1214
1586
|
value: function CallExpression(node) {
|
|
@@ -1224,6 +1596,14 @@
|
|
|
1224
1596
|
out += ")";
|
|
1225
1597
|
return out;
|
|
1226
1598
|
}
|
|
1599
|
+
/**
|
|
1600
|
+
* We replicate the exact AST for validation:
|
|
1601
|
+
* x = 1;
|
|
1602
|
+
* y = {x,}
|
|
1603
|
+
* z = {y};
|
|
1604
|
+
* @param {import("@babel/types").ObjectExpression} node - The Babel AST node.
|
|
1605
|
+
* @returns {string} Stringification of the node.
|
|
1606
|
+
*/
|
|
1227
1607
|
}, {
|
|
1228
1608
|
key: "ObjectExpression",
|
|
1229
1609
|
value: function ObjectExpression(node) {
|
|
@@ -1245,6 +1625,10 @@
|
|
|
1245
1625
|
out += '}';
|
|
1246
1626
|
return out;
|
|
1247
1627
|
}
|
|
1628
|
+
/**
|
|
1629
|
+
* @param {import("@babel/types").ObjectProperty} node - The Babel AST node.
|
|
1630
|
+
* @returns {string} Stringification of the node.
|
|
1631
|
+
*/
|
|
1248
1632
|
}, {
|
|
1249
1633
|
key: "ObjectProperty",
|
|
1250
1634
|
value: function ObjectProperty(node) {
|
|
@@ -1272,11 +1656,19 @@
|
|
|
1272
1656
|
out += right;
|
|
1273
1657
|
return out;
|
|
1274
1658
|
}
|
|
1659
|
+
/**
|
|
1660
|
+
* @param {import("@babel/types").BooleanLiteral} node - The Babel AST node.
|
|
1661
|
+
* @returns {string} Stringification of the node.
|
|
1662
|
+
*/
|
|
1275
1663
|
}, {
|
|
1276
1664
|
key: "BooleanLiteral",
|
|
1277
1665
|
value: function BooleanLiteral(node) {
|
|
1278
1666
|
return node.value.toString();
|
|
1279
1667
|
}
|
|
1668
|
+
/**
|
|
1669
|
+
* @param {import("@babel/types").AssignmentExpression} node - The Babel AST node.
|
|
1670
|
+
* @returns {string} Stringification of the node.
|
|
1671
|
+
*/
|
|
1280
1672
|
}, {
|
|
1281
1673
|
key: "AssignmentExpression",
|
|
1282
1674
|
value: function AssignmentExpression(node) {
|
|
@@ -1285,8 +1677,13 @@
|
|
|
1285
1677
|
right = node.right;
|
|
1286
1678
|
var left_ = this.toSource(left);
|
|
1287
1679
|
var right_ = this.toSource(right);
|
|
1680
|
+
// operator is for example: = |= &=
|
|
1288
1681
|
return "".concat(left_, " ").concat(operator, " ").concat(right_);
|
|
1289
1682
|
}
|
|
1683
|
+
/**
|
|
1684
|
+
* @param {import("@babel/types").BinaryExpression} node - The Babel AST node.
|
|
1685
|
+
* @returns {string} Stringification of the node.
|
|
1686
|
+
*/
|
|
1290
1687
|
}, {
|
|
1291
1688
|
key: "BinaryExpression",
|
|
1292
1689
|
value: function BinaryExpression(node) {
|
|
@@ -1297,11 +1694,19 @@
|
|
|
1297
1694
|
var right_ = this.toSource(right);
|
|
1298
1695
|
return "".concat(left_, " ").concat(operator, " ").concat(right_);
|
|
1299
1696
|
}
|
|
1697
|
+
/**
|
|
1698
|
+
* @param {import("@babel/types").ThisExpression} node - The Babel AST node.
|
|
1699
|
+
* @returns {string} Stringification of the node.
|
|
1700
|
+
*/
|
|
1300
1701
|
}, {
|
|
1301
1702
|
key: "ThisExpression",
|
|
1302
1703
|
value: function ThisExpression(node) {
|
|
1303
1704
|
return 'this';
|
|
1304
1705
|
}
|
|
1706
|
+
/**
|
|
1707
|
+
* @param {import("@babel/types").ArrayExpression} node - The Babel AST node.
|
|
1708
|
+
* @returns {string} Stringification of the node.
|
|
1709
|
+
*/
|
|
1305
1710
|
}, {
|
|
1306
1711
|
key: "ArrayExpression",
|
|
1307
1712
|
value: function ArrayExpression(node) {
|
|
@@ -1324,6 +1729,10 @@
|
|
|
1324
1729
|
out += '\n' + this.spaces + ']';
|
|
1325
1730
|
return out;
|
|
1326
1731
|
}
|
|
1732
|
+
/**
|
|
1733
|
+
* @param {import("@babel/types").VariableDeclaration} node - The Babel AST node.
|
|
1734
|
+
* @returns {string} Stringification of the node.
|
|
1735
|
+
*/
|
|
1327
1736
|
}, {
|
|
1328
1737
|
key: "VariableDeclaration",
|
|
1329
1738
|
value: function VariableDeclaration(node) {
|
|
@@ -1337,6 +1746,10 @@
|
|
|
1337
1746
|
}
|
|
1338
1747
|
return "".concat(spaces).concat(kind, " ").concat(this.mapToSource(declarations).join(', ')).concat(semicolon);
|
|
1339
1748
|
}
|
|
1749
|
+
/**
|
|
1750
|
+
* @param {import("@babel/types").VariableDeclarator} node - The Babel AST node.
|
|
1751
|
+
* @returns {string} Stringification of the node.
|
|
1752
|
+
*/
|
|
1340
1753
|
}, {
|
|
1341
1754
|
key: "VariableDeclarator",
|
|
1342
1755
|
value: function VariableDeclarator(node) {
|
|
@@ -1347,6 +1760,10 @@
|
|
|
1347
1760
|
}
|
|
1348
1761
|
return this.toSource(id);
|
|
1349
1762
|
}
|
|
1763
|
+
/**
|
|
1764
|
+
* @param {import("@babel/types").ConditionalExpression} node - The Babel AST node.
|
|
1765
|
+
* @returns {string} Stringification of the node.
|
|
1766
|
+
*/
|
|
1350
1767
|
}, {
|
|
1351
1768
|
key: "ConditionalExpression",
|
|
1352
1769
|
value: function ConditionalExpression(node) {
|
|
@@ -1355,6 +1772,12 @@
|
|
|
1355
1772
|
test = node.test;
|
|
1356
1773
|
return "".concat(this.toSource(test), " ? ").concat(this.toSource(consequent), " : ").concat(this.toSource(alternate));
|
|
1357
1774
|
}
|
|
1775
|
+
/**
|
|
1776
|
+
* if (...)
|
|
1777
|
+
*
|
|
1778
|
+
* @param {import("@babel/types").LogicalExpression} node - The Babel AST node.
|
|
1779
|
+
* @returns {string} Stringification of the node.
|
|
1780
|
+
*/
|
|
1358
1781
|
}, {
|
|
1359
1782
|
key: "LogicalExpression",
|
|
1360
1783
|
value: function LogicalExpression(node) {
|
|
@@ -1371,6 +1794,12 @@
|
|
|
1371
1794
|
}
|
|
1372
1795
|
return "".concat(l, " ").concat(operator, " ").concat(r);
|
|
1373
1796
|
}
|
|
1797
|
+
/**
|
|
1798
|
+
* TODO TEST: can init be undefined in for(;;)
|
|
1799
|
+
*
|
|
1800
|
+
* @param {import("@babel/types").ForStatement} node - The Babel AST node.
|
|
1801
|
+
* @returns {string} Stringification of the node.
|
|
1802
|
+
*/
|
|
1374
1803
|
}, {
|
|
1375
1804
|
key: "ForStatement",
|
|
1376
1805
|
value: function ForStatement(node) {
|
|
@@ -1385,6 +1814,12 @@
|
|
|
1385
1814
|
var b = this.toSourceCurly(body);
|
|
1386
1815
|
return "".concat(spaces, "for (").concat(i, "; ").concat(t, "; ").concat(u, ")").concat(b);
|
|
1387
1816
|
}
|
|
1817
|
+
/**
|
|
1818
|
+
* showAST("++i")
|
|
1819
|
+
*
|
|
1820
|
+
* @param {import("@babel/types").UpdateExpression} node - The Babel AST node.
|
|
1821
|
+
* @returns {string} Stringification of the node.
|
|
1822
|
+
*/
|
|
1388
1823
|
}, {
|
|
1389
1824
|
key: "UpdateExpression",
|
|
1390
1825
|
value: function UpdateExpression(node) {
|
|
@@ -1396,6 +1831,10 @@
|
|
|
1396
1831
|
}
|
|
1397
1832
|
return "".concat(this.toSource(argument)).concat(operator);
|
|
1398
1833
|
}
|
|
1834
|
+
/**
|
|
1835
|
+
* @param {import("@babel/types").NewExpression} node - The Babel AST node.
|
|
1836
|
+
* @returns {string} Stringification of the node.
|
|
1837
|
+
*/
|
|
1399
1838
|
}, {
|
|
1400
1839
|
key: "NewExpression",
|
|
1401
1840
|
value: function NewExpression(node) {
|
|
@@ -1405,6 +1844,12 @@
|
|
|
1405
1844
|
var args = this.mapToSource(args_).join(', ');
|
|
1406
1845
|
return "new ".concat(c, "(").concat(args, ")");
|
|
1407
1846
|
}
|
|
1847
|
+
/**
|
|
1848
|
+
* @example
|
|
1849
|
+
* console.log(ast2json(parseSync("`${1} b ${2+3}c`").program.body[0]));
|
|
1850
|
+
* @param {import("@babel/types").TemplateLiteral} node - The Babel AST node.
|
|
1851
|
+
* @returns {string} Stringification of the node.
|
|
1852
|
+
*/
|
|
1408
1853
|
}, {
|
|
1409
1854
|
key: "TemplateLiteral",
|
|
1410
1855
|
value: function TemplateLiteral(node) {
|
|
@@ -1420,12 +1865,20 @@
|
|
|
1420
1865
|
out += '`';
|
|
1421
1866
|
return out;
|
|
1422
1867
|
}
|
|
1868
|
+
/**
|
|
1869
|
+
* @param {import("@babel/types").TemplateElement} node - The Babel AST node.
|
|
1870
|
+
* @returns {string} Stringification of the node.
|
|
1871
|
+
*/
|
|
1423
1872
|
}, {
|
|
1424
1873
|
key: "TemplateElement",
|
|
1425
1874
|
value: function TemplateElement(node) {
|
|
1426
1875
|
var value = node.value;
|
|
1427
1876
|
return value.raw;
|
|
1428
1877
|
}
|
|
1878
|
+
/**
|
|
1879
|
+
* @param {import("@babel/types").ParenthesizedExpression} node - The Babel AST node.
|
|
1880
|
+
* @returns {string} Stringification of the node.
|
|
1881
|
+
*/
|
|
1429
1882
|
}, {
|
|
1430
1883
|
key: "ParenthesizedExpression",
|
|
1431
1884
|
value: function ParenthesizedExpression(node) {
|
|
@@ -1442,23 +1895,39 @@
|
|
|
1442
1895
|
out += '\n' + this.spaces + ')';
|
|
1443
1896
|
return out;
|
|
1444
1897
|
}
|
|
1898
|
+
/**
|
|
1899
|
+
* @param {import("@babel/types").PrivateName} node - The Babel AST node.
|
|
1900
|
+
* @returns {string} Stringification of the node.
|
|
1901
|
+
*/
|
|
1445
1902
|
}, {
|
|
1446
1903
|
key: "PrivateName",
|
|
1447
1904
|
value: function PrivateName(node) {
|
|
1448
1905
|
var id = node.id;
|
|
1449
1906
|
return "#".concat(this.toSource(id));
|
|
1450
1907
|
}
|
|
1908
|
+
/**
|
|
1909
|
+
* @param {import("@babel/types").ExportAllDeclaration} node - The Babel AST node.
|
|
1910
|
+
* @returns {string} Stringification of the node.
|
|
1911
|
+
*/
|
|
1451
1912
|
}, {
|
|
1452
1913
|
key: "ExportAllDeclaration",
|
|
1453
1914
|
value: function ExportAllDeclaration(node) {
|
|
1454
1915
|
return "export * from ".concat(node.source.extra.raw, ";");
|
|
1455
1916
|
}
|
|
1917
|
+
/**
|
|
1918
|
+
* @param {import("@babel/types").ExportNamespaceSpecifier} node - The Babel AST node.
|
|
1919
|
+
* @returns {string} Stringification of the node.
|
|
1920
|
+
*/
|
|
1456
1921
|
}, {
|
|
1457
1922
|
key: "ExportNamespaceSpecifier",
|
|
1458
1923
|
value: function ExportNamespaceSpecifier(node) {
|
|
1459
1924
|
var exported = node.exported;
|
|
1460
1925
|
return '* as ' + this.toSource(exported);
|
|
1461
1926
|
}
|
|
1927
|
+
/**
|
|
1928
|
+
* @param {import("@babel/types").ExportNamedDeclaration} node - The Babel AST node.
|
|
1929
|
+
* @returns {string} Stringification of the node.
|
|
1930
|
+
*/
|
|
1462
1931
|
}, {
|
|
1463
1932
|
key: "ExportNamedDeclaration",
|
|
1464
1933
|
value: function ExportNamedDeclaration(node) {
|
|
@@ -1486,6 +1955,7 @@
|
|
|
1486
1955
|
out += '}';
|
|
1487
1956
|
} else {
|
|
1488
1957
|
out += 'export {\n';
|
|
1958
|
+
// todo: fix spacing system
|
|
1489
1959
|
out += this.mapToSource(specifiers).map(function (_) {
|
|
1490
1960
|
return " ".concat(_this3.spaces).concat(_);
|
|
1491
1961
|
}).join(',\n');
|
|
@@ -1505,6 +1975,10 @@
|
|
|
1505
1975
|
}
|
|
1506
1976
|
return out;
|
|
1507
1977
|
}
|
|
1978
|
+
/**
|
|
1979
|
+
* @param {import("@babel/types").ExportDefaultDeclaration} node - The Babel AST node.
|
|
1980
|
+
* @returns {string} Stringification of the node.
|
|
1981
|
+
*/
|
|
1508
1982
|
}, {
|
|
1509
1983
|
key: "ExportDefaultDeclaration",
|
|
1510
1984
|
value: function ExportDefaultDeclaration(node) {
|
|
@@ -1512,6 +1986,10 @@
|
|
|
1512
1986
|
var a = this.toSource(declaration);
|
|
1513
1987
|
return "export default ".concat(a, ";");
|
|
1514
1988
|
}
|
|
1989
|
+
/**
|
|
1990
|
+
* @param {import("@babel/types").ExportSpecifier} node - The Babel AST node.
|
|
1991
|
+
* @returns {string} Stringification of the node.
|
|
1992
|
+
*/
|
|
1515
1993
|
}, {
|
|
1516
1994
|
key: "ExportSpecifier",
|
|
1517
1995
|
value: function ExportSpecifier(node) {
|
|
@@ -1523,13 +2001,24 @@
|
|
|
1523
2001
|
if (left === right) {
|
|
1524
2002
|
return "".concat(spaces).concat(left);
|
|
1525
2003
|
}
|
|
2004
|
+
// For example:
|
|
2005
|
+
// PostEffect: PostEffect$1\n
|
|
2006
|
+
// createMesh: createMesh$1\n
|
|
1526
2007
|
return "".concat(spaces).concat(right, " as ").concat(left);
|
|
1527
2008
|
}
|
|
2009
|
+
/**
|
|
2010
|
+
* @param {import("@babel/types").Super} node - The Babel AST node.
|
|
2011
|
+
* @returns {string} Stringification of the node.
|
|
2012
|
+
*/
|
|
1528
2013
|
}, {
|
|
1529
2014
|
key: "Super",
|
|
1530
2015
|
value: function Super(node) {
|
|
1531
2016
|
return 'super';
|
|
1532
2017
|
}
|
|
2018
|
+
/**
|
|
2019
|
+
* @param {import("@babel/types").ForInStatement} node - The Babel AST node.
|
|
2020
|
+
* @returns {string} Stringification of the node.
|
|
2021
|
+
*/
|
|
1533
2022
|
}, {
|
|
1534
2023
|
key: "ForInStatement",
|
|
1535
2024
|
value: function ForInStatement(node) {
|
|
@@ -1542,6 +2031,10 @@
|
|
|
1542
2031
|
var b = this.toSourceCurly(body);
|
|
1543
2032
|
return "".concat(spaces, "for (").concat(l, " in ").concat(r, ")").concat(b);
|
|
1544
2033
|
}
|
|
2034
|
+
/**
|
|
2035
|
+
* @param {import("@babel/types").ThrowStatement} node - The Babel AST node.
|
|
2036
|
+
* @returns {string} Stringification of the node.
|
|
2037
|
+
*/
|
|
1545
2038
|
}, {
|
|
1546
2039
|
key: "ThrowStatement",
|
|
1547
2040
|
value: function ThrowStatement(node) {
|
|
@@ -1550,6 +2043,10 @@
|
|
|
1550
2043
|
var arg = this.toSource(argument);
|
|
1551
2044
|
return "".concat(spaces, "throw ").concat(arg, ";");
|
|
1552
2045
|
}
|
|
2046
|
+
/**
|
|
2047
|
+
* @param {import("@babel/types").WhileStatement} node - The Babel AST node.
|
|
2048
|
+
* @returns {string} Stringification of the node.
|
|
2049
|
+
*/
|
|
1553
2050
|
}, {
|
|
1554
2051
|
key: "WhileStatement",
|
|
1555
2052
|
value: function WhileStatement(node) {
|
|
@@ -1560,6 +2057,10 @@
|
|
|
1560
2057
|
var b = this.toSourceCurly(body);
|
|
1561
2058
|
return "".concat(spaces, "while (").concat(t, ")").concat(b);
|
|
1562
2059
|
}
|
|
2060
|
+
/**
|
|
2061
|
+
* @param {import("@babel/types").BreakStatement} node - The Babel AST node.
|
|
2062
|
+
* @returns {string} Stringification of the node.
|
|
2063
|
+
*/
|
|
1563
2064
|
}, {
|
|
1564
2065
|
key: "BreakStatement",
|
|
1565
2066
|
value: function BreakStatement(node) {
|
|
@@ -1571,6 +2072,10 @@
|
|
|
1571
2072
|
out += ';';
|
|
1572
2073
|
return out;
|
|
1573
2074
|
}
|
|
2075
|
+
/**
|
|
2076
|
+
* @param {import("@babel/types").ForOfStatement} node - The Babel AST node.
|
|
2077
|
+
* @returns {string} Stringification of the node.
|
|
2078
|
+
*/
|
|
1574
2079
|
}, {
|
|
1575
2080
|
key: "ForOfStatement",
|
|
1576
2081
|
value: function ForOfStatement(node) {
|
|
@@ -1585,6 +2090,13 @@
|
|
|
1585
2090
|
var a = await_ ? 'await ' : '';
|
|
1586
2091
|
return "".concat(spaces, "for ").concat(a, "(").concat(l, " of ").concat(r, ")").concat(b);
|
|
1587
2092
|
}
|
|
2093
|
+
/**
|
|
2094
|
+
* for (const [a, b] in c)
|
|
2095
|
+
* --> [a, b] is the array pattern
|
|
2096
|
+
*
|
|
2097
|
+
* @param {import("@babel/types").ArrayPattern} node - The Babel AST node.
|
|
2098
|
+
* @returns {string} Stringification of the node.
|
|
2099
|
+
*/
|
|
1588
2100
|
}, {
|
|
1589
2101
|
key: "ArrayPattern",
|
|
1590
2102
|
value: function ArrayPattern(node) {
|
|
@@ -1592,6 +2104,10 @@
|
|
|
1592
2104
|
var e = this.mapToSource(elements).join(', ');
|
|
1593
2105
|
return "[".concat(e, "]");
|
|
1594
2106
|
}
|
|
2107
|
+
/**
|
|
2108
|
+
* @param {import("@babel/types").SwitchStatement} node - The Babel AST node.
|
|
2109
|
+
* @returns {string} Stringification of the node.
|
|
2110
|
+
*/
|
|
1595
2111
|
}, {
|
|
1596
2112
|
key: "SwitchStatement",
|
|
1597
2113
|
value: function SwitchStatement(node) {
|
|
@@ -1604,6 +2120,10 @@
|
|
|
1604
2120
|
out += spaces + '}';
|
|
1605
2121
|
return out;
|
|
1606
2122
|
}
|
|
2123
|
+
/**
|
|
2124
|
+
* @param {import("@babel/types").SwitchCase} node - The Babel AST node.
|
|
2125
|
+
* @returns {string} Stringification of the node.
|
|
2126
|
+
*/
|
|
1607
2127
|
}, {
|
|
1608
2128
|
key: "SwitchCase",
|
|
1609
2129
|
value: function SwitchCase(node) {
|
|
@@ -1617,26 +2137,49 @@
|
|
|
1617
2137
|
}
|
|
1618
2138
|
return "".concat(spaces, "default:\n").concat(c);
|
|
1619
2139
|
}
|
|
2140
|
+
/**
|
|
2141
|
+
* @param {import("@babel/types").RegExpLiteral} node - The Babel AST node.
|
|
2142
|
+
* @returns {string} Stringification of the node.
|
|
2143
|
+
*/
|
|
1620
2144
|
}, {
|
|
1621
2145
|
key: "RegExpLiteral",
|
|
1622
2146
|
value: function RegExpLiteral(node) {
|
|
2147
|
+
// parseSync("/test/gm")
|
|
2148
|
+
// todo figure out why it always exposes node.value === undefined... oversight in Babel?
|
|
1623
2149
|
var extra = node.extra;
|
|
1624
2150
|
node.value;
|
|
1625
2151
|
node.pattern;
|
|
1626
2152
|
node.flags;
|
|
1627
2153
|
return extra.raw;
|
|
1628
2154
|
}
|
|
2155
|
+
/**
|
|
2156
|
+
* for (var i=0, n=arr.length; i<n; i++)
|
|
2157
|
+
* sequence expression: var i=0, n=arr.length
|
|
2158
|
+
*
|
|
2159
|
+
* @param {import("@babel/types").SequenceExpression} node - The Babel AST node.
|
|
2160
|
+
* @returns {string} Stringification of the node.
|
|
2161
|
+
*/
|
|
1629
2162
|
}, {
|
|
1630
2163
|
key: "SequenceExpression",
|
|
1631
2164
|
value: function SequenceExpression(node) {
|
|
1632
2165
|
var expressions = node.expressions;
|
|
1633
2166
|
return this.mapToSource(expressions).join(', ');
|
|
1634
2167
|
}
|
|
2168
|
+
/**
|
|
2169
|
+
* showAST("if (true);");
|
|
2170
|
+
*
|
|
2171
|
+
* @param {import("@babel/types").EmptyStatement} node - The Babel AST node.
|
|
2172
|
+
* @returns {string} Stringification of the node.
|
|
2173
|
+
*/
|
|
1635
2174
|
}, {
|
|
1636
2175
|
key: "EmptyStatement",
|
|
1637
2176
|
value: function EmptyStatement(node) {
|
|
1638
2177
|
return ';';
|
|
1639
2178
|
}
|
|
2179
|
+
/**
|
|
2180
|
+
* @param {import("@babel/types").SpreadElement} node - The Babel AST node.
|
|
2181
|
+
* @returns {string} Stringification of the node.
|
|
2182
|
+
*/
|
|
1640
2183
|
}, {
|
|
1641
2184
|
key: "SpreadElement",
|
|
1642
2185
|
value: function SpreadElement(node) {
|
|
@@ -1644,9 +2187,15 @@
|
|
|
1644
2187
|
var a = this.toSource(argument);
|
|
1645
2188
|
return "...".concat(a);
|
|
1646
2189
|
}
|
|
2190
|
+
/**
|
|
2191
|
+
* @param {import("@babel/types").ObjectMethod} node - The Babel AST node.
|
|
2192
|
+
* @returns {string} Stringification of the node.
|
|
2193
|
+
*/
|
|
1647
2194
|
}, {
|
|
1648
2195
|
key: "ObjectMethod",
|
|
1649
2196
|
value: function ObjectMethod(node) {
|
|
2197
|
+
// @todo PR in Babel why method/id is a key in node... (seems like a bug/oversight)
|
|
2198
|
+
// method === true just indicates kind === 'method'
|
|
1650
2199
|
node.method;
|
|
1651
2200
|
var key = node.key,
|
|
1652
2201
|
computed = node.computed,
|
|
@@ -1660,6 +2209,10 @@
|
|
|
1660
2209
|
console.warn("ObjectMethod> id !== null is unhandled", node);
|
|
1661
2210
|
debugger;
|
|
1662
2211
|
}
|
|
2212
|
+
// if (method) {
|
|
2213
|
+
// console.warn("ObjectMethod> node was a method", node);
|
|
2214
|
+
// debugger;
|
|
2215
|
+
// }
|
|
1663
2216
|
var out = this.spaces;
|
|
1664
2217
|
if (generator) {
|
|
1665
2218
|
out += '*';
|
|
@@ -1686,6 +2239,11 @@
|
|
|
1686
2239
|
out += this.toSource(body);
|
|
1687
2240
|
return out;
|
|
1688
2241
|
}
|
|
2242
|
+
/**
|
|
2243
|
+
* E.g. function testComma({x,y,z,}) {}
|
|
2244
|
+
* @param {import("@babel/types").ObjectPattern} node - The Babel AST node.
|
|
2245
|
+
* @returns {string} Stringification of the node.
|
|
2246
|
+
*/
|
|
1689
2247
|
}, {
|
|
1690
2248
|
key: "ObjectPattern",
|
|
1691
2249
|
value: function ObjectPattern(node) {
|
|
@@ -1706,6 +2264,16 @@
|
|
|
1706
2264
|
out += '}';
|
|
1707
2265
|
return out;
|
|
1708
2266
|
}
|
|
2267
|
+
/**
|
|
2268
|
+
* > x?.y
|
|
2269
|
+
* > x?.y.z
|
|
2270
|
+
* > x[y?.z]
|
|
2271
|
+
* > x?.[y?.z]
|
|
2272
|
+
* > b?.file?.variants[variant]
|
|
2273
|
+
*
|
|
2274
|
+
* @param {import("@babel/types").OptionalMemberExpression} node - The Babel AST node.
|
|
2275
|
+
* @returns {string} Stringification of the node.
|
|
2276
|
+
*/
|
|
1709
2277
|
}, {
|
|
1710
2278
|
key: "OptionalMemberExpression",
|
|
1711
2279
|
value: function OptionalMemberExpression(node) {
|
|
@@ -1715,6 +2283,7 @@
|
|
|
1715
2283
|
optional = node.optional;
|
|
1716
2284
|
var a = this.toSource(object);
|
|
1717
2285
|
var b = this.toSource(property);
|
|
2286
|
+
// Basically four cases: computed=true/false optional=true/false, 00, 01, 10, 11
|
|
1718
2287
|
if (!computed && !optional) {
|
|
1719
2288
|
return "".concat(a, ".").concat(b);
|
|
1720
2289
|
} else if (!computed && optional) {
|
|
@@ -1722,8 +2291,17 @@
|
|
|
1722
2291
|
} else if (computed && !optional) {
|
|
1723
2292
|
return "".concat(a, "[").concat(b, "]");
|
|
1724
2293
|
}
|
|
2294
|
+
// Can only be case 4 now (computed && optional):
|
|
1725
2295
|
return "".concat(a, "?.[").concat(b, "]");
|
|
1726
2296
|
}
|
|
2297
|
+
/**
|
|
2298
|
+
* > version?.indexOf('$');
|
|
2299
|
+
* > version?.indexOf?.('$');
|
|
2300
|
+
* > this.passEncoder?.pushDebugGroup(name);
|
|
2301
|
+
*
|
|
2302
|
+
* @param {import("@babel/types").OptionalCallExpression} node - The Babel AST node.
|
|
2303
|
+
* @returns {string} Stringification of the node.
|
|
2304
|
+
*/
|
|
1727
2305
|
}, {
|
|
1728
2306
|
key: "OptionalCallExpression",
|
|
1729
2307
|
value: function OptionalCallExpression(node) {
|
|
@@ -1737,6 +2315,10 @@
|
|
|
1737
2315
|
}
|
|
1738
2316
|
return "".concat(a, "(").concat(b, ")");
|
|
1739
2317
|
}
|
|
2318
|
+
/**
|
|
2319
|
+
* @param {import("@babel/types").DoWhileStatement} node - The Babel AST node.
|
|
2320
|
+
* @returns {string} Stringification of the node.
|
|
2321
|
+
*/
|
|
1740
2322
|
}, {
|
|
1741
2323
|
key: "DoWhileStatement",
|
|
1742
2324
|
value: function DoWhileStatement(node) {
|
|
@@ -1750,6 +2332,10 @@
|
|
|
1750
2332
|
out += " while (".concat(this.toSource(test), ");");
|
|
1751
2333
|
return out;
|
|
1752
2334
|
}
|
|
2335
|
+
/**
|
|
2336
|
+
* @param {import("@babel/types").TryStatement} node - The Babel AST node.
|
|
2337
|
+
* @returns {string} Stringification of the node.
|
|
2338
|
+
*/
|
|
1753
2339
|
}, {
|
|
1754
2340
|
key: "TryStatement",
|
|
1755
2341
|
value: function TryStatement(node) {
|
|
@@ -1767,6 +2353,10 @@
|
|
|
1767
2353
|
}
|
|
1768
2354
|
return out;
|
|
1769
2355
|
}
|
|
2356
|
+
/**
|
|
2357
|
+
* @param {import("@babel/types").CatchClause} node - The Babel AST node.
|
|
2358
|
+
* @returns {string} Stringification of the node.
|
|
2359
|
+
*/
|
|
1770
2360
|
}, {
|
|
1771
2361
|
key: "CatchClause",
|
|
1772
2362
|
value: function CatchClause(node) {
|
|
@@ -1777,29 +2367,49 @@
|
|
|
1777
2367
|
var p = this.toSource(param);
|
|
1778
2368
|
return " catch (".concat(p, ") ").concat(b);
|
|
1779
2369
|
}
|
|
2370
|
+
// Example: try { 1n / 0 } catch {}
|
|
1780
2371
|
return " catch ".concat(b);
|
|
1781
2372
|
}
|
|
2373
|
+
/**
|
|
2374
|
+
* @param {import("@babel/types").RestElement} node - The Babel AST node.
|
|
2375
|
+
* @returns {string} Stringification of the node.
|
|
2376
|
+
*/
|
|
1782
2377
|
}, {
|
|
1783
2378
|
key: "RestElement",
|
|
1784
2379
|
value: function RestElement(node) {
|
|
1785
2380
|
var argument = node.argument;
|
|
1786
2381
|
return "...".concat(this.toSource(argument));
|
|
1787
2382
|
}
|
|
2383
|
+
/**
|
|
2384
|
+
* @param {import("@babel/types").DebuggerStatement} node - The Babel AST node.
|
|
2385
|
+
* @returns {string} Stringification of the node.
|
|
2386
|
+
*/
|
|
1788
2387
|
}, {
|
|
1789
2388
|
key: "DebuggerStatement",
|
|
1790
2389
|
value: function DebuggerStatement(node) {
|
|
1791
2390
|
return "".concat(this.spaces, "debugger;");
|
|
1792
2391
|
}
|
|
2392
|
+
/**
|
|
2393
|
+
* @param {import("@babel/types").Import} node - The Babel AST node.
|
|
2394
|
+
* @returns {string} Stringification of the node.
|
|
2395
|
+
*/
|
|
1793
2396
|
}, {
|
|
1794
2397
|
key: "Import",
|
|
1795
2398
|
value: function Import(node) {
|
|
1796
2399
|
return 'import';
|
|
1797
2400
|
}
|
|
2401
|
+
/**
|
|
2402
|
+
* @param {import("@babel/types").ImportDeclaration} node - The Babel AST node.
|
|
2403
|
+
* @returns {string} Stringification of the node.
|
|
2404
|
+
*/
|
|
1798
2405
|
}, {
|
|
1799
2406
|
key: "ImportDeclaration",
|
|
1800
2407
|
value: function ImportDeclaration(node) {
|
|
1801
2408
|
var specifiers = node.specifiers,
|
|
1802
2409
|
source = node.source;
|
|
2410
|
+
// ImportNamespaceSpecifier: import * as a from "b";
|
|
2411
|
+
// ImportDefaultSpecifier : import a from "b";
|
|
2412
|
+
// ImportSpecifier : import { a } from "b";
|
|
1803
2413
|
var a = this.mapToSource(specifiers).join(', ');
|
|
1804
2414
|
var b = this.toSource(source);
|
|
1805
2415
|
if (specifiers.length === 0) {
|
|
@@ -1810,6 +2420,10 @@
|
|
|
1810
2420
|
}
|
|
1811
2421
|
return "import {".concat(a, "} from ").concat(b, ";");
|
|
1812
2422
|
}
|
|
2423
|
+
/**
|
|
2424
|
+
* @param {import("@babel/types").ImportSpecifier} node - The Babel AST node.
|
|
2425
|
+
* @returns {string} Stringification of the node.
|
|
2426
|
+
*/
|
|
1813
2427
|
}, {
|
|
1814
2428
|
key: "ImportSpecifier",
|
|
1815
2429
|
value: function ImportSpecifier(node) {
|
|
@@ -1822,37 +2436,61 @@
|
|
|
1822
2436
|
}
|
|
1823
2437
|
return a;
|
|
1824
2438
|
}
|
|
2439
|
+
/**
|
|
2440
|
+
* @param {import("@babel/types").ImportDefaultSpecifier} node - The Babel AST node.
|
|
2441
|
+
* @returns {string} Stringification of the node.
|
|
2442
|
+
*/
|
|
1825
2443
|
}, {
|
|
1826
2444
|
key: "ImportDefaultSpecifier",
|
|
1827
2445
|
value: function ImportDefaultSpecifier(node) {
|
|
1828
2446
|
var local = node.local;
|
|
1829
2447
|
return this.toSource(local);
|
|
1830
2448
|
}
|
|
2449
|
+
/**
|
|
2450
|
+
* @param {import("@babel/types").ImportNamespaceSpecifier} node - The Babel AST node.
|
|
2451
|
+
* @returns {string} Stringification of the node.
|
|
2452
|
+
*/
|
|
1831
2453
|
}, {
|
|
1832
2454
|
key: "ImportNamespaceSpecifier",
|
|
1833
2455
|
value: function ImportNamespaceSpecifier(node) {
|
|
1834
2456
|
var local = node.local;
|
|
1835
2457
|
return "* as ".concat(this.toSource(local));
|
|
1836
2458
|
}
|
|
2459
|
+
/**
|
|
2460
|
+
* @param {import("@babel/types").File} node - The Babel AST node.
|
|
2461
|
+
* @returns {string} Stringification of the node.
|
|
2462
|
+
*/
|
|
1837
2463
|
}, {
|
|
1838
2464
|
key: "File",
|
|
1839
2465
|
value: function File(node) {
|
|
1840
2466
|
return this.toSource(node.program) + '\n';
|
|
1841
2467
|
}
|
|
2468
|
+
/**
|
|
2469
|
+
* @param {import("@babel/types").Program} node - The Babel AST node.
|
|
2470
|
+
* @returns {string} Stringification of the node.
|
|
2471
|
+
*/
|
|
1842
2472
|
}, {
|
|
1843
2473
|
key: "Program",
|
|
1844
2474
|
value: function Program(node) {
|
|
1845
2475
|
var body = node.body,
|
|
1846
2476
|
directives = node.directives;
|
|
1847
2477
|
var out = '';
|
|
2478
|
+
// @todo I would like to keep comments above and below,
|
|
2479
|
+
// but below one is currently dropped (does't matter for AST)
|
|
2480
|
+
// See: test/typechecking/directive.mjs
|
|
1848
2481
|
out += this.mapToSource(directives);
|
|
1849
2482
|
out += this.mapToSource(body).join('\n');
|
|
1850
2483
|
return out;
|
|
1851
2484
|
}
|
|
2485
|
+
/**
|
|
2486
|
+
* @param {import("@babel/types").StringLiteral} node - The Babel AST node.
|
|
2487
|
+
* @returns {string} Stringification of the node.
|
|
2488
|
+
*/
|
|
1852
2489
|
}, {
|
|
1853
2490
|
key: "StringLiteral",
|
|
1854
2491
|
value: function StringLiteral(node) {
|
|
1855
2492
|
var extra = node.extra;
|
|
2493
|
+
// Never experienced this so far, but types are types...
|
|
1856
2494
|
if (!extra) {
|
|
1857
2495
|
debugger;
|
|
1858
2496
|
return '';
|
|
@@ -1863,11 +2501,19 @@
|
|
|
1863
2501
|
}
|
|
1864
2502
|
return extra.raw;
|
|
1865
2503
|
}
|
|
2504
|
+
/**
|
|
2505
|
+
* @param {import("@babel/types").NumericLiteral} node - The Babel AST node.
|
|
2506
|
+
* @returns {string} Stringification of the node.
|
|
2507
|
+
*/
|
|
1866
2508
|
}, {
|
|
1867
2509
|
key: "NumericLiteral",
|
|
1868
2510
|
value: function NumericLiteral(node) {
|
|
1869
2511
|
return node.extra.raw;
|
|
1870
2512
|
}
|
|
2513
|
+
/**
|
|
2514
|
+
* @param {import("@babel/types").AssignmentPattern} node - The Babel AST node.
|
|
2515
|
+
* @returns {string} Stringification of the node.
|
|
2516
|
+
*/
|
|
1871
2517
|
}, {
|
|
1872
2518
|
key: "AssignmentPattern",
|
|
1873
2519
|
value: function AssignmentPattern(node) {
|
|
@@ -1875,11 +2521,19 @@
|
|
|
1875
2521
|
right = node.right;
|
|
1876
2522
|
return "".concat(this.toSource(left), " = ").concat(this.toSource(right));
|
|
1877
2523
|
}
|
|
2524
|
+
/**
|
|
2525
|
+
* @param {import("@babel/types").NullLiteral} node - The Babel AST node.
|
|
2526
|
+
* @returns {string} Stringification of the node.
|
|
2527
|
+
*/
|
|
1878
2528
|
}, {
|
|
1879
2529
|
key: "NullLiteral",
|
|
1880
2530
|
value: function NullLiteral(node) {
|
|
1881
2531
|
return 'null';
|
|
1882
2532
|
}
|
|
2533
|
+
/**
|
|
2534
|
+
* @param {import("@babel/types").TaggedTemplateExpression} node - The Babel AST node.
|
|
2535
|
+
* @returns {string} Stringification of the node.
|
|
2536
|
+
*/
|
|
1883
2537
|
}, {
|
|
1884
2538
|
key: "TaggedTemplateExpression",
|
|
1885
2539
|
value: function TaggedTemplateExpression(node) {
|
|
@@ -1889,6 +2543,10 @@
|
|
|
1889
2543
|
var q = this.toSource(quasi);
|
|
1890
2544
|
return t + q;
|
|
1891
2545
|
}
|
|
2546
|
+
/**
|
|
2547
|
+
* @param {import("@babel/types").YieldExpression} node - The Babel AST node.
|
|
2548
|
+
* @returns {string} Stringification of the node.
|
|
2549
|
+
*/
|
|
1892
2550
|
}, {
|
|
1893
2551
|
key: "YieldExpression",
|
|
1894
2552
|
value: function YieldExpression(node) {
|
|
@@ -1905,9 +2563,25 @@
|
|
|
1905
2563
|
return Stringifier;
|
|
1906
2564
|
}();
|
|
1907
2565
|
|
|
1908
|
-
|
|
2566
|
+
/** @typedef {import('@babel/types').Node } Node */
|
|
2567
|
+
/** @typedef {import("@babel/types").ClassMethod } ClassMethod */
|
|
2568
|
+
/** @typedef {import("@babel/types").ClassPrivateMethod} ClassPrivateMethod */
|
|
2569
|
+
/** @typedef {import('./stat.mjs').Stat } Stat */
|
|
2570
|
+
/**
|
|
2571
|
+
* @typedef {object} Options
|
|
2572
|
+
* @property {boolean} [forceCurly] - Determines whether curly braces are enforced in Stringifier.
|
|
2573
|
+
* @property {boolean} [validateDivision] - Indicates whether division operations should be validated.
|
|
2574
|
+
* @property {Function} [expandType] - A function that expands shorthand types into full descriptions.
|
|
2575
|
+
* @property {string} [filename] - The name of a file to which the instance pertains.
|
|
2576
|
+
* @property {boolean} [addHeader] - Whether to add import declarations headers. Defaults to true.
|
|
2577
|
+
* @property {string[]} [ignoreLocations] - Ignore these locations because they are known false-positives.
|
|
2578
|
+
*/
|
|
2579
|
+
var Asserter = /*#__PURE__*/function (_Stringifier) {
|
|
1909
2580
|
_inherits(Asserter, _Stringifier);
|
|
1910
2581
|
var _super = _createSuper(Asserter);
|
|
2582
|
+
/**
|
|
2583
|
+
* @param {Options} [options] - The options.
|
|
2584
|
+
*/
|
|
1911
2585
|
function Asserter() {
|
|
1912
2586
|
var _this;
|
|
1913
2587
|
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
|
@@ -1919,9 +2593,12 @@
|
|
|
1919
2593
|
expandType = _ref$expandType === void 0 ? expandTypeDepFree : _ref$expandType,
|
|
1920
2594
|
filename = _ref.filename,
|
|
1921
2595
|
_ref$addHeader = _ref.addHeader,
|
|
1922
|
-
addHeader = _ref$addHeader === void 0 ? true : _ref$addHeader
|
|
2596
|
+
addHeader = _ref$addHeader === void 0 ? true : _ref$addHeader,
|
|
2597
|
+
_ref$ignoreLocations = _ref.ignoreLocations,
|
|
2598
|
+
ignoreLocations = _ref$ignoreLocations === void 0 ? [] : _ref$ignoreLocations;
|
|
1923
2599
|
_classCallCheck(this, Asserter);
|
|
1924
2600
|
_this = _super.call(this);
|
|
2601
|
+
/** @type {Record<string, Stat>} */
|
|
1925
2602
|
_defineProperty(_assertThisInitialized(_this), "stats", {
|
|
1926
2603
|
'ArrowFunctionExpression': {
|
|
1927
2604
|
checked: 0,
|
|
@@ -1968,17 +2645,28 @@
|
|
|
1968
2645
|
unchecked: 0
|
|
1969
2646
|
}
|
|
1970
2647
|
});
|
|
2648
|
+
/** @type {Record<string, object>} */
|
|
1971
2649
|
_defineProperty(_assertThisInitialized(_this), "typedefs", {});
|
|
1972
2650
|
_this.forceCurly = forceCurly;
|
|
1973
2651
|
_this.validateDivision = validateDivision;
|
|
2652
|
+
// @todo collect every type + manually validate as test set
|
|
2653
|
+
// + implement expandType using Babel Flow type parser aswell
|
|
1974
2654
|
_this.expandType = expandType;
|
|
1975
2655
|
_this.filename = filename;
|
|
1976
2656
|
_this.addHeader = addHeader;
|
|
2657
|
+
_this.ignoreLocations = ignoreLocations;
|
|
1977
2658
|
return _this;
|
|
1978
2659
|
}
|
|
1979
2660
|
_createClass(Asserter, [{
|
|
1980
2661
|
key: "ArrowFunctionExpression",
|
|
1981
|
-
value:
|
|
2662
|
+
value:
|
|
2663
|
+
/**
|
|
2664
|
+
* We expand type-asserted ArrowFunctionExpressions in order to add type assertions.
|
|
2665
|
+
* @override
|
|
2666
|
+
* @param {import("@babel/types").ArrowFunctionExpression} node - The Babel AST node.
|
|
2667
|
+
* @returns {string} Stringification of the node.
|
|
2668
|
+
*/
|
|
2669
|
+
function ArrowFunctionExpression(node) {
|
|
1982
2670
|
var async = node.async,
|
|
1983
2671
|
body = node.body,
|
|
1984
2672
|
generator = node.generator,
|
|
@@ -2002,6 +2690,11 @@
|
|
|
2002
2690
|
}
|
|
2003
2691
|
return out;
|
|
2004
2692
|
}
|
|
2693
|
+
/**
|
|
2694
|
+
* @override
|
|
2695
|
+
* @param {import("@babel/types").ClassDeclaration} node - The Babel AST node.
|
|
2696
|
+
* @returns {string} Stringification of the node.
|
|
2697
|
+
*/
|
|
2005
2698
|
}, {
|
|
2006
2699
|
key: "ClassDeclaration",
|
|
2007
2700
|
value: function ClassDeclaration(node) {
|
|
@@ -2011,6 +2704,14 @@
|
|
|
2011
2704
|
out += "".concat(this.spaces, "registerClass(").concat(id_, ");");
|
|
2012
2705
|
return out;
|
|
2013
2706
|
}
|
|
2707
|
+
/**
|
|
2708
|
+
* Finds the closest ancestor of the given node that matches the specified type.
|
|
2709
|
+
*
|
|
2710
|
+
* @param {Node} node - The starting node to search from.
|
|
2711
|
+
* @param {T} type - Type name of the node to search for.
|
|
2712
|
+
* @template {Node['type']} T
|
|
2713
|
+
* @returns {Extract<Node, {type: T}>|undefined} The first ancestor node of the specified type, or undefined if none is found.
|
|
2714
|
+
*/
|
|
2014
2715
|
}, {
|
|
2015
2716
|
key: "findParentOfType",
|
|
2016
2717
|
value: function findParentOfType(node, type) {
|
|
@@ -2024,6 +2725,13 @@
|
|
|
2024
2725
|
return _.type === type;
|
|
2025
2726
|
});
|
|
2026
2727
|
}
|
|
2728
|
+
/**
|
|
2729
|
+
* Alternatively "import * as rti from ..." would also prevent "Unused external imports" warning...
|
|
2730
|
+
* or keeping log of every single call during RTI parsing.
|
|
2731
|
+
* @todo
|
|
2732
|
+
* Once we went over every node, we can see if we really require registerTypef, registerClass etc.
|
|
2733
|
+
* @returns {string} The import declaration header for importing RTI.
|
|
2734
|
+
*/
|
|
2027
2735
|
}, {
|
|
2028
2736
|
key: "getHeader",
|
|
2029
2737
|
value: function getHeader() {
|
|
@@ -2035,9 +2743,19 @@
|
|
|
2035
2743
|
header += ", validateDivision";
|
|
2036
2744
|
}
|
|
2037
2745
|
header += ", registerTypedef, registerClass} from '@runtime-type-inspector/runtime';\n";
|
|
2746
|
+
// Prevent tree-shaking in UMD build so we can always "add a breakpoint here".
|
|
2038
2747
|
header += "export * from '@runtime-type-inspector/runtime';\n";
|
|
2039
2748
|
return header;
|
|
2040
2749
|
}
|
|
2750
|
+
/**
|
|
2751
|
+
* Retrieves the node associated with the leading comments for an arrow function expression.
|
|
2752
|
+
*
|
|
2753
|
+
* This method travels up the syntax tree from the given node to find a parent node with leading comments.
|
|
2754
|
+
* This search is bounded by function boundaries or a 'CallExpression' node, as per the logic defined within the loop.
|
|
2755
|
+
* @param {Node} node - The node representing the arrow function expression for which to find the leading comments node.
|
|
2756
|
+
* @returns {Node|undefined} The node that contains the leading comments, or `undefined`
|
|
2757
|
+
* if none is found before reaching a different function or 'CallExpression'.
|
|
2758
|
+
*/
|
|
2041
2759
|
}, {
|
|
2042
2760
|
key: "getLeadingCommentsNodeForArrowFunctionExpression",
|
|
2043
2761
|
value: function getLeadingCommentsNodeForArrowFunctionExpression(node) {
|
|
@@ -2049,9 +2767,16 @@
|
|
|
2049
2767
|
if (parent.leadingComments) {
|
|
2050
2768
|
return parent;
|
|
2051
2769
|
}
|
|
2770
|
+
// Skip now, if we find another function first,
|
|
2771
|
+
// there is no JSDoc for our function anymore.
|
|
2772
|
+
// Not interested in our start node if it didn't
|
|
2773
|
+
// contain leadingComments.
|
|
2052
2774
|
i--;
|
|
2053
2775
|
while (i >= 0) {
|
|
2054
2776
|
parent = parents[i];
|
|
2777
|
+
//if (parent.type === 'CallExpression') {
|
|
2778
|
+
// break;
|
|
2779
|
+
//}
|
|
2055
2780
|
if (nodeIsFunction(parent)) {
|
|
2056
2781
|
break;
|
|
2057
2782
|
}
|
|
@@ -2061,6 +2786,10 @@
|
|
|
2061
2786
|
i--;
|
|
2062
2787
|
}
|
|
2063
2788
|
}
|
|
2789
|
+
/**
|
|
2790
|
+
* Emits a warning message to the console, optionally prefixed with the instance's filename.
|
|
2791
|
+
* @param {...any} args - A list of arguments to be passed to the console.warn function.
|
|
2792
|
+
*/
|
|
2064
2793
|
}, {
|
|
2065
2794
|
key: "warn",
|
|
2066
2795
|
value: function warn() {
|
|
@@ -2081,9 +2810,16 @@
|
|
|
2081
2810
|
if (parent.leadingComments) {
|
|
2082
2811
|
return parent;
|
|
2083
2812
|
}
|
|
2813
|
+
// Skip now, if we find another function first,
|
|
2814
|
+
// there is no JSDoc for our function anymore.
|
|
2815
|
+
// Not interested in our start node if it didn't
|
|
2816
|
+
// contain leadingComments.
|
|
2084
2817
|
i--;
|
|
2085
2818
|
while (i >= 0) {
|
|
2086
2819
|
parent = parents[i];
|
|
2820
|
+
//if (parent.type === 'CallExpression') {
|
|
2821
|
+
// break;
|
|
2822
|
+
//}
|
|
2087
2823
|
if (nodeIsFunction(parent)) {
|
|
2088
2824
|
break;
|
|
2089
2825
|
}
|
|
@@ -2092,7 +2828,26 @@
|
|
|
2092
2828
|
}
|
|
2093
2829
|
i--;
|
|
2094
2830
|
}
|
|
2095
|
-
|
|
2831
|
+
/** @todo convert all files in test/typechecking/*.mjs into full unit tests */
|
|
2832
|
+
// Old way:
|
|
2833
|
+
// if (node.leadingComments) {
|
|
2834
|
+
// return node.leadingComments;
|
|
2835
|
+
// }
|
|
2836
|
+
// node = this.findParentOfType(node, 'ExpressionStatement');
|
|
2837
|
+
// if (!node) {
|
|
2838
|
+
// /**
|
|
2839
|
+
// * @todo Need more refactoring, see missing type-assertions in test/typechecking/good-old-es5.mjs
|
|
2840
|
+
// */
|
|
2841
|
+
// node = this.parents.findLast(_ => _.type === 'VariableDeclaration');
|
|
2842
|
+
// if (!node) {
|
|
2843
|
+
// return;
|
|
2844
|
+
// }
|
|
2845
|
+
// }
|
|
2846
|
+
}
|
|
2847
|
+
/**
|
|
2848
|
+
* @param {Node} node - The Babel AST node.
|
|
2849
|
+
* @returns {undefined | {}} The return value of `parseJSDoc`.
|
|
2850
|
+
*/
|
|
2096
2851
|
}, {
|
|
2097
2852
|
key: "getJSDoc",
|
|
2098
2853
|
value: function getJSDoc(node) {
|
|
@@ -2101,10 +2856,12 @@
|
|
|
2101
2856
|
}
|
|
2102
2857
|
var _node = node,
|
|
2103
2858
|
leadingComments = _node.leadingComments;
|
|
2859
|
+
// Receive the leadingComments from the ExpressionStatement, not the FunctionExpression itself.
|
|
2104
2860
|
if (node.type === 'FunctionExpression') {
|
|
2105
2861
|
var tmp = this.getLeadingCommentsNodeForFunctionExpression(node);
|
|
2106
2862
|
leadingComments = tmp === null || tmp === void 0 ? void 0 : tmp.leadingComments;
|
|
2107
2863
|
}
|
|
2864
|
+
// Receive the leadingComments from ExportNamedDeclaration, if FunctionDeclaration has none
|
|
2108
2865
|
if (!leadingComments) {
|
|
2109
2866
|
if (node.type === 'FunctionDeclaration') {
|
|
2110
2867
|
var exportNamedDeclaration = this.findParentOfType(node, 'ExportNamedDeclaration');
|
|
@@ -2135,6 +2892,15 @@
|
|
|
2135
2892
|
}
|
|
2136
2893
|
}
|
|
2137
2894
|
}
|
|
2895
|
+
/**
|
|
2896
|
+
* Retrieves the name of a parameter from a Babel AST node.
|
|
2897
|
+
*
|
|
2898
|
+
* This function expects a node representing a function parameter and attempts to extract
|
|
2899
|
+
* the parameter's name directly or from an AssignmentPattern.
|
|
2900
|
+
*
|
|
2901
|
+
* @param {Node} param - The AST node representing the function parameter from which to extract the name.
|
|
2902
|
+
* @returns {string} The name of the parameter as a string, or the parameter's source code if the extraction fails.
|
|
2903
|
+
*/
|
|
2138
2904
|
}, {
|
|
2139
2905
|
key: "getNameOfParam",
|
|
2140
2906
|
value: function getNameOfParam(param) {
|
|
@@ -2159,17 +2925,27 @@
|
|
|
2159
2925
|
value: function statsPrint() {
|
|
2160
2926
|
console.table(this.stats);
|
|
2161
2927
|
}
|
|
2928
|
+
/**
|
|
2929
|
+
* Retrieves statistical information for a given Babel AST node of this instance.
|
|
2930
|
+
*
|
|
2931
|
+
* @param {Node} node - The Babel AST node for which the statistical data is retrieved.
|
|
2932
|
+
* @returns {Stat} An object containing the statistical data for the specified node. If the
|
|
2933
|
+
* node type is unhandled, defaults to returning a dummy object with 'checked' and 'unchecked'
|
|
2934
|
+
* properties both set to 0.
|
|
2935
|
+
*/
|
|
2162
2936
|
}, {
|
|
2163
2937
|
key: "getStatsForNode",
|
|
2164
2938
|
value: function getStatsForNode(node) {
|
|
2165
2939
|
var stats = this.stats;
|
|
2166
2940
|
var type = nodeIsFunction(node) ? node.type : this.parentType;
|
|
2167
2941
|
if (type === 'ClassMethod') {
|
|
2168
|
-
var parent =
|
|
2942
|
+
var parent = /** @type {ClassMethod} */
|
|
2943
|
+
this.parent;
|
|
2169
2944
|
var kind = parent.kind;
|
|
2170
2945
|
return stats["ClassMethod#".concat(kind)];
|
|
2171
2946
|
} else if (type === 'ClassPrivateMethod') {
|
|
2172
|
-
var _parent =
|
|
2947
|
+
var _parent = /** @type {ClassPrivateMethod} */
|
|
2948
|
+
this.parent;
|
|
2173
2949
|
var _kind = _parent.kind;
|
|
2174
2950
|
return stats["ClassPrivateMethod#".concat(_kind)];
|
|
2175
2951
|
}
|
|
@@ -2183,6 +2959,17 @@
|
|
|
2183
2959
|
}
|
|
2184
2960
|
return stat;
|
|
2185
2961
|
}
|
|
2962
|
+
/**
|
|
2963
|
+
* Checks if a provided Babel AST node has a parameter with the given name.
|
|
2964
|
+
*
|
|
2965
|
+
* This function will look at the node's parameters if available and determine whether
|
|
2966
|
+
* one of them matches the provided name. Supports various parameter types such as Identifiers
|
|
2967
|
+
* and AssignmentPatterns.
|
|
2968
|
+
*
|
|
2969
|
+
* @param {Node} node - The Babel AST node to inspect. If it's a BlockStatement, the parent node is used instead.
|
|
2970
|
+
* @param {string} name - The name of the parameter to look for within the node's parameters.
|
|
2971
|
+
* @returns {boolean} True if the node has a parameter with the given name; false otherwise.
|
|
2972
|
+
*/
|
|
2186
2973
|
}, {
|
|
2187
2974
|
key: "nodeHasParamName",
|
|
2188
2975
|
value: function nodeHasParamName(node, name) {
|
|
@@ -2215,6 +3002,18 @@
|
|
|
2215
3002
|
return false;
|
|
2216
3003
|
});
|
|
2217
3004
|
}
|
|
3005
|
+
/**
|
|
3006
|
+
* Generates a string containing type checks for a given Babel AST node based on associated JSDoc information.
|
|
3007
|
+
*
|
|
3008
|
+
* This function analyzes the node and its JSDoc annotations to construct runtime type
|
|
3009
|
+
* check expressions. It handles various parameter patterns and outputs code that performs
|
|
3010
|
+
* actual type assertions. If a node does not correspond to any known or supported pattern,
|
|
3011
|
+
* it returns an empty string.
|
|
3012
|
+
*
|
|
3013
|
+
* @override
|
|
3014
|
+
* @param {Node} node - The Babel AST node for which to generate type checks.
|
|
3015
|
+
* @returns {string} A string of code with type check assertions, based on the JSDoc comments associated with the given node.
|
|
3016
|
+
*/
|
|
2218
3017
|
}, {
|
|
2219
3018
|
key: "generateTypeChecks",
|
|
2220
3019
|
value: function generateTypeChecks(node) {
|
|
@@ -2224,6 +3023,7 @@
|
|
|
2224
3023
|
return '';
|
|
2225
3024
|
}
|
|
2226
3025
|
var jsdoc = this.getJSDoc(node);
|
|
3026
|
+
// return '// ' + JSON.stringify(jsdoc) + '\n';
|
|
2227
3027
|
var stat = this.getStatsForNode(node);
|
|
2228
3028
|
if (!jsdoc) {
|
|
2229
3029
|
stat.unchecked++;
|
|
@@ -2233,6 +3033,12 @@
|
|
|
2233
3033
|
var spaces = this.spaces;
|
|
2234
3034
|
var out = '';
|
|
2235
3035
|
var first = true;
|
|
3036
|
+
var loc = this.getName(node);
|
|
3037
|
+
if (this.ignoreLocations.includes(loc)) {
|
|
3038
|
+
return '// IGNORE RTI TYPE VALIDATIONS, KNOWN ISSUES\n';
|
|
3039
|
+
}
|
|
3040
|
+
//out += `${spaces}/*${spaces} node.type=${node.type}\n${spaces}
|
|
3041
|
+
// ${JSON.stringify(jsdoc)}\n${parent}\n${spaces}*/\n`;
|
|
2236
3042
|
var _loop = function _loop(name) {
|
|
2237
3043
|
var type = jsdoc[name];
|
|
2238
3044
|
var hasParam = _this2.nodeHasParamName(node, name);
|
|
@@ -2249,11 +3055,24 @@
|
|
|
2249
3055
|
var isObjectPattern = param.type === 'ObjectPattern';
|
|
2250
3056
|
var isArrayPattern = param.type === 'ArrayPattern';
|
|
2251
3057
|
var isSupportedPattern = isObjectPattern || isArrayPattern;
|
|
3058
|
+
// There are four kinds of patterns:
|
|
3059
|
+
// ObjectPattern:
|
|
3060
|
+
// function test({x = 123}) {return x;} test({x: 456});
|
|
3061
|
+
// ArrayPattern:
|
|
3062
|
+
// function test([x = 123]) {return x;}; test([456]);
|
|
3063
|
+
// AssignmentPattern made up of ObjectPattern:
|
|
3064
|
+
// function test({x = 123} = {}) {return x;} test();
|
|
3065
|
+
// AssignmentPattern made up of ArrayPattern:
|
|
3066
|
+
// function test([x = 123] = []) {return x;} test();
|
|
2252
3067
|
if (isSupportedPattern) {
|
|
3068
|
+
// The name doesn't matter any longer, because any pattern inherently
|
|
3069
|
+
// drops the identifier from the AST. But we can access it
|
|
3070
|
+
// via arguments[paramIndex] anyway.
|
|
2253
3071
|
name = "arguments[".concat(paramIndex, "]");
|
|
2254
3072
|
} else if (param.type === 'AssignmentPattern') {
|
|
2255
3073
|
var _loc = _this2.getName(node);
|
|
2256
3074
|
if (param.left.type === 'ArrayPattern' && type.type === 'array') {
|
|
3075
|
+
// Add a type assertion for each element of the ArrayPattern
|
|
2257
3076
|
var _iterator = _createForOfIteratorHelper(param.left.elements),
|
|
2258
3077
|
_step;
|
|
2259
3078
|
try {
|
|
@@ -2272,8 +3091,9 @@
|
|
|
2272
3091
|
} finally {
|
|
2273
3092
|
_iterator.f();
|
|
2274
3093
|
}
|
|
2275
|
-
return 0;
|
|
3094
|
+
return 0; // continue
|
|
2276
3095
|
} else if (param.left.type === 'ObjectPattern' && type.type === 'object') {
|
|
3096
|
+
// Add a type assertion for each property of the ObjectPattern
|
|
2277
3097
|
var _iterator2 = _createForOfIteratorHelper(param.left.properties),
|
|
2278
3098
|
_step2;
|
|
2279
3099
|
try {
|
|
@@ -2302,15 +3122,15 @@
|
|
|
2302
3122
|
} finally {
|
|
2303
3123
|
_iterator2.f();
|
|
2304
3124
|
}
|
|
2305
|
-
return 0;
|
|
3125
|
+
return 0; // continue
|
|
2306
3126
|
}
|
|
2307
3127
|
_this2.warn("generateTypeChecks> ".concat(_loc, "> todo implement"), "AssignmentPattern for parameter ".concat(name));
|
|
2308
|
-
return 0;
|
|
3128
|
+
return 0; // continue
|
|
2309
3129
|
}
|
|
2310
3130
|
} else {
|
|
2311
3131
|
var _loc2 = _this2.getName(node);
|
|
2312
3132
|
_this2.warn("generateTypeChecks> ".concat(_loc2, "> Missing param: ").concat(name));
|
|
2313
|
-
return 0;
|
|
3133
|
+
return 0; // continue
|
|
2314
3134
|
}
|
|
2315
3135
|
}
|
|
2316
3136
|
var t = JSON.stringify(type, null, 2).replaceAll('\n', '\n' + spaces);
|
|
@@ -2323,6 +3143,8 @@
|
|
|
2323
3143
|
}
|
|
2324
3144
|
var loc = _this2.getName(node);
|
|
2325
3145
|
var prevCheck = '';
|
|
3146
|
+
// JSDoc doesn't support multiple function signatures yet, but this is
|
|
3147
|
+
// exactly what we would need to deal with ObjectPool'ing
|
|
2326
3148
|
if (loc === 'ContactPoint#constructor' || loc === 'ContactResult#constructor' || loc === 'SingleContactResult#constructor') {
|
|
2327
3149
|
prevCheck = 'arguments.length !== 0 && ';
|
|
2328
3150
|
}
|
|
@@ -2340,15 +3162,25 @@
|
|
|
2340
3162
|
}
|
|
2341
3163
|
return out;
|
|
2342
3164
|
}
|
|
3165
|
+
/**
|
|
3166
|
+
* @param {Node} node - The Babel AST node.
|
|
3167
|
+
* @returns {string} Best possible human-readable name of given node.
|
|
3168
|
+
*/
|
|
2343
3169
|
}, {
|
|
2344
3170
|
key: "getNameForFunctionExpression",
|
|
2345
3171
|
value: function getNameForFunctionExpression(node) {
|
|
2346
3172
|
var objectProperty = this.findParentOfType(node, 'ObjectProperty');
|
|
2347
3173
|
if (objectProperty) {
|
|
3174
|
+
// See good-old-es5.mjs example for a test case
|
|
3175
|
+
// TODO: Make an even better name based on Object.assign(ScopeSpace.prototype
|
|
3176
|
+
// Ideally we would figure out the name: ScopeSpace#resolve
|
|
3177
|
+
// Currently we only find "resolve" (still better than 'unnamed function expression'...)
|
|
2348
3178
|
return this.toSource(objectProperty.key);
|
|
2349
3179
|
}
|
|
2350
3180
|
var expressionStatement = this.findParentOfType(node, 'ExpressionStatement');
|
|
2351
3181
|
if (expressionStatement) {
|
|
3182
|
+
// There are many kinds of expressions
|
|
3183
|
+
// type Expression = ArrayExpression | AssignmentExpression | BinaryExpression | CallExpression | ...
|
|
2352
3184
|
var left = expressionStatement.expression.left;
|
|
2353
3185
|
if (left) {
|
|
2354
3186
|
return this.toSource(left);
|
|
@@ -2357,6 +3189,10 @@
|
|
|
2357
3189
|
}
|
|
2358
3190
|
return 'unnamed function expression';
|
|
2359
3191
|
}
|
|
3192
|
+
/**
|
|
3193
|
+
* @param {Node} node - The Babel AST node.
|
|
3194
|
+
* @returns {string} Stringification of the node.
|
|
3195
|
+
*/
|
|
2360
3196
|
}, {
|
|
2361
3197
|
key: "getName",
|
|
2362
3198
|
value: function getName(node) {
|
|
@@ -2400,6 +3236,11 @@
|
|
|
2400
3236
|
return '/*MISSING*/';
|
|
2401
3237
|
}
|
|
2402
3238
|
}
|
|
3239
|
+
/**
|
|
3240
|
+
* @override
|
|
3241
|
+
* @param {import("@babel/types").BinaryExpression} node - The Babel AST node.
|
|
3242
|
+
* @returns {string} Stringification of the node.
|
|
3243
|
+
*/
|
|
2403
3244
|
}, {
|
|
2404
3245
|
key: "BinaryExpression",
|
|
2405
3246
|
value: function BinaryExpression(node) {
|
|
@@ -2418,7 +3259,14 @@
|
|
|
2418
3259
|
}
|
|
2419
3260
|
}, {
|
|
2420
3261
|
key: "File",
|
|
2421
|
-
value:
|
|
3262
|
+
value:
|
|
3263
|
+
/**
|
|
3264
|
+
* @override
|
|
3265
|
+
* @param {import("@babel/types").File} node - The Babel AST node.
|
|
3266
|
+
* @returns {string} Stringification of the node.
|
|
3267
|
+
*/
|
|
3268
|
+
function File(node) {
|
|
3269
|
+
// @todo figure out why errors is in Babel node and not in @babel/types...
|
|
2422
3270
|
var program = node.program,
|
|
2423
3271
|
comments = node.comments;
|
|
2424
3272
|
if (comments) {
|
|
@@ -2436,6 +3284,7 @@
|
|
|
2436
3284
|
_iterator3.f();
|
|
2437
3285
|
}
|
|
2438
3286
|
}
|
|
3287
|
+
//console.log("this.typedefs", this.typedefs);
|
|
2439
3288
|
var out = '';
|
|
2440
3289
|
for (var name in this.typedefs) {
|
|
2441
3290
|
var typedef = this.typedefs[name];
|
|
@@ -2450,7 +3299,24 @@
|
|
|
2450
3299
|
return Asserter;
|
|
2451
3300
|
}(Stringifier);
|
|
2452
3301
|
|
|
3302
|
+
/**
|
|
3303
|
+
* Simple facade which does all the processing. Processes the input
|
|
3304
|
+
* source string, adding runtime type checks based on JSDoc comments.
|
|
3305
|
+
*
|
|
3306
|
+
* This function takes JavaScript source code as input, parses it to an AST, traverses the
|
|
3307
|
+
* AST to find type annotations in JSDoc comments, and generates appropriate runtime type
|
|
3308
|
+
* assertions. These are then inserted into the source, producing a new version of the code
|
|
3309
|
+
* that includes runtime type checking based on the original JSDoc annotations.
|
|
3310
|
+
*
|
|
3311
|
+
* @param {string} src - The input source code containing JSDoc comments to be processed
|
|
3312
|
+
* for type checks.
|
|
3313
|
+
* @param {import('./Asserter.mjs').Options} [options] - Configuration options that dictate
|
|
3314
|
+
* how the processing is performed.
|
|
3315
|
+
* @returns {string} The transformed source code with inserted runtime type checks, or the
|
|
3316
|
+
* original source code commented with an error if processing fails.
|
|
3317
|
+
*/
|
|
2453
3318
|
function addTypeChecks(src, options) {
|
|
3319
|
+
console.log("GOT OPTIONS", options);
|
|
2454
3320
|
try {
|
|
2455
3321
|
var asserter = new Asserter(options);
|
|
2456
3322
|
var ast = parser.parse(src, {
|
|
@@ -2465,28 +3331,45 @@
|
|
|
2465
3331
|
}
|
|
2466
3332
|
}
|
|
2467
3333
|
|
|
3334
|
+
/**
|
|
3335
|
+
* @param {object} ast - The Babel AST.
|
|
3336
|
+
* @returns {string} String representation in JSON format for debugging/inspecting the AST.
|
|
3337
|
+
*/
|
|
2468
3338
|
function ast2json(ast) {
|
|
2469
3339
|
return JSON.stringify(ast, function (name, val) {
|
|
2470
3340
|
if (name === "loc" || name === "start" || name === "end") {
|
|
2471
|
-
return;
|
|
3341
|
+
return; // remove
|
|
2472
3342
|
}
|
|
2473
|
-
|
|
3343
|
+
|
|
3344
|
+
return val; // keep
|
|
2474
3345
|
}, 2);
|
|
2475
3346
|
}
|
|
2476
3347
|
|
|
2477
3348
|
var drop = ['loc', 'start', 'end', 'leadingComments', 'trailingComments', 'innerComments', 'innerComments', 'comments'];
|
|
3349
|
+
/**
|
|
3350
|
+
* @example
|
|
3351
|
+
* setRight(ast2jsonForComparison(parseSync("/** *"))); // Close comment with / after last *
|
|
3352
|
+
* @param {object} ast - The Babel AST.
|
|
3353
|
+
* @returns {string} String representation in JSON format for debugging/inspecting the AST.
|
|
3354
|
+
*/
|
|
2478
3355
|
function ast2jsonForComparison(ast) {
|
|
2479
3356
|
return JSON.stringify(ast, function (name, val) {
|
|
2480
3357
|
if (name === 'trailingComma' || name === 'parenStart') {
|
|
2481
3358
|
return 'offset removed for better comparison';
|
|
2482
3359
|
}
|
|
2483
3360
|
if (drop.includes(name)) {
|
|
2484
|
-
return undefined;
|
|
3361
|
+
return undefined; // remove
|
|
2485
3362
|
}
|
|
2486
|
-
|
|
3363
|
+
|
|
3364
|
+
return val; // keep
|
|
2487
3365
|
}, 2);
|
|
2488
3366
|
}
|
|
2489
3367
|
|
|
3368
|
+
/**
|
|
3369
|
+
* A roundtrip between code -> AST -> code to validate Stringifier.
|
|
3370
|
+
* @param {string} code - The code.
|
|
3371
|
+
* @returns {string | undefined} The new and once parsed and stringified code.
|
|
3372
|
+
*/
|
|
2490
3373
|
function code2ast2code(code) {
|
|
2491
3374
|
var stringifier = new Stringifier();
|
|
2492
3375
|
var ast = parser.parse(code, {
|
|
@@ -2499,6 +3382,11 @@
|
|
|
2499
3382
|
return out;
|
|
2500
3383
|
}
|
|
2501
3384
|
|
|
3385
|
+
/**
|
|
3386
|
+
* @param {string} left - Left source code.
|
|
3387
|
+
* @param {string} right - Right source code.
|
|
3388
|
+
* @returns {boolean} Whether source codes are identical on the AST level.
|
|
3389
|
+
*/
|
|
2502
3390
|
function compareAST(left, right) {
|
|
2503
3391
|
var l = parser.parse(left, {
|
|
2504
3392
|
sourceType: 'module'
|
|
@@ -2512,19 +3400,70 @@
|
|
|
2512
3400
|
return test;
|
|
2513
3401
|
}
|
|
2514
3402
|
|
|
3403
|
+
/**
|
|
3404
|
+
* Transforms a type string into a structured type representation.
|
|
3405
|
+
*
|
|
3406
|
+
* This function parses a given type string and converts it into a TypeScript
|
|
3407
|
+
* Abstract Syntax Tree (AST), then uses that AST to return a structured type
|
|
3408
|
+
* representation that can be further utilized or interpreted.
|
|
3409
|
+
*
|
|
3410
|
+
* @todo Better handling of weird case: Array<>
|
|
3411
|
+
* @example
|
|
3412
|
+
* const {expandType} = await import("./src-transpiler/expandType.mjs");
|
|
3413
|
+
* expandType('[string, Array|AnyTypedArray, number[]]|[ONNXTensor]');
|
|
3414
|
+
* expandType('(123) '); // Outputs: '123'
|
|
3415
|
+
* expandType(' ( ( 123 ) ) '); // Outputs: '123'
|
|
3416
|
+
* expandType('Array<number> '); // Outputs: {type: 'array', elementType: 'number'}
|
|
3417
|
+
* expandType('Array<(123) > '); // Outputs: {type: 'array', elementType: '123'}
|
|
3418
|
+
* expandType('Array<"abc" | 123> '); // Outputs: {type: 'array', elementType: {type: 'union', members: ['"abc"', '123']}}
|
|
3419
|
+
* expandType(' (string ) |(number ) '); // Outputs: {type: 'union', members: [ 'string', 'number']}
|
|
3420
|
+
* expandType(' "apples" | ( "bananas") '); // Outputs: {type: 'union', members: [ '"apples"', '"bananas"']}
|
|
3421
|
+
* expandType('123? '); // Outputs: {"type":"union","members":["123","null"]}
|
|
3422
|
+
* expandType('123|null '); // Outputs: {"type":"union","members":["123","null"]}
|
|
3423
|
+
* expandType('Map<string, any> '); // Outputs:
|
|
3424
|
+
* expandType('typeof Number '); // Outputs:
|
|
3425
|
+
* @param {string} type - The type string to be expanded into a structured representation.
|
|
3426
|
+
* @todo Share type with expandTypeBabelTS and expandTypeDepFree
|
|
3427
|
+
* @returns {string | {type: string, [key: string]: any} | undefined} The structured type
|
|
3428
|
+
* representation obtained from parsing and converting the provided type string.
|
|
3429
|
+
*/
|
|
2515
3430
|
function expandType(type) {
|
|
2516
3431
|
var ast = parseType(type);
|
|
2517
3432
|
return toSourceTS(ast);
|
|
2518
3433
|
}
|
|
3434
|
+
/**
|
|
3435
|
+
* @todo I want to use for example: import('typescript').Node
|
|
3436
|
+
* But the TS types make no sense to me so far ... need to investigate more.
|
|
3437
|
+
* @typedef TypeScriptType
|
|
3438
|
+
* @property {object[]|undefined} typeArguments - The type arguments.
|
|
3439
|
+
* @property {import('typescript').Node} typeName - The type name.
|
|
3440
|
+
* @property {number} kind - The kind for `ts.SyntaxKind[kind]`.
|
|
3441
|
+
*/
|
|
3442
|
+
/**
|
|
3443
|
+
* @param {string} str - The type string.
|
|
3444
|
+
* @returns {TypeScriptType} - The node containing all the information about the input type string.
|
|
3445
|
+
*/
|
|
2519
3446
|
function parseType(str) {
|
|
3447
|
+
// TS doesn't like ... notation in this context
|
|
2520
3448
|
if (str.startsWith('...')) {
|
|
2521
|
-
str = str.slice(3);
|
|
2522
|
-
str += '[]';
|
|
3449
|
+
str = str.slice(3); // remove dots
|
|
3450
|
+
str += '[]'; // turn into array
|
|
2523
3451
|
}
|
|
3452
|
+
// type tmp = (...string) => 123; to have a function context
|
|
2524
3453
|
str = "type tmp = ".concat(str, ";");
|
|
2525
|
-
var ast = ts.createSourceFile('repl.ts', str, ts.ScriptTarget.Latest, true);
|
|
3454
|
+
var ast = ts.createSourceFile('repl.ts', str, ts.ScriptTarget.Latest, true /*setParentNodes*/);
|
|
2526
3455
|
return ast.statements[0].type;
|
|
2527
3456
|
}
|
|
3457
|
+
/**
|
|
3458
|
+
* Converts a TypeScript AST node to a source string representation or to an intermediate object describing the type.
|
|
3459
|
+
*
|
|
3460
|
+
* This function handles various TypeScript AST node types and converts them into a string
|
|
3461
|
+
* or an object representing the type.
|
|
3462
|
+
*
|
|
3463
|
+
* @param {TypeScriptType} node - The TypeScript AST node to convert.
|
|
3464
|
+
* @returns {string | {type: string, [key: string]: any} | undefined} The source string or an object with type information based on the node,
|
|
3465
|
+
* or `undefined` if the node kind is not handled.
|
|
3466
|
+
*/
|
|
2528
3467
|
function toSourceTS(node) {
|
|
2529
3468
|
var typeArguments = node.typeArguments,
|
|
2530
3469
|
typeName = node.typeName;
|
|
@@ -2570,18 +3509,22 @@
|
|
|
2570
3509
|
KeyOfKeyword = _ts$SyntaxKind.KeyOfKeyword,
|
|
2571
3510
|
ConstructorType = _ts$SyntaxKind.ConstructorType,
|
|
2572
3511
|
NamedTupleMember = _ts$SyntaxKind.NamedTupleMember;
|
|
3512
|
+
// console.log({typeArguments, typeName, kind_, node});
|
|
2573
3513
|
switch (node.kind) {
|
|
2574
3514
|
case BigIntKeyword:
|
|
2575
3515
|
return {
|
|
2576
3516
|
type: 'bigint'
|
|
2577
3517
|
};
|
|
2578
3518
|
case BigIntLiteral:
|
|
2579
|
-
var literal = node.text.slice(0, -1);
|
|
3519
|
+
var literal = node.text.slice(0, -1); // Remove the "n"
|
|
2580
3520
|
return {
|
|
2581
3521
|
type: 'bigint',
|
|
2582
3522
|
literal: literal
|
|
2583
3523
|
};
|
|
2584
3524
|
case ConditionalType:
|
|
3525
|
+
// Keys on node:
|
|
3526
|
+
// ['pos', 'end', 'flags', 'modifierFlagsCache', 'transformFlags', 'parent', 'kind', 'checkType',
|
|
3527
|
+
// 'extendsType', 'trueType', 'falseType', 'locals', 'nextContainer']
|
|
2585
3528
|
var checkType = toSourceTS(node.checkType);
|
|
2586
3529
|
var extendsType = toSourceTS(node.extendsType);
|
|
2587
3530
|
var trueType = toSourceTS(node.trueType);
|
|
@@ -2629,6 +3572,8 @@
|
|
|
2629
3572
|
type: 'union',
|
|
2630
3573
|
members: [t, 'null']
|
|
2631
3574
|
};
|
|
3575
|
+
// todo work out more: const jsdoc = `(...a: ...number) => 123
|
|
3576
|
+
// TS even thinks it's two parameters... just go for array/[]
|
|
2632
3577
|
case Parameter:
|
|
2633
3578
|
var type = node.type ? toSourceTS(node.type) : 'any';
|
|
2634
3579
|
var name = toSourceTS(node.name);
|
|
@@ -2761,6 +3706,7 @@
|
|
|
2761
3706
|
return toSourceTS(node.literal);
|
|
2762
3707
|
case AnyKeyword:
|
|
2763
3708
|
case BooleanKeyword:
|
|
3709
|
+
// ts.SyntaxKind[parseType("*").kind] === 'JSDocAllType'
|
|
2764
3710
|
case JSDocAllType:
|
|
2765
3711
|
case NullKeyword:
|
|
2766
3712
|
case NumericLiteral:
|
|
@@ -2779,10 +3725,17 @@
|
|
|
2779
3725
|
properties: {}
|
|
2780
3726
|
};
|
|
2781
3727
|
case ParenthesizedType:
|
|
3728
|
+
// fall-through for parentheses
|
|
2782
3729
|
return toSourceTS(node.type);
|
|
2783
3730
|
case LastTypeNode:
|
|
2784
3731
|
return toSourceTS(node.qualifier);
|
|
2785
3732
|
default:
|
|
3733
|
+
// const test = {};
|
|
3734
|
+
// Object.entries(ts.SyntaxKind).forEach(([name, id]) => {
|
|
3735
|
+
// test[id] = (test[id] || []);
|
|
3736
|
+
// test[id].push(name);
|
|
3737
|
+
// });
|
|
3738
|
+
// console.log(test);
|
|
2786
3739
|
console.warn('toSourceTS> unhandled kind - make sure to understand you cannot reverse TS enums');
|
|
2787
3740
|
console.warn('if they contain range aliases, for example:');
|
|
2788
3741
|
console.warn('ts.SyntaxKind.NumericLiteral === ts.SyntaxKind.FirstLiteralToken');
|
|
@@ -2791,17 +3744,58 @@
|
|
|
2791
3744
|
}
|
|
2792
3745
|
}
|
|
2793
3746
|
|
|
3747
|
+
/**
|
|
3748
|
+
* @todo Better handling of weird case: Array<>
|
|
3749
|
+
* @example
|
|
3750
|
+
* const {expandTypeBabelTS} = await import("./src-transpiler/expandTypeBabelTS.mjs");
|
|
3751
|
+
* expandTypeBabelTS('[string, Array|AnyTypedArray, number[]]|[ONNXTensor]');
|
|
3752
|
+
* expandTypeBabelTS('(123) '); // Outputs: '123'
|
|
3753
|
+
* expandTypeBabelTS(' ( ( 123 ) ) '); // Outputs: '123'
|
|
3754
|
+
* expandTypeBabelTS('Array<number> '); // Outputs: {type: 'array', elementType: 'number'}
|
|
3755
|
+
* expandTypeBabelTS('Array<(123) > '); // Outputs: {type: 'array', elementType: '123'}
|
|
3756
|
+
* expandTypeBabelTS('Array<"abc" | 123> '); // Outputs: {type: 'array', elementType: {type: 'union', members: ['"abc"', '123']}}
|
|
3757
|
+
* expandTypeBabelTS(' (string ) |(number ) '); // Outputs: {type: 'union', members: [ 'string', 'number']}
|
|
3758
|
+
* expandTypeBabelTS(' "apples" | ( "bananas") '); // Outputs: {type: 'union', members: [ '"apples"', '"bananas"']}
|
|
3759
|
+
* expandTypeBabelTS('123? '); // Outputs: {type: 'union', members: ['123', 'null']}
|
|
3760
|
+
* expandTypeBabelTS('123|null '); // Outputs: {type: 'union', members: ['123', 'null']}
|
|
3761
|
+
* expandTypeBabelTS('Map<string, any> '); // Outputs: {type: 'map', key: 'string', val: 'any'}
|
|
3762
|
+
* expandTypeBabelTS("(a: number, b: number) => number")
|
|
3763
|
+
* @param {string} type - The input type.
|
|
3764
|
+
* @returns {string|object|undefined} - See `toSourceBabelTS`.
|
|
3765
|
+
*/
|
|
2794
3766
|
function expandTypeBabelTS(type) {
|
|
2795
3767
|
var ast = parseTypeBabelTS(type);
|
|
2796
3768
|
return toSourceBabelTS(ast);
|
|
2797
3769
|
}
|
|
3770
|
+
/**
|
|
3771
|
+
* @param {string} str - The type string.
|
|
3772
|
+
* @returns {import('@babel/types').Node} - The node containing all the information about the input type string.
|
|
3773
|
+
*/
|
|
2798
3774
|
function parseTypeBabelTS(str) {
|
|
3775
|
+
// TS doesn't like ... notation in this context
|
|
3776
|
+
//if (str.startsWith('...')) {
|
|
3777
|
+
// str = str.slice(3); // remove dots
|
|
3778
|
+
// str += '[]'; // turn into array
|
|
3779
|
+
//}
|
|
3780
|
+
// type tmp = (...string) => 123; to have a function context
|
|
2799
3781
|
str = "type tmp = ".concat(str, ";");
|
|
2800
3782
|
var ast = parser.parse(str, {
|
|
2801
3783
|
plugins: ['typescript']
|
|
2802
3784
|
});
|
|
2803
3785
|
return ast.program.body[0].typeAnnotation;
|
|
2804
3786
|
}
|
|
3787
|
+
/**
|
|
3788
|
+
* Converts a Babel AST node to its source string representation or structured type object.
|
|
3789
|
+
*
|
|
3790
|
+
* This function handles a variety of node types provided by Babel and converts them into a string
|
|
3791
|
+
* or an intermediate object representing the type, depending on the complexity of the type described by the node.
|
|
3792
|
+
*
|
|
3793
|
+
* @param {import('@babel/types').Node} node - The Babel AST node to convert.
|
|
3794
|
+
* @returns {string|object|undefined} - A string, object representing a structured type, or `undefined` for unhandled types.
|
|
3795
|
+
* Depending on the node, it may return a simple type string (e.g., `"string"` for `TSStringKeyword`),
|
|
3796
|
+
* a structured type object (e.g., a record type for `TSTypeReference` with type arguments),
|
|
3797
|
+
* or `undefined` if the encountered type is not handled. Unhandled types trigger a warning and enter a debugger statement.
|
|
3798
|
+
*/
|
|
2805
3799
|
function toSourceBabelTS(node) {
|
|
2806
3800
|
switch (node.type) {
|
|
2807
3801
|
case 'TSBigIntKeyword':
|
|
@@ -2814,10 +3808,34 @@
|
|
|
2814
3808
|
type: 'bigint',
|
|
2815
3809
|
literal: literal
|
|
2816
3810
|
};
|
|
3811
|
+
// expandTypeBabelTS("(a: number, b: number) => number")
|
|
3812
|
+
/**
|
|
3813
|
+
* @todo the parameters are given as identifiers with "typeAnnotation"
|
|
3814
|
+
*/
|
|
3815
|
+
// case 'TSFunctionType':
|
|
3816
|
+
// const parameters = node.parameters.map(toSourceBabelTS);
|
|
3817
|
+
// // I wish Babel AST would be like tsc AST here:
|
|
3818
|
+
// // parseType("(a: number, b: number) => number").parameters[0].kind === ts.SyntaxKind.Parameter
|
|
3819
|
+
// return {type: 'function', parameters};
|
|
3820
|
+
// Fix first: https://github.com/babel/babel/issues/16073
|
|
3821
|
+
//case 'JSDocNullableType':
|
|
3822
|
+
// const t = toSourceBabelTS(node.type);
|
|
3823
|
+
// return {type: 'union', members: [t, 'null']};
|
|
3824
|
+
// todo work out more: const jsdoc = `(...a: ...number) => 123
|
|
3825
|
+
// TS even thinks it's two parameters... just go for array/[]
|
|
3826
|
+
//case 'Parameter':
|
|
3827
|
+
// const type = node.type ? toSourceBabelTS(node.type) : 'any';
|
|
3828
|
+
// const name = toSourceBabelTS(node.name);
|
|
3829
|
+
// const ret = {type, name};
|
|
3830
|
+
// if (node.dotDotDotToken) {
|
|
3831
|
+
// return {type: 'array', elementType: ret};
|
|
3832
|
+
// }
|
|
3833
|
+
// return ret;
|
|
2817
3834
|
case 'TSTypeReference':
|
|
2818
3835
|
{
|
|
2819
3836
|
var name = toSourceBabelTS(node.typeName);
|
|
2820
3837
|
if (!node.typeParameters) {
|
|
3838
|
+
// console.log(`node.typeName.name=${node.typeName.name} name=${name}`, node);
|
|
2821
3839
|
return node.typeName.name;
|
|
2822
3840
|
}
|
|
2823
3841
|
console.assert(node.typeParameters.type === 'TSTypeParameterInstantiation');
|
|
@@ -2901,6 +3919,9 @@
|
|
|
2901
3919
|
type: 'object',
|
|
2902
3920
|
properties: properties
|
|
2903
3921
|
};
|
|
3922
|
+
// case 'PropertySignature':
|
|
3923
|
+
// console.warn('toSourceBabelTS> should not happen, handled by TypeLiteral directly');
|
|
3924
|
+
// return `${toSourceBabelTS(node.name)}: ${toSourceBabelTS(node.type)}`;
|
|
2904
3925
|
case 'Identifier':
|
|
2905
3926
|
return node.name;
|
|
2906
3927
|
case 'TSArrayType':
|
|
@@ -2910,25 +3931,36 @@
|
|
|
2910
3931
|
};
|
|
2911
3932
|
case 'TSLiteralType':
|
|
2912
3933
|
return toSourceBabelTS(node.literal);
|
|
3934
|
+
// expandTypeBabelTS("any")
|
|
2913
3935
|
case 'TSAnyKeyword':
|
|
2914
3936
|
return 'any';
|
|
3937
|
+
// expandTypeBabelTS("boolean")
|
|
2915
3938
|
case 'TSBooleanKeyword':
|
|
2916
3939
|
return 'boolean';
|
|
3940
|
+
// expandTypeBabelTS('true | false');
|
|
2917
3941
|
case 'BooleanLiteral':
|
|
2918
3942
|
return node.value.toString();
|
|
3943
|
+
// ts.SyntaxKind[parseType("*").kind] === 'JSDocAllType'
|
|
3944
|
+
// But Babel-TS doesn't parse it atm
|
|
3945
|
+
//case 'JSDocAllType':
|
|
3946
|
+
// expandTypeBabelTS('null')
|
|
2919
3947
|
case 'TSNullKeyword':
|
|
2920
3948
|
return 'null';
|
|
3949
|
+
// expandTypeBabelTS('123')
|
|
2921
3950
|
case 'NumericLiteral':
|
|
2922
3951
|
case 'StringLiteral':
|
|
2923
3952
|
return node.extra.raw;
|
|
3953
|
+
// expandTypeBabelTS('undefined')
|
|
2924
3954
|
case 'TSUndefinedKeyword':
|
|
2925
3955
|
return 'undefined';
|
|
2926
3956
|
case 'TSUnknownKeyword':
|
|
2927
3957
|
return 'unknown';
|
|
2928
3958
|
case 'TSNeverKeyword':
|
|
2929
3959
|
return 'never';
|
|
3960
|
+
// parseTypeBabelTS('void');
|
|
2930
3961
|
case 'TSVoidKeyword':
|
|
2931
3962
|
return 'void';
|
|
3963
|
+
// expandTypeBabelTS('this')
|
|
2932
3964
|
case 'TSThisType':
|
|
2933
3965
|
return 'this';
|
|
2934
3966
|
case 'ObjectKeyword':
|
|
@@ -2937,6 +3969,7 @@
|
|
|
2937
3969
|
properties: {}
|
|
2938
3970
|
};
|
|
2939
3971
|
case 'ParenthesizedType':
|
|
3972
|
+
// fall-through for parentheses
|
|
2940
3973
|
return toSourceBabelTS(node.type);
|
|
2941
3974
|
case 'LastTypeNode':
|
|
2942
3975
|
return toSourceBabelTS(node.qualifier);
|