@@ -62,10 +62,17 @@ import {
62
62
Expression ,
63
63
ExpressionStatement ,
64
64
findAncestor ,
65
+ FlowArrayMutation ,
66
+ FlowAssignment ,
67
+ FlowCall ,
68
+ FlowCondition ,
65
69
FlowFlags ,
66
70
FlowLabel ,
67
71
FlowNode ,
72
+ FlowNodeBase ,
68
73
FlowReduceLabel ,
74
+ FlowStart ,
75
+ FlowSwitchClause ,
69
76
forEach ,
70
77
forEachChild ,
71
78
ForInOrOfStatement ,
@@ -464,11 +471,88 @@ const enum ContainerFlags {
464
471
IsObjectLiteralOrClassExpressionMethodOrAccessor = 1 << 7 ,
465
472
}
466
473
467
- function initFlowNode < T extends FlowNode > ( node : T ) {
468
- Debug . attachFlowNodeDebugInfo ( node ) ;
469
- return node ;
474
+ function createFlowNode < T extends FlowNode > (
475
+ flags : FlowFlags ,
476
+ node ?: Node ,
477
+ antecedent ?: FlowNode ,
478
+ antecedents ?: FlowNode [ ] ,
479
+ target ?: FlowLabel ,
480
+ switchStatement ?: SwitchStatement ,
481
+ clauseStart ?: number ,
482
+ clauseEnd ?: number ,
483
+ ) : T {
484
+ // Create all flow nodes in a predictable order. If FlowNode changes, add more
485
+ // properties here.
486
+ const flowNode : FlowNodeBase = {
487
+ flags,
488
+ id : undefined ,
489
+ node,
490
+ antecedent,
491
+ antecedents,
492
+ target,
493
+ switchStatement,
494
+ clauseStart,
495
+ clauseEnd,
496
+ } ;
497
+ Debug . attachFlowNodeDebugInfo ( flowNode ) ;
498
+ return flowNode as T ;
470
499
}
471
500
501
+ function createFlowStartNode ( flags : FlowFlags ) : FlowStart {
502
+ return createFlowNode ( flags ) ;
503
+ }
504
+
505
+ function createFlowLabelNode (
506
+ flags : FlowFlags ,
507
+ antecedents : FlowNode [ ] | undefined ,
508
+ ) : FlowLabel {
509
+ return createFlowNode ( flags , /*node*/ undefined , /*antecedent*/ undefined , antecedents ) ;
510
+ }
511
+
512
+ function createFlowMutationNode (
513
+ flags : FlowFlags ,
514
+ node : FlowAssignment [ "node" ] | FlowArrayMutation [ "node" ] ,
515
+ antecedent : FlowNode ,
516
+ ) : FlowAssignment | FlowArrayMutation {
517
+ return createFlowNode ( flags , node , antecedent ) ;
518
+ }
519
+
520
+ function createFlowConditionNode (
521
+ flags : FlowFlags ,
522
+ node : FlowCondition [ "node" ] ,
523
+ antecedent : FlowNode ,
524
+ ) : FlowCondition {
525
+ return createFlowNode ( flags , node , antecedent ) ;
526
+ }
527
+
528
+ function createFlowSwitchClauseNode (
529
+ flags : FlowFlags ,
530
+ switchStatement : SwitchStatement ,
531
+ clauseStart : number ,
532
+ clauseEnd : number ,
533
+ antecedent : FlowNode ,
534
+ ) : FlowSwitchClause {
535
+ return createFlowNode ( flags , /*node*/ undefined , antecedent , /*antecedents*/ undefined , /*target*/ undefined , switchStatement , clauseStart , clauseEnd ) ;
536
+ }
537
+
538
+ function createFlowCallNode (
539
+ flags : FlowFlags ,
540
+ node : FlowCall [ "node" ] ,
541
+ antecedent : FlowNode ,
542
+ ) : FlowCall {
543
+ return createFlowNode ( flags , node , antecedent ) ;
544
+ }
545
+
546
+ function createFlowReduceLabelNode (
547
+ flags : FlowFlags ,
548
+ antecedent : FlowNode ,
549
+ antecedents : FlowNode [ ] ,
550
+ target : FlowLabel ,
551
+ ) : FlowReduceLabel {
552
+ return createFlowNode ( flags , /*node*/ undefined , antecedent , antecedents , target ) ;
553
+ }
554
+
555
+
472
556
const binder = createBinder ( ) ;
473
557
474
558
/** @internal */
@@ -965,7 +1049,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
965
1049
// A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave
966
1050
// similarly to break statements that exit to a label just past the statement body.
967
1051
if ( ! isImmediatelyInvoked ) {
968
- currentFlow = initFlowNode ( { flags : FlowFlags . Start } ) ;
1052
+ currentFlow = createFlowStartNode ( FlowFlags . Start ) ;
969
1053
if ( containerFlags & ( ContainerFlags . IsFunctionExpression | ContainerFlags . IsObjectLiteralOrClassExpressionMethodOrAccessor ) ) {
970
1054
currentFlow . node = node as FunctionExpression | ArrowFunction | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration ;
971
1055
}
@@ -1261,15 +1345,15 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
1261
1345
}
1262
1346
1263
1347
function createBranchLabel ( ) : FlowLabel {
1264
- return initFlowNode ( { flags : FlowFlags . BranchLabel , antecedents : undefined } ) ;
1348
+ return createFlowLabelNode ( FlowFlags . BranchLabel , /* antecedents*/ undefined ) ;
1265
1349
}
1266
1350
1267
1351
function createLoopLabel ( ) : FlowLabel {
1268
- return initFlowNode ( { flags : FlowFlags . LoopLabel , antecedents : undefined } ) ;
1352
+ return createFlowLabelNode ( FlowFlags . LoopLabel , /* antecedents*/ undefined ) ;
1269
1353
}
1270
1354
1271
1355
function createReduceLabel ( target : FlowLabel , antecedents : FlowNode [ ] , antecedent : FlowNode ) : FlowReduceLabel {
1272
- return initFlowNode ( { flags : FlowFlags . ReduceLabel , target , antecedents, antecedent } ) ;
1356
+ return createFlowReduceLabelNode ( FlowFlags . ReduceLabel , antecedent , antecedents , target ) ;
1273
1357
}
1274
1358
1275
1359
function setFlowNodeReferenced ( flow : FlowNode ) {
@@ -1300,17 +1384,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
1300
1384
return antecedent ;
1301
1385
}
1302
1386
setFlowNodeReferenced ( antecedent ) ;
1303
- return initFlowNode ( { flags, antecedent , node : expression } ) ;
1387
+ return createFlowConditionNode ( flags , expression , antecedent ) ;
1304
1388
}
1305
1389
1306
1390
function createFlowSwitchClause ( antecedent : FlowNode , switchStatement : SwitchStatement , clauseStart : number , clauseEnd : number ) : FlowNode {
1307
1391
setFlowNodeReferenced ( antecedent ) ;
1308
- return initFlowNode ( { flags : FlowFlags . SwitchClause , antecedent , switchStatement, clauseStart, clauseEnd } ) ;
1392
+ return createFlowSwitchClauseNode ( FlowFlags . SwitchClause , switchStatement , clauseStart , clauseEnd , antecedent ) ;
1309
1393
}
1310
1394
1311
1395
function createFlowMutation ( flags : FlowFlags , antecedent : FlowNode , node : Expression | VariableDeclaration | ArrayBindingElement ) : FlowNode {
1312
1396
setFlowNodeReferenced ( antecedent ) ;
1313
- const result = initFlowNode ( { flags, antecedent , node } ) ;
1397
+ const result = createFlowMutationNode ( flags , node , antecedent ) ;
1314
1398
if ( currentExceptionTarget ) {
1315
1399
addAntecedent ( currentExceptionTarget , result ) ;
1316
1400
}
@@ -1319,7 +1403,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
1319
1403
1320
1404
function createFlowCall ( antecedent : FlowNode , node : CallExpression ) : FlowNode {
1321
1405
setFlowNodeReferenced ( antecedent ) ;
1322
- return initFlowNode ( { flags : FlowFlags . Call , antecedent , node } ) ;
1406
+ return createFlowCallNode ( FlowFlags . Call , node , antecedent ) ;
1323
1407
}
1324
1408
1325
1409
function finishFlowLabel ( flow : FlowLabel ) : FlowNode {
@@ -2415,7 +2499,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
2415
2499
const host = typeAlias . parent . parent ;
2416
2500
container = findAncestor ( host . parent , n => ! ! ( getContainerFlags ( n ) & ContainerFlags . IsContainer ) ) || file ;
2417
2501
blockScopeContainer = getEnclosingBlockScopeContainer ( host ) || file ;
2418
- currentFlow = initFlowNode ( { flags : FlowFlags . Start } ) ;
2502
+ currentFlow = createFlowStartNode ( FlowFlags . Start ) ;
2419
2503
parent = typeAlias ;
2420
2504
bind ( typeAlias . typeExpression ) ;
2421
2505
const declName = getNameOfDeclaration ( typeAlias ) ;
0 commit comments