@@ -924,7 +924,7 @@ private Object visit(IStatementContainer nd) {
924
924
}.find (ctxt .size () - 1 );
925
925
}
926
926
927
- private Node visit (Node nd , Object trueSuccessors , Object falseSuccessors ) {
927
+ private Node visitWithSuccessors (Node nd , Object trueSuccessors , Object falseSuccessors ) {
928
928
if (nd == null ) return null ;
929
929
930
930
followingCache .put (nd , union (followingCache .get (nd ), union (trueSuccessors , falseSuccessors )));
@@ -936,11 +936,19 @@ private Node visit(Node nd, Object trueSuccessors, Object falseSuccessors) {
936
936
return First .of (nd );
937
937
}
938
938
939
+ private Node visitWithSuccessors (Node nd , Object successors ) {
940
+ if (nd == null ) return null ;
941
+
942
+ followingCache .put (nd , union (followingCache .get (nd ), successors ));
943
+ nd .accept (this , new SimpleSuccessorInfo (successors ));
944
+ return First .of (nd );
945
+ }
946
+
939
947
private Object seq (Object ... nodes ) {
940
948
Object fst = nodes [nodes .length - 1 ];
941
949
for (int i = nodes .length - 2 ; i >= 0 ; --i ) {
942
950
for (Node node : createReversedIterable (nodes [i ])) {
943
- Node ffst = visit (node , fst , null );
951
+ Node ffst = visitWithSuccessors (node , fst );
944
952
if (ffst != null ) fst = ffst ;
945
953
}
946
954
}
@@ -1212,7 +1220,7 @@ public Void visit(LabeledStatement nd, SuccessorInfo i) {
1212
1220
@ Override
1213
1221
public Void visit (ExpressionStatement nd , SuccessorInfo i ) {
1214
1222
writeSuccessors (nd , First .of (nd .getExpression ()));
1215
- visit (nd .getExpression (), i .getAllSuccessors (), null );
1223
+ visitWithSuccessors (nd .getExpression (), i .getAllSuccessors ());
1216
1224
return null ;
1217
1225
}
1218
1226
@@ -1227,20 +1235,20 @@ public Void visit(IfStatement nd, SuccessorInfo i) {
1227
1235
Expression test = nd .getTest ();
1228
1236
writeSuccessors (nd , First .of (test ));
1229
1237
Object following = i .getAllSuccessors ();
1230
- visit (
1238
+ visitWithSuccessors (
1231
1239
test ,
1232
1240
First .of (nd .getConsequent ()),
1233
1241
nd .hasAlternate () ? First .of (nd .getAlternate ()) : following );
1234
- this . visit (nd .getConsequent (), following , null );
1235
- this . visit (nd .getAlternate (), following , null );
1242
+ visitWithSuccessors (nd .getConsequent (), following );
1243
+ visitWithSuccessors (nd .getAlternate (), following );
1236
1244
return null ;
1237
1245
}
1238
1246
1239
1247
@ Override
1240
1248
public Void visit (ConditionalExpression nd , SuccessorInfo i ) {
1241
1249
Expression test = nd .getTest ();
1242
1250
writeSuccessors (nd , First .of (test ));
1243
- visit (test , First .of (nd .getConsequent ()), First .of (nd .getAlternate ()));
1251
+ visitWithSuccessors (test , First .of (nd .getConsequent ()), First .of (nd .getAlternate ()));
1244
1252
1245
1253
nd .getConsequent ().accept (this , i );
1246
1254
nd .getAlternate ().accept (this , i );
@@ -1294,10 +1302,10 @@ public Void visit(SwitchStatement nd, SuccessorInfo i) {
1294
1302
}
1295
1303
}
1296
1304
1297
- if (nd .getCases ().isEmpty ()) this . visit (nd .getDiscriminant (), i .getAllSuccessors (), null );
1305
+ if (nd .getCases ().isEmpty ()) visitWithSuccessors (nd .getDiscriminant (), i .getAllSuccessors ());
1298
1306
else if (nd .getCases ().size () > 1 && nd .getCases ().get (0 ).isDefault ())
1299
- this . visit (nd .getDiscriminant (), First .of (nd .getCases ().get (1 )), null );
1300
- else this . visit (nd .getDiscriminant (), First .of (nd .getCases ().get (0 )), null );
1307
+ visitWithSuccessors (nd .getDiscriminant (), First .of (nd .getCases ().get (1 )));
1308
+ else visitWithSuccessors (nd .getDiscriminant (), First .of (nd .getCases ().get (0 )));
1301
1309
this .seq (nd .getCases (), i .getAllSuccessors ());
1302
1310
this .ctxt .pop ();
1303
1311
return null ;
@@ -1318,14 +1326,14 @@ public Void visit(SwitchCase nd, SuccessorInfo i) {
1318
1326
1319
1327
@ Override
1320
1328
public Void visit (ReturnStatement nd , SuccessorInfo i ) {
1321
- visit (nd .getArgument (), nd , null );
1329
+ visitWithSuccessors (nd .getArgument (), nd );
1322
1330
writeSuccessors (nd , findTarget (JumpType .RETURN , null ));
1323
1331
return null ;
1324
1332
}
1325
1333
1326
1334
@ Override
1327
1335
public Void visit (ThrowStatement nd , SuccessorInfo i ) {
1328
- visit (nd .getArgument (), nd , null );
1336
+ visitWithSuccessors (nd .getArgument (), nd );
1329
1337
writeSuccessors (nd , findTarget (JumpType .THROW , null ));
1330
1338
return null ;
1331
1339
}
@@ -1337,17 +1345,22 @@ public Void visit(TryStatement nd, SuccessorInfo i) {
1337
1345
1338
1346
ctxt .push (nd );
1339
1347
Object fst = nd .hasFinalizer () ? First .of (nd .getFinalizer ()) : i .getAllSuccessors ();
1340
- this . visit (nd .getBlock (), fst , null );
1348
+ visitWithSuccessors (nd .getBlock (), fst );
1341
1349
ctxt .pop ();
1342
1350
1343
1351
if (nd .hasFinalizer ()) ctxt .push (new Finally (nd .getFinalizer ().getLoc (), nd .getFinalizer ()));
1344
1352
1345
- for (int j = 0 , n = nd .getAllHandlers ().size (); j < n ; ++j )
1346
- visit (nd .getAllHandlers ().get (j ), fst , j + 1 < n ? nd .getAllHandlers ().get (j + 1 ) : null );
1353
+ for (int j = 0 , n = nd .getAllHandlers ().size (); j < n ; ++j ) {
1354
+ if (j + 1 < n ) {
1355
+ visitWithSuccessors (nd .getAllHandlers ().get (j ), fst , nd .getAllHandlers ().get (j + 1 ));
1356
+ } else {
1357
+ visitWithSuccessors (nd .getAllHandlers ().get (j ), fst );
1358
+ }
1359
+ }
1347
1360
1348
1361
if (nd .hasFinalizer ()) {
1349
1362
ctxt .pop ();
1350
- visit (nd .getFinalizer (), followingCache .get (nd .getFinalizer ()), null );
1363
+ visitWithSuccessors (nd .getFinalizer (), followingCache .get (nd .getFinalizer ()));
1351
1364
}
1352
1365
return null ;
1353
1366
}
@@ -1397,8 +1410,8 @@ public Void visit(WhileStatement nd, SuccessorInfo i) {
1397
1410
Node testStart = First .of (test );
1398
1411
writeSuccessors (nd , testStart );
1399
1412
ctxt .push (nd );
1400
- visit (nd .getBody (), testStart , null );
1401
- visit (test , First .of (nd .getBody ()), i .getAllSuccessors ());
1413
+ visitWithSuccessors (nd .getBody (), testStart );
1414
+ visitWithSuccessors (test , First .of (nd .getBody ()), i .getAllSuccessors ());
1402
1415
ctxt .pop ();
1403
1416
return null ;
1404
1417
}
@@ -1409,8 +1422,8 @@ public Void visit(DoWhileStatement nd, SuccessorInfo i) {
1409
1422
writeSuccessors (nd , body );
1410
1423
ctxt .push (nd );
1411
1424
Expression test = nd .getTest ();
1412
- visit (nd .getBody (), First .of (test ), null );
1413
- visit (test , body , i .getAllSuccessors ());
1425
+ visitWithSuccessors (nd .getBody (), First .of (test ));
1426
+ visitWithSuccessors (test , body , i .getAllSuccessors ());
1414
1427
ctxt .pop ();
1415
1428
return null ;
1416
1429
}
@@ -1431,11 +1444,11 @@ public Void visit(ForStatement nd, SuccessorInfo i) {
1431
1444
writeSuccessors (nd , First .of (nd .hasInit () ? nd .getInit () : nd .hasTest () ? nd .getTest () : nd .getBody ()));
1432
1445
ctxt .push (nd );
1433
1446
Node fst = First .of (nd .hasTest () ? nd .getTest () : nd .getBody ());
1434
- visit (nd .getInit (), fst , null );
1447
+ visitWithSuccessors (nd .getInit (), fst );
1435
1448
1436
1449
if (nd .hasTest ()) {
1437
1450
Expression test = nd .getTest ();
1438
- visit (test , First .of (nd .getBody ()), i .getAllSuccessors ());
1451
+ visitWithSuccessors (test , First .of (nd .getBody ()), i .getAllSuccessors ());
1439
1452
}
1440
1453
seq (nd .getBody (), nd .getUpdate (), fst );
1441
1454
ctxt .pop ();
@@ -1449,7 +1462,7 @@ public Void visit(SequenceExpression nd, SuccessorInfo i) {
1449
1462
int n = expressions .size () - 1 ;
1450
1463
expressions .get (n ).accept (this , i );
1451
1464
Node next = First .of (expressions .get (n ));
1452
- while (--n >= 0 ) next = visit (expressions .get (n ), next , null );
1465
+ while (--n >= 0 ) next = visitWithSuccessors (expressions .get (n ), next );
1453
1466
return null ;
1454
1467
}
1455
1468
@@ -1579,16 +1592,16 @@ public Void visit(AssignmentExpression nd, SuccessorInfo i) {
1579
1592
if ("&&=" .equals (nd .getOperator ()) || "||=" .equals (nd .getOperator ()) || "??=" .equals (nd .getOperator ())) {
1580
1593
if ("&&=" .equals (nd .getOperator ())) {
1581
1594
// from lhs to rhs on truthy. from lhs to false-branch on falsy.
1582
- visit (nd .getLeft (), First .of (nd .getRight ()), i .getSuccessors (false ));
1595
+ visitWithSuccessors (nd .getLeft (), First .of (nd .getRight ()), i .getSuccessors (false ));
1583
1596
} else if ("||=" .equals (nd .getOperator ())) {
1584
1597
// from lhs to true-branch on truthy. from lhs to rhs on falsy.
1585
- visit (nd .getLeft (), i .getSuccessors (true ), First .of (nd .getRight ()));
1598
+ visitWithSuccessors (nd .getLeft (), i .getSuccessors (true ), First .of (nd .getRight ()));
1586
1599
} else { // "??="
1587
1600
// the union of the above - truthyness is unknown.
1588
- visit (nd .getLeft (), union (First .of (nd .getRight ()), i .getAllSuccessors ()), null );
1601
+ visitWithSuccessors (nd .getLeft (), union (First .of (nd .getRight ()), i .getAllSuccessors ()));
1589
1602
}
1590
1603
1591
- visit (nd .getRight (), First .of (nd ), null ); // from right to assignment.
1604
+ visitWithSuccessors (nd .getRight (), First .of (nd )); // from right to assignment.
1592
1605
1593
1606
writeSuccessors (nd , i .getGuardedSuccessors (nd ));
1594
1607
} else {
@@ -1612,7 +1625,7 @@ public Void visit(BinaryExpression nd, SuccessorInfo i) {
1612
1625
union (
1613
1626
First .of (nd .getRight ()),
1614
1627
i .getAllSuccessors ()); // short-circuiting happens with both truthy and falsy values
1615
- visit (nd .getLeft (), leftSucc , null );
1628
+ visitWithSuccessors (nd .getLeft (), leftSucc );
1616
1629
nd .getRight ().accept (this , i );
1617
1630
} else {
1618
1631
this .seq (nd .getLeft (), nd .getRight (), nd );
@@ -1634,36 +1647,36 @@ public Void visit(LogicalExpression nd, SuccessorInfo i) {
1634
1647
Expression left = nd .getLeft ();
1635
1648
writeSuccessors (nd , First .of (left ));
1636
1649
if ("&&" .equals (nd .getOperator ()))
1637
- visit (left , First .of (nd .getRight ()), i .getSuccessors (false ));
1638
- else visit (left , i .getSuccessors (true ), First .of (nd .getRight ()));
1650
+ visitWithSuccessors (left , First .of (nd .getRight ()), i .getSuccessors (false ));
1651
+ else visitWithSuccessors (left , i .getSuccessors (true ), First .of (nd .getRight ()));
1639
1652
nd .getRight ().accept (this , i );
1640
1653
return null ;
1641
1654
}
1642
1655
1643
1656
@ Override
1644
1657
public Void visit (SpreadElement nd , SuccessorInfo i ) {
1645
- visit (nd .getArgument (), nd , null );
1658
+ visitWithSuccessors (nd .getArgument (), nd );
1646
1659
writeSuccessors (nd , i .getAllSuccessors ());
1647
1660
return null ;
1648
1661
}
1649
1662
1650
1663
@ Override
1651
1664
public Void visit (UnaryExpression nd , SuccessorInfo i ) {
1652
- visit (nd .getArgument (), nd , null );
1665
+ visitWithSuccessors (nd .getArgument (), nd );
1653
1666
writeSuccessors (nd , i .getGuardedSuccessors (nd ));
1654
1667
return null ;
1655
1668
}
1656
1669
1657
1670
@ Override
1658
1671
public Void visit (UpdateExpression nd , SuccessorInfo i ) {
1659
- visit (nd .getArgument (), nd , null );
1672
+ visitWithSuccessors (nd .getArgument (), nd );
1660
1673
writeSuccessors (nd , i .getGuardedSuccessors (nd ));
1661
1674
return null ;
1662
1675
}
1663
1676
1664
1677
@ Override
1665
1678
public Void visit (YieldExpression nd , SuccessorInfo i ) {
1666
- visit (nd .getArgument (), nd , null );
1679
+ visitWithSuccessors (nd .getArgument (), nd );
1667
1680
// yield expressions may throw
1668
1681
writeSuccessors (nd , union (this .findTarget (JumpType .THROW , null ), i .getGuardedSuccessors (nd )));
1669
1682
return null ;
@@ -1759,7 +1772,7 @@ private Node visitComprehensionBlock(ComprehensionExpression nd, int i, Object f
1759
1772
1760
1773
private Node visitComprehensionFilter (ComprehensionExpression nd , Object follow ) {
1761
1774
if (nd .hasFilter ()) {
1762
- visit (nd .getFilter (), visitComprehensionBody (nd , follow ), follow );
1775
+ visitWithSuccessors (nd .getFilter (), visitComprehensionBody (nd , follow ), follow );
1763
1776
return First .of (nd .getFilter ());
1764
1777
} else {
1765
1778
return visitComprehensionBody (nd , follow );
@@ -1873,7 +1886,7 @@ public Void visit(JSXAttribute nd, SuccessorInfo c) {
1873
1886
1874
1887
@ Override
1875
1888
public Void visit (JSXSpreadAttribute nd , SuccessorInfo c ) {
1876
- visit (nd .getArgument (), nd , null );
1889
+ visitWithSuccessors (nd .getArgument (), nd );
1877
1890
Label propkey = trapwriter .localID (nd , "JSXSpreadAttribute" );
1878
1891
Label spreadkey = trapwriter .localID (nd );
1879
1892
trapwriter .addTuple ("successor" , spreadkey , propkey );
0 commit comments