1423 // need to go via this$n |
1423 // need to go via this$n |
1424 return makeOuterThis(pos, c); |
1424 return makeOuterThis(pos, c); |
1425 } |
1425 } |
1426 } |
1426 } |
1427 |
1427 |
1428 /** Optionally replace a try statement with an automatic resource |
1428 /** |
1429 * management (ARM) block. |
1429 * Optionally replace a try statement with the desugaring of a |
|
1430 * try-with-resources statement. The canonical desugaring of |
|
1431 * |
|
1432 * try ResourceSpecification |
|
1433 * Block |
|
1434 * |
|
1435 * is |
|
1436 * |
|
1437 * { |
|
1438 * final VariableModifiers_minus_final R #resource = Expression; |
|
1439 * Throwable #primaryException = null; |
|
1440 * |
|
1441 * try ResourceSpecificationtail |
|
1442 * Block |
|
1443 * catch (Throwable #t) { |
|
1444 * #primaryException = t; |
|
1445 * throw #t; |
|
1446 * } finally { |
|
1447 * if (#resource != null) { |
|
1448 * if (#primaryException != null) { |
|
1449 * try { |
|
1450 * #resource.close(); |
|
1451 * } catch(Throwable #suppressedException) { |
|
1452 * #primaryException.addSuppressed(#suppressedException); |
|
1453 * } |
|
1454 * } else { |
|
1455 * #resource.close(); |
|
1456 * } |
|
1457 * } |
|
1458 * } |
|
1459 * |
1430 * @param tree The try statement to inspect. |
1460 * @param tree The try statement to inspect. |
1431 * @return An ARM block, or the original try block if there are no |
1461 * @return A a desugared try-with-resources tree, or the original |
1432 * resources to manage. |
1462 * try block if there are no resources to manage. |
1433 */ |
1463 */ |
1434 JCTree makeArmTry(JCTry tree) { |
1464 JCTree makeTwrTry(JCTry tree) { |
1435 make_at(tree.pos()); |
1465 make_at(tree.pos()); |
1436 twrVars = twrVars.dup(); |
1466 twrVars = twrVars.dup(); |
1437 JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0); |
1467 JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, 0); |
1438 if (tree.catchers.isEmpty() && tree.finalizer == null) |
1468 if (tree.catchers.isEmpty() && tree.finalizer == null) |
1439 result = translate(armBlock); |
1469 result = translate(twrBlock); |
1440 else |
1470 else |
1441 result = translate(make.Try(armBlock, tree.catchers, tree.finalizer)); |
1471 result = translate(make.Try(twrBlock, tree.catchers, tree.finalizer)); |
1442 twrVars = twrVars.leave(); |
1472 twrVars = twrVars.leave(); |
1443 return result; |
1473 return result; |
1444 } |
1474 } |
1445 |
1475 |
1446 private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) { |
1476 private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) { |
1447 if (resources.isEmpty()) |
1477 if (resources.isEmpty()) |
1448 return block; |
1478 return block; |
1449 |
1479 |
1450 // Add resource declaration or expression to block statements |
1480 // Add resource declaration or expression to block statements |
1451 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); |
1481 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); |
1495 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat)); |
1525 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat)); |
1496 JCCatch catchClause = make.Catch(paramTree, catchBlock); |
1526 JCCatch catchClause = make.Catch(paramTree, catchBlock); |
1497 |
1527 |
1498 int oldPos = make.pos; |
1528 int oldPos = make.pos; |
1499 make.at(TreeInfo.endPos(block)); |
1529 make.at(TreeInfo.endPos(block)); |
1500 JCBlock finallyClause = makeArmFinallyClause(primaryException, expr); |
1530 JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr); |
1501 make.at(oldPos); |
1531 make.at(oldPos); |
1502 JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1), |
1532 JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1), |
1503 List.<JCCatch>of(catchClause), |
1533 List.<JCCatch>of(catchClause), |
1504 finallyClause); |
1534 finallyClause); |
1505 stats.add(outerTry); |
1535 stats.add(outerTry); |
1506 return make.Block(0L, stats.toList()); |
1536 return make.Block(0L, stats.toList()); |
1507 } |
1537 } |
1508 |
1538 |
1509 private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) { |
1539 private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) { |
1510 // primaryException.addSuppressed(catchException); |
1540 // primaryException.addSuppressed(catchException); |
1511 VarSymbol catchException = |
1541 VarSymbol catchException = |
1512 new VarSymbol(0, make.paramName(2), |
1542 new VarSymbol(0, make.paramName(2), |
1513 syms.throwableType, |
1543 syms.throwableType, |
1514 currentMethodSym); |
1544 currentMethodSym); |
1523 JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null); |
1553 JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null); |
1524 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement)); |
1554 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement)); |
1525 List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock)); |
1555 List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock)); |
1526 JCTry tryTree = make.Try(tryBlock, catchClauses, null); |
1556 JCTry tryTree = make.Try(tryBlock, catchClauses, null); |
1527 |
1557 |
1528 // if (resource != null) resourceClose; |
1558 // if (primaryException != null) {try...} else resourceClose; |
1529 JCExpression nullCheck = makeBinary(JCTree.NE, |
1559 JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)), |
1530 make.Ident(primaryException), |
|
1531 makeNull()); |
|
1532 JCIf closeIfStatement = make.If(nullCheck, |
|
1533 tryTree, |
1560 tryTree, |
1534 makeResourceCloseInvocation(resource)); |
1561 makeResourceCloseInvocation(resource)); |
1535 return make.Block(0L, List.<JCStatement>of(closeIfStatement)); |
1562 |
|
1563 // if (#resource != null) { if (primaryException ... } |
|
1564 return make.Block(0L, |
|
1565 List.<JCStatement>of(make.If(makeNonNullCheck(resource), |
|
1566 closeIfStatement, |
|
1567 null))); |
1536 } |
1568 } |
1537 |
1569 |
1538 private JCStatement makeResourceCloseInvocation(JCExpression resource) { |
1570 private JCStatement makeResourceCloseInvocation(JCExpression resource) { |
1539 // create resource.close() method invocation |
1571 // create resource.close() method invocation |
1540 JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil()); |
1572 JCExpression resourceClose = makeCall(resource, |
|
1573 names.close, |
|
1574 List.<JCExpression>nil()); |
1541 return make.Exec(resourceClose); |
1575 return make.Exec(resourceClose); |
|
1576 } |
|
1577 |
|
1578 private JCExpression makeNonNullCheck(JCExpression expression) { |
|
1579 return makeBinary(JCTree.NE, expression, makeNull()); |
1542 } |
1580 } |
1543 |
1581 |
1544 /** Construct a tree that represents the outer instance |
1582 /** Construct a tree that represents the outer instance |
1545 * <C.this>. Never pick the current `this'. |
1583 * <C.this>. Never pick the current `this'. |
1546 * @param pos The source code position to be used for the tree. |
1584 * @param pos The source code position to be used for the tree. |