1408 }
1409 //where
1410 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1411 return access(v, make.at(pos).Ident(v), null, false);
1412 }
1413
1414 /** Construct a tree simulating the expression <C.this>.
1415 * @param pos The source code position to be used for the tree.
1416 * @param c The qualifier class.
1417 */
1418 JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1419 if (currentClass == c) {
1420 // in this case, `this' works fine
1421 return make.at(pos).This(c.erasure(types));
1422 } else {
1423 // need to go via this$n
1424 return makeOuterThis(pos, c);
1425 }
1426 }
1427
1428 /** Optionally replace a try statement with an automatic resource
1429 * management (ARM) block.
1430 * @param tree The try statement to inspect.
1431 * @return An ARM block, or the original try block if there are no
1432 * resources to manage.
1433 */
1434 JCTree makeArmTry(JCTry tree) {
1435 make_at(tree.pos());
1436 twrVars = twrVars.dup();
1437 JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0);
1438 if (tree.catchers.isEmpty() && tree.finalizer == null)
1439 result = translate(armBlock);
1440 else
1441 result = translate(make.Try(armBlock, tree.catchers, tree.finalizer));
1442 twrVars = twrVars.leave();
1443 return result;
1444 }
1445
1446 private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) {
1447 if (resources.isEmpty())
1448 return block;
1449
1450 // Add resource declaration or expression to block statements
1451 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1452 JCTree resource = resources.head;
1453 JCExpression expr = null;
1454 if (resource instanceof JCVariableDecl) {
1455 JCVariableDecl var = (JCVariableDecl) resource;
1456 expr = make.Ident(var.sym).setType(resource.type);
1457 stats.add(var);
1458 } else {
1459 Assert.check(resource instanceof JCExpression);
1460 VarSymbol syntheticTwrVar =
1461 new VarSymbol(SYNTHETIC | FINAL,
1462 makeSyntheticName(names.fromString("twrVar" +
1463 depth), twrVars),
1464 (resource.type.tag == TypeTags.BOT) ?
1465 syms.autoCloseableType : resource.type,
1466 currentMethodSym);
1480 currentMethodSym);
1481 twrVars.enter(primaryException);
1482 JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
1483 stats.add(primaryExceptionTreeDecl);
1484
1485 // Create catch clause that saves exception and then rethrows it
1486 VarSymbol param =
1487 new VarSymbol(FINAL|SYNTHETIC,
1488 names.fromString("t" +
1489 target.syntheticNameChar()),
1490 syms.throwableType,
1491 currentMethodSym);
1492 JCVariableDecl paramTree = make.VarDef(param, null);
1493 JCStatement assign = make.Assignment(primaryException, make.Ident(param));
1494 JCStatement rethrowStat = make.Throw(make.Ident(param));
1495 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
1496 JCCatch catchClause = make.Catch(paramTree, catchBlock);
1497
1498 int oldPos = make.pos;
1499 make.at(TreeInfo.endPos(block));
1500 JCBlock finallyClause = makeArmFinallyClause(primaryException, expr);
1501 make.at(oldPos);
1502 JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1),
1503 List.<JCCatch>of(catchClause),
1504 finallyClause);
1505 stats.add(outerTry);
1506 return make.Block(0L, stats.toList());
1507 }
1508
1509 private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) {
1510 // primaryException.addSuppressed(catchException);
1511 VarSymbol catchException =
1512 new VarSymbol(0, make.paramName(2),
1513 syms.throwableType,
1514 currentMethodSym);
1515 JCStatement addSuppressionStatement =
1516 make.Exec(makeCall(make.Ident(primaryException),
1517 names.addSuppressed,
1518 List.<JCExpression>of(make.Ident(catchException))));
1519
1520 // try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
1521 JCBlock tryBlock =
1522 make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
1523 JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
1524 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
1525 List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
1526 JCTry tryTree = make.Try(tryBlock, catchClauses, null);
1527
1528 // if (resource != null) resourceClose;
1529 JCExpression nullCheck = makeBinary(JCTree.NE,
1530 make.Ident(primaryException),
1531 makeNull());
1532 JCIf closeIfStatement = make.If(nullCheck,
1533 tryTree,
1534 makeResourceCloseInvocation(resource));
1535 return make.Block(0L, List.<JCStatement>of(closeIfStatement));
1536 }
1537
1538 private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1539 // create resource.close() method invocation
1540 JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil());
1541 return make.Exec(resourceClose);
1542 }
1543
1544 /** Construct a tree that represents the outer instance
1545 * <C.this>. Never pick the current `this'.
1546 * @param pos The source code position to be used for the tree.
1547 * @param c The qualifier class.
1548 */
1549 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1550 List<VarSymbol> ots = outerThisStack;
1551 if (ots.isEmpty()) {
1552 log.error(pos, "no.encl.instance.of.type.in.scope", c);
1553 Assert.error();
1554 return makeNull();
1555 }
1556 VarSymbol ot = ots.head;
1557 JCExpression tree = access(make.at(pos).Ident(ot));
1558 TypeSymbol otc = ot.type.tsym;
1559 while (otc != c) {
1560 do {
1561 ots = ots.tail;
1562 if (ots.isEmpty()) {
1563 log.error(pos,
3556 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3557 }
3558
3559 public void visitLetExpr(LetExpr tree) {
3560 tree.defs = translateVarDefs(tree.defs);
3561 tree.expr = translate(tree.expr, tree.type);
3562 result = tree;
3563 }
3564
3565 // There ought to be nothing to rewrite here;
3566 // we don't generate code.
3567 public void visitAnnotation(JCAnnotation tree) {
3568 result = tree;
3569 }
3570
3571 @Override
3572 public void visitTry(JCTry tree) {
3573 if (tree.resources.isEmpty()) {
3574 super.visitTry(tree);
3575 } else {
3576 result = makeArmTry(tree);
3577 }
3578 }
3579
3580 /**************************************************************************
3581 * main method
3582 *************************************************************************/
3583
3584 /** Translate a toplevel class and return a list consisting of
3585 * the translated class and translated versions of all inner classes.
3586 * @param env The attribution environment current at the class definition.
3587 * We need this for resolving some additional symbols.
3588 * @param cdef The tree representing the class definition.
3589 */
3590 public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3591 ListBuffer<JCTree> translated = null;
3592 try {
3593 attrEnv = env;
3594 this.make = make;
3595 endPositions = env.toplevel.endPositions;
3596 currentClass = null;
|
1408 }
1409 //where
1410 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1411 return access(v, make.at(pos).Ident(v), null, false);
1412 }
1413
1414 /** Construct a tree simulating the expression <C.this>.
1415 * @param pos The source code position to be used for the tree.
1416 * @param c The qualifier class.
1417 */
1418 JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1419 if (currentClass == c) {
1420 // in this case, `this' works fine
1421 return make.at(pos).This(c.erasure(types));
1422 } else {
1423 // need to go via this$n
1424 return makeOuterThis(pos, c);
1425 }
1426 }
1427
1428 /**
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 *
1460 * @param tree The try statement to inspect.
1461 * @return A a desugared try-with-resources tree, or the original
1462 * try block if there are no resources to manage.
1463 */
1464 JCTree makeTwrTry(JCTry tree) {
1465 make_at(tree.pos());
1466 twrVars = twrVars.dup();
1467 JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, 0);
1468 if (tree.catchers.isEmpty() && tree.finalizer == null)
1469 result = translate(twrBlock);
1470 else
1471 result = translate(make.Try(twrBlock, tree.catchers, tree.finalizer));
1472 twrVars = twrVars.leave();
1473 return result;
1474 }
1475
1476 private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) {
1477 if (resources.isEmpty())
1478 return block;
1479
1480 // Add resource declaration or expression to block statements
1481 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1482 JCTree resource = resources.head;
1483 JCExpression expr = null;
1484 if (resource instanceof JCVariableDecl) {
1485 JCVariableDecl var = (JCVariableDecl) resource;
1486 expr = make.Ident(var.sym).setType(resource.type);
1487 stats.add(var);
1488 } else {
1489 Assert.check(resource instanceof JCExpression);
1490 VarSymbol syntheticTwrVar =
1491 new VarSymbol(SYNTHETIC | FINAL,
1492 makeSyntheticName(names.fromString("twrVar" +
1493 depth), twrVars),
1494 (resource.type.tag == TypeTags.BOT) ?
1495 syms.autoCloseableType : resource.type,
1496 currentMethodSym);
1510 currentMethodSym);
1511 twrVars.enter(primaryException);
1512 JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
1513 stats.add(primaryExceptionTreeDecl);
1514
1515 // Create catch clause that saves exception and then rethrows it
1516 VarSymbol param =
1517 new VarSymbol(FINAL|SYNTHETIC,
1518 names.fromString("t" +
1519 target.syntheticNameChar()),
1520 syms.throwableType,
1521 currentMethodSym);
1522 JCVariableDecl paramTree = make.VarDef(param, null);
1523 JCStatement assign = make.Assignment(primaryException, make.Ident(param));
1524 JCStatement rethrowStat = make.Throw(make.Ident(param));
1525 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
1526 JCCatch catchClause = make.Catch(paramTree, catchBlock);
1527
1528 int oldPos = make.pos;
1529 make.at(TreeInfo.endPos(block));
1530 JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr);
1531 make.at(oldPos);
1532 JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1533 List.<JCCatch>of(catchClause),
1534 finallyClause);
1535 stats.add(outerTry);
1536 return make.Block(0L, stats.toList());
1537 }
1538
1539 private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) {
1540 // primaryException.addSuppressed(catchException);
1541 VarSymbol catchException =
1542 new VarSymbol(0, make.paramName(2),
1543 syms.throwableType,
1544 currentMethodSym);
1545 JCStatement addSuppressionStatement =
1546 make.Exec(makeCall(make.Ident(primaryException),
1547 names.addSuppressed,
1548 List.<JCExpression>of(make.Ident(catchException))));
1549
1550 // try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
1551 JCBlock tryBlock =
1552 make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
1553 JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
1554 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
1555 List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
1556 JCTry tryTree = make.Try(tryBlock, catchClauses, null);
1557
1558 // if (primaryException != null) {try...} else resourceClose;
1559 JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)),
1560 tryTree,
1561 makeResourceCloseInvocation(resource));
1562
1563 // if (#resource != null) { if (primaryException ... }
1564 return make.Block(0L,
1565 List.<JCStatement>of(make.If(makeNonNullCheck(resource),
1566 closeIfStatement,
1567 null)));
1568 }
1569
1570 private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1571 // create resource.close() method invocation
1572 JCExpression resourceClose = makeCall(resource,
1573 names.close,
1574 List.<JCExpression>nil());
1575 return make.Exec(resourceClose);
1576 }
1577
1578 private JCExpression makeNonNullCheck(JCExpression expression) {
1579 return makeBinary(JCTree.NE, expression, makeNull());
1580 }
1581
1582 /** Construct a tree that represents the outer instance
1583 * <C.this>. Never pick the current `this'.
1584 * @param pos The source code position to be used for the tree.
1585 * @param c The qualifier class.
1586 */
1587 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1588 List<VarSymbol> ots = outerThisStack;
1589 if (ots.isEmpty()) {
1590 log.error(pos, "no.encl.instance.of.type.in.scope", c);
1591 Assert.error();
1592 return makeNull();
1593 }
1594 VarSymbol ot = ots.head;
1595 JCExpression tree = access(make.at(pos).Ident(ot));
1596 TypeSymbol otc = ot.type.tsym;
1597 while (otc != c) {
1598 do {
1599 ots = ots.tail;
1600 if (ots.isEmpty()) {
1601 log.error(pos,
3594 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3595 }
3596
3597 public void visitLetExpr(LetExpr tree) {
3598 tree.defs = translateVarDefs(tree.defs);
3599 tree.expr = translate(tree.expr, tree.type);
3600 result = tree;
3601 }
3602
3603 // There ought to be nothing to rewrite here;
3604 // we don't generate code.
3605 public void visitAnnotation(JCAnnotation tree) {
3606 result = tree;
3607 }
3608
3609 @Override
3610 public void visitTry(JCTry tree) {
3611 if (tree.resources.isEmpty()) {
3612 super.visitTry(tree);
3613 } else {
3614 result = makeTwrTry(tree);
3615 }
3616 }
3617
3618 /**************************************************************************
3619 * main method
3620 *************************************************************************/
3621
3622 /** Translate a toplevel class and return a list consisting of
3623 * the translated class and translated versions of all inner classes.
3624 * @param env The attribution environment current at the class definition.
3625 * We need this for resolving some additional symbols.
3626 * @param cdef The tree representing the class definition.
3627 */
3628 public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3629 ListBuffer<JCTree> translated = null;
3630 try {
3631 attrEnv = env;
3632 this.make = make;
3633 endPositions = env.toplevel.endPositions;
3634 currentClass = null;
|