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;
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;
|
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 makeTwrTry(JCTry tree) {
1435 make_at(tree.pos());
1436 twrVars = twrVars.dup();
1437 JCBlock armBlock = makeTwrBlock(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 makeTwrBlock(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 = makeTwrFinallyClause(primaryException, expr);
1501 make.at(oldPos);
1502 JCTry outerTry = make.Try(makeTwrBlock(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 makeTwrFinallyClause(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 (primaryException != null) {try...} else resourceClose;
1529 JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)),
1530 tryTree,
1531 makeResourceCloseInvocation(resource));
1532
1533 // if (#resource != null) { if (primaryException ... }
1534 return make.Block(0L,
1535 List.<JCStatement>of(make.If(makeNonNullCheck(resource),
1536 closeIfStatement,
1537 null)));
1538 }
1539
1540 private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1541 // create resource.close() method invocation protected by a null-check
1542
1543 JCExpression resourceClose = makeCall(resource,
1544 names.close,
1545 List.<JCExpression>nil());
1546 return make.Exec(resourceClose);
1547
1548 //return make.If(makeNonNullCheck(resource), make.Exec(resourceClose), null);
1549 }
1550
1551 private JCExpression makeNonNullCheck(JCExpression expression) {
1552 return makeBinary(JCTree.NE, expression, makeNull());
1553 }
1554
1555 /** Construct a tree that represents the outer instance
1556 * <C.this>. Never pick the current `this'.
1557 * @param pos The source code position to be used for the tree.
1558 * @param c The qualifier class.
1559 */
1560 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1561 List<VarSymbol> ots = outerThisStack;
1562 if (ots.isEmpty()) {
1563 log.error(pos, "no.encl.instance.of.type.in.scope", c);
1564 Assert.error();
1565 return makeNull();
1566 }
1567 VarSymbol ot = ots.head;
1568 JCExpression tree = access(make.at(pos).Ident(ot));
1569 TypeSymbol otc = ot.type.tsym;
1570 while (otc != c) {
1571 do {
1572 ots = ots.tail;
3567 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3568 }
3569
3570 public void visitLetExpr(LetExpr tree) {
3571 tree.defs = translateVarDefs(tree.defs);
3572 tree.expr = translate(tree.expr, tree.type);
3573 result = tree;
3574 }
3575
3576 // There ought to be nothing to rewrite here;
3577 // we don't generate code.
3578 public void visitAnnotation(JCAnnotation tree) {
3579 result = tree;
3580 }
3581
3582 @Override
3583 public void visitTry(JCTry tree) {
3584 if (tree.resources.isEmpty()) {
3585 super.visitTry(tree);
3586 } else {
3587 result = makeTwrTry(tree);
3588 }
3589 }
3590
3591 /**************************************************************************
3592 * main method
3593 *************************************************************************/
3594
3595 /** Translate a toplevel class and return a list consisting of
3596 * the translated class and translated versions of all inner classes.
3597 * @param env The attribution environment current at the class definition.
3598 * We need this for resolving some additional symbols.
3599 * @param cdef The tree representing the class definition.
3600 */
3601 public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3602 ListBuffer<JCTree> translated = null;
3603 try {
3604 attrEnv = env;
3605 this.make = make;
3606 endPositions = env.toplevel.endPositions;
3607 currentClass = null;
|