@@ -371,6 +371,10 @@ namespace ts {
371
371
return formatEnum ( flags , ( < any > ts ) . ObjectFlags , /*isFlags*/ true ) ;
372
372
}
373
373
374
+ export function formatFlowFlags ( flags : FlowFlags | undefined ) : string {
375
+ return formatEnum ( flags , ( < any > ts ) . FlowFlags , /*isFlags*/ true ) ;
376
+ }
377
+
374
378
let isDebugInfoEnabled = false ;
375
379
376
380
interface ExtendedDebugModule {
@@ -396,13 +400,87 @@ namespace ts {
396
400
return extendedDebug ( ) . formatControlFlowGraph ( flowNode ) ;
397
401
}
398
402
399
- export function attachFlowNodeDebugInfo ( flowNode : FlowNode ) {
403
+ let flowNodeProto : FlowNodeBase | undefined ;
404
+
405
+ function attachFlowNodeDebugInfoWorker ( flowNode : FlowNodeBase ) {
406
+ if ( ! ( "__debugFlowFlags" in flowNode ) ) { // eslint-disable-line no-in-operator
407
+ Object . defineProperties ( flowNode , {
408
+ // for use with vscode-js-debug's new customDescriptionGenerator in launch.json
409
+ __tsDebuggerDisplay : {
410
+ value ( this : FlowNodeBase ) {
411
+ const flowHeader =
412
+ this . flags & FlowFlags . Start ? "FlowStart" :
413
+ this . flags & FlowFlags . BranchLabel ? "FlowBranchLabel" :
414
+ this . flags & FlowFlags . LoopLabel ? "FlowLoopLabel" :
415
+ this . flags & FlowFlags . Assignment ? "FlowAssignment" :
416
+ this . flags & FlowFlags . TrueCondition ? "FlowTrueCondition" :
417
+ this . flags & FlowFlags . FalseCondition ? "FlowFalseCondition" :
418
+ this . flags & FlowFlags . SwitchClause ? "FlowSwitchClause" :
419
+ this . flags & FlowFlags . ArrayMutation ? "FlowArrayMutation" :
420
+ this . flags & FlowFlags . Call ? "FlowCall" :
421
+ this . flags & FlowFlags . ReduceLabel ? "FlowReduceLabel" :
422
+ this . flags & FlowFlags . Unreachable ? "FlowUnreachable" :
423
+ "UnknownFlow" ;
424
+ const remainingFlags = this . flags & ~ ( FlowFlags . Referenced - 1 ) ;
425
+ return `${ flowHeader } ${ remainingFlags ? ` (${ formatFlowFlags ( remainingFlags ) } )` : "" } ` ;
426
+ }
427
+ } ,
428
+ __debugFlowFlags : { get ( this : FlowNodeBase ) { return formatEnum ( this . flags , ( ts as any ) . FlowFlags , /*isFlags*/ true ) ; } } ,
429
+ __debugToString : { value ( this : FlowNodeBase ) { return formatControlFlowGraph ( this ) ; } }
430
+ } ) ;
431
+ }
432
+ }
433
+
434
+ export function attachFlowNodeDebugInfo ( flowNode : FlowNodeBase ) {
400
435
if ( isDebugInfoEnabled ) {
401
- if ( ! ( "__debugFlowFlags" in flowNode ) ) { // eslint-disable-line no-in-operator
402
- Object . defineProperties ( flowNode , {
403
- __debugFlowFlags : { get ( this : FlowNode ) { return formatEnum ( this . flags , ( ts as any ) . FlowFlags , /*isFlags*/ true ) ; } } ,
404
- __debugToString : { value ( this : FlowNode ) { return formatControlFlowGraph ( this ) ; } }
405
- } ) ;
436
+ if ( typeof Object . setPrototypeOf === "function" ) {
437
+ // if we're in es2015, attach the method to a shared prototype for `FlowNode`
438
+ // so the method doesn't show up in the watch window.
439
+ if ( ! flowNodeProto ) {
440
+ flowNodeProto = Object . create ( Object . prototype ) as FlowNodeBase ;
441
+ attachFlowNodeDebugInfoWorker ( flowNodeProto ) ;
442
+ }
443
+ Object . setPrototypeOf ( flowNode , flowNodeProto ) ;
444
+ }
445
+ else {
446
+ // not running in an es2015 environment, attach the method directly.
447
+ attachFlowNodeDebugInfoWorker ( flowNode ) ;
448
+ }
449
+ }
450
+ }
451
+
452
+ let nodeArrayProto : NodeArray < Node > | undefined ;
453
+
454
+ function attachNodeArrayDebugInfoWorker ( array : NodeArray < Node > ) {
455
+ if ( ! ( "__tsDebuggerDisplay" in array ) ) { // eslint-disable-line no-in-operator
456
+ Object . defineProperties ( array , {
457
+ __tsDebuggerDisplay : {
458
+ value ( this : NodeArray < Node > , defaultValue : string ) {
459
+ // An `Array` with extra properties is rendered as `[A, B, prop1: 1, prop2: 2]`. Most of
460
+ // these aren't immediately useful so we trim off the `prop1: ..., prop2: ...` part from the
461
+ // formatted string.
462
+ defaultValue = String ( defaultValue ) . replace ( / (?: , [ \s \w \d _ ] + : [ ^ , ] + ) + \] $ / , "]" ) ;
463
+ return `NodeArray ${ defaultValue } ` ;
464
+ }
465
+ }
466
+ } ) ;
467
+ }
468
+ }
469
+
470
+ export function attachNodeArrayDebugInfo ( array : NodeArray < Node > ) {
471
+ if ( isDebugInfoEnabled ) {
472
+ if ( typeof Object . setPrototypeOf === "function" ) {
473
+ // if we're in es2015, attach the method to a shared prototype for `NodeArray`
474
+ // so the method doesn't show up in the watch window.
475
+ if ( ! nodeArrayProto ) {
476
+ nodeArrayProto = Object . create ( Array . prototype ) as NodeArray < Node > ;
477
+ attachNodeArrayDebugInfoWorker ( nodeArrayProto ) ;
478
+ }
479
+ Object . setPrototypeOf ( array , nodeArrayProto ) ;
480
+ }
481
+ else {
482
+ // not running in an es2015 environment, attach the method directly.
483
+ attachNodeArrayDebugInfoWorker ( array ) ;
406
484
}
407
485
}
408
486
}
@@ -434,10 +512,51 @@ namespace ts {
434
512
435
513
// Add additional properties in debug mode to assist with debugging.
436
514
Object . defineProperties ( objectAllocator . getSymbolConstructor ( ) . prototype , {
515
+ // for use with vscode-js-debug's new customDescriptionGenerator in launch.json
516
+ __tsDebuggerDisplay : {
517
+ value ( this : Symbol ) {
518
+ const symbolHeader =
519
+ this . flags & SymbolFlags . Transient ? "TransientSymbol" :
520
+ "Symbol" ;
521
+ const remainingSymbolFlags = this . flags & ~ SymbolFlags . Transient ;
522
+ return `${ symbolHeader } '${ symbolName ( this ) } '${ remainingSymbolFlags ? ` (${ formatSymbolFlags ( remainingSymbolFlags ) } )` : "" } ` ;
523
+ }
524
+ } ,
437
525
__debugFlags : { get ( this : Symbol ) { return formatSymbolFlags ( this . flags ) ; } }
438
526
} ) ;
439
527
440
528
Object . defineProperties ( objectAllocator . getTypeConstructor ( ) . prototype , {
529
+ // for use with vscode-js-debug's new customDescriptionGenerator in launch.json
530
+ __tsDebuggerDisplay : {
531
+ value ( this : Type ) {
532
+ const typeHeader =
533
+ this . flags & TypeFlags . Nullable ? "NullableType" :
534
+ this . flags & TypeFlags . StringOrNumberLiteral ? `LiteralType ${ JSON . stringify ( ( this as LiteralType ) . value ) } ` :
535
+ this . flags & TypeFlags . BigIntLiteral ? `LiteralType ${ ( this as BigIntLiteralType ) . value . negative ? "-" : "" } ${ ( this as BigIntLiteralType ) . value . base10Value } n` :
536
+ this . flags & TypeFlags . UniqueESSymbol ? "UniqueESSymbolType" :
537
+ this . flags & TypeFlags . Enum ? "EnumType" :
538
+ this . flags & TypeFlags . Intrinsic ? `IntrinsicType ${ ( this as IntrinsicType ) . intrinsicName } ` :
539
+ this . flags & TypeFlags . Union ? "UnionType" :
540
+ this . flags & TypeFlags . Intersection ? "IntersectionType" :
541
+ this . flags & TypeFlags . Index ? "IndexType" :
542
+ this . flags & TypeFlags . IndexedAccess ? "IndexedAccessType" :
543
+ this . flags & TypeFlags . Conditional ? "ConditionalType" :
544
+ this . flags & TypeFlags . Substitution ? "SubstitutionType" :
545
+ this . flags & TypeFlags . TypeParameter ? "TypeParameter" :
546
+ this . flags & TypeFlags . Object ?
547
+ ( this as ObjectType ) . objectFlags & ObjectFlags . ClassOrInterface ? "InterfaceType" :
548
+ ( this as ObjectType ) . objectFlags & ObjectFlags . Reference ? "TypeReference" :
549
+ ( this as ObjectType ) . objectFlags & ObjectFlags . Tuple ? "TupleType" :
550
+ ( this as ObjectType ) . objectFlags & ObjectFlags . Anonymous ? "AnonymousType" :
551
+ ( this as ObjectType ) . objectFlags & ObjectFlags . Mapped ? "MappedType" :
552
+ ( this as ObjectType ) . objectFlags & ObjectFlags . ReverseMapped ? "ReverseMappedType" :
553
+ ( this as ObjectType ) . objectFlags & ObjectFlags . EvolvingArray ? "EvolvingArrayType" :
554
+ "ObjectType" :
555
+ "Type" ;
556
+ const remainingObjectFlags = this . flags & TypeFlags . Object ? ( this as ObjectType ) . objectFlags & ~ ObjectFlags . ObjectTypeKindMask : 0 ;
557
+ return `${ typeHeader } ${ this . symbol ? ` '${ symbolName ( this . symbol ) } '` : "" } ${ remainingObjectFlags ? ` (${ formatObjectFlags ( remainingObjectFlags ) } )` : "" } ` ;
558
+ }
559
+ } ,
441
560
__debugFlags : { get ( this : Type ) { return formatTypeFlags ( this . flags ) ; } } ,
442
561
__debugObjectFlags : { get ( this : Type ) { return this . flags & TypeFlags . Object ? formatObjectFlags ( ( < ObjectType > this ) . objectFlags ) : "" ; } } ,
443
562
__debugTypeToString : {
@@ -464,6 +583,50 @@ namespace ts {
464
583
for ( const ctor of nodeConstructors ) {
465
584
if ( ! ctor . prototype . hasOwnProperty ( "__debugKind" ) ) {
466
585
Object . defineProperties ( ctor . prototype , {
586
+ // for use with vscode-js-debug's new customDescriptionGenerator in launch.json
587
+ __tsDebuggerDisplay : {
588
+ value ( this : Node ) {
589
+ const nodeHeader =
590
+ isGeneratedIdentifier ( this ) ? "GeneratedIdentifier" :
591
+ isIdentifier ( this ) ? `Identifier '${ idText ( this ) } '` :
592
+ isPrivateIdentifier ( this ) ? `PrivateIdentifier '${ idText ( this ) } '` :
593
+ isStringLiteral ( this ) ? `StringLiteral ${ JSON . stringify ( this . text . length < 10 ? this . text : this . text . slice ( 10 ) + "..." ) } ` :
594
+ isNumericLiteral ( this ) ? `NumericLiteral ${ this . text } ` :
595
+ isBigIntLiteral ( this ) ? `BigIntLiteral ${ this . text } n` :
596
+ isTypeParameterDeclaration ( this ) ? "TypeParameterDeclaration" :
597
+ isParameter ( this ) ? "ParameterDeclaration" :
598
+ isConstructorDeclaration ( this ) ? "ConstructorDeclaration" :
599
+ isGetAccessorDeclaration ( this ) ? "GetAccessorDeclaration" :
600
+ isSetAccessorDeclaration ( this ) ? "SetAccessorDeclaration" :
601
+ isCallSignatureDeclaration ( this ) ? "CallSignatureDeclaration" :
602
+ isConstructSignatureDeclaration ( this ) ? "ConstructSignatureDeclaration" :
603
+ isIndexSignatureDeclaration ( this ) ? "IndexSignatureDeclaration" :
604
+ isTypePredicateNode ( this ) ? "TypePredicateNode" :
605
+ isTypeReferenceNode ( this ) ? "TypeReferenceNode" :
606
+ isFunctionTypeNode ( this ) ? "FunctionTypeNode" :
607
+ isConstructorTypeNode ( this ) ? "ConstructorTypeNode" :
608
+ isTypeQueryNode ( this ) ? "TypeQueryNode" :
609
+ isTypeLiteralNode ( this ) ? "TypeLiteralNode" :
610
+ isArrayTypeNode ( this ) ? "ArrayTypeNode" :
611
+ isTupleTypeNode ( this ) ? "TupleTypeNode" :
612
+ isOptionalTypeNode ( this ) ? "OptionalTypeNode" :
613
+ isRestTypeNode ( this ) ? "RestTypeNode" :
614
+ isUnionTypeNode ( this ) ? "UnionTypeNode" :
615
+ isIntersectionTypeNode ( this ) ? "IntersectionTypeNode" :
616
+ isConditionalTypeNode ( this ) ? "ConditionalTypeNode" :
617
+ isInferTypeNode ( this ) ? "InferTypeNode" :
618
+ isParenthesizedTypeNode ( this ) ? "ParenthesizedTypeNode" :
619
+ isThisTypeNode ( this ) ? "ThisTypeNode" :
620
+ isTypeOperatorNode ( this ) ? "TypeOperatorNode" :
621
+ isIndexedAccessTypeNode ( this ) ? "IndexedAccessTypeNode" :
622
+ isMappedTypeNode ( this ) ? "MappedTypeNode" :
623
+ isLiteralTypeNode ( this ) ? "LiteralTypeNode" :
624
+ isNamedTupleMember ( this ) ? "NamedTupleMember" :
625
+ isImportTypeNode ( this ) ? "ImportTypeNode" :
626
+ formatSyntaxKind ( this . kind ) ;
627
+ return `${ nodeHeader } ${ this . flags ? ` (${ formatNodeFlags ( this . flags ) } )` : "" } ` ;
628
+ }
629
+ } ,
467
630
__debugKind : { get ( this : Node ) { return formatSyntaxKind ( this . kind ) ; } } ,
468
631
__debugNodeFlags : { get ( this : Node ) { return formatNodeFlags ( this . flags ) ; } } ,
469
632
__debugModifierFlags : { get ( this : Node ) { return formatModifierFlags ( getEffectiveModifierFlagsNoCache ( this ) ) ; } } ,
0 commit comments