1383 } 1384 //where 1385 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) { 1386 return access(v, make.at(pos).Ident(v), null, false); 1387 } 1388 1389 /** Construct a tree simulating the expression <C.this>. 1390 * @param pos The source code position to be used for the tree. 1391 * @param c The qualifier class. 1392 */ 1393 JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) { 1394 if (currentClass == c) { 1395 // in this case, `this' works fine 1396 return make.at(pos).This(c.erasure(types)); 1397 } else { 1398 // need to go via this$n 1399 return makeOuterThis(pos, c); 1400 } 1401 } 1402 1403 /** Construct a tree that represents the outer instance 1404 * <C.this>. Never pick the current `this'. 1405 * @param pos The source code position to be used for the tree. 1406 * @param c The qualifier class. 1407 */ 1408 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) { 1409 List<VarSymbol> ots = outerThisStack; 1410 if (ots.isEmpty()) { 1411 log.error(pos, "no.encl.instance.of.type.in.scope", c); 1412 assert false; 1413 return makeNull(); 1414 } 1415 VarSymbol ot = ots.head; 1416 JCExpression tree = access(make.at(pos).Ident(ot)); 1417 TypeSymbol otc = ot.type.tsym; 1418 while (otc != c) { 1419 do { 1420 ots = ots.tail; 1421 if (ots.isEmpty()) { 1422 log.error(pos, 3388 if (tree.name == names._class) 3389 result = classOf(tree.selected); 3390 else if (tree.name == names._this || tree.name == names._super) 3391 result = makeThis(tree.pos(), tree.selected.type.tsym); 3392 else 3393 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); 3394 } 3395 3396 public void visitLetExpr(LetExpr tree) { 3397 tree.defs = translateVarDefs(tree.defs); 3398 tree.expr = translate(tree.expr, tree.type); 3399 result = tree; 3400 } 3401 3402 // There ought to be nothing to rewrite here; 3403 // we don't generate code. 3404 public void visitAnnotation(JCAnnotation tree) { 3405 result = tree; 3406 } 3407 3408 /************************************************************************** 3409 * main method 3410 *************************************************************************/ 3411 3412 /** Translate a toplevel class and return a list consisting of 3413 * the translated class and translated versions of all inner classes. 3414 * @param env The attribution environment current at the class definition. 3415 * We need this for resolving some additional symbols. 3416 * @param cdef The tree representing the class definition. 3417 */ 3418 public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) { 3419 ListBuffer<JCTree> translated = null; 3420 try { 3421 attrEnv = env; 3422 this.make = make; 3423 endPositions = env.toplevel.endPositions; 3424 currentClass = null; 3425 currentMethodDef = null; 3426 outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl)cdef : null; 3427 outermostMemberDef = null; | 1383 } 1384 //where 1385 JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) { 1386 return access(v, make.at(pos).Ident(v), null, false); 1387 } 1388 1389 /** Construct a tree simulating the expression <C.this>. 1390 * @param pos The source code position to be used for the tree. 1391 * @param c The qualifier class. 1392 */ 1393 JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) { 1394 if (currentClass == c) { 1395 // in this case, `this' works fine 1396 return make.at(pos).This(c.erasure(types)); 1397 } else { 1398 // need to go via this$n 1399 return makeOuterThis(pos, c); 1400 } 1401 } 1402 1403 /** Optionally replace a try statement with an automatic resource management 1404 * (ARM) block. 1405 * @param tree The try statement to inspect. 1406 * @return An ARM block, or the original try block if there are no 1407 * resources to manage. 1408 */ 1409 JCTree makeArmTry(JCTry tree) { 1410 make_at(tree.pos()); 1411 JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0); 1412 if (tree.catchers.isEmpty() && tree.finalizer == null) 1413 result = translate(armBlock); 1414 else 1415 result = translate(make.Try(armBlock, tree.catchers, tree.finalizer)); 1416 return result; 1417 } 1418 1419 private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) { 1420 if (resources.isEmpty()) 1421 return block; 1422 1423 // Add resource declaration or expression to block statements 1424 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); 1425 JCTree resource = resources.head; 1426 JCExpression expr = null; 1427 if (resource instanceof JCVariableDecl) { 1428 JCVariableDecl var = (JCVariableDecl) resource; 1429 expr = make.Ident(var.sym).setType(resource.type); 1430 stats.add(var); 1431 } else { 1432 assert resource instanceof JCExpression; 1433 VarSymbol syntheticArmVar = 1434 new VarSymbol(SYNTHETIC | FINAL, 1435 names.fromString("armVar" + 1436 resource.pos + 1437 target.syntheticNameChar()), 1438 (resource.type.tag == TypeTags.BOT) ? 1439 syms.autoCloseableType : resource.type, 1440 currentMethodSym); 1441 JCVariableDecl syntheticArmVarDecl = 1442 make.VarDef(syntheticArmVar, (JCExpression)resource); 1443 expr = (JCExpression)make.Ident(syntheticArmVar); 1444 stats.add(syntheticArmVarDecl); 1445 } 1446 1447 // Add primaryException declaration 1448 VarSymbol primaryException = 1449 new VarSymbol(SYNTHETIC, 1450 names.fromString("primaryException" + 1451 resource.pos + 1452 target.syntheticNameChar()), 1453 syms.throwableType, 1454 currentMethodSym); 1455 JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull()); 1456 stats.add(primaryExceptionTreeDecl); 1457 1458 // Create catch clause that saves exception and then rethrows it 1459 VarSymbol param = 1460 new VarSymbol(FINAL|SYNTHETIC, 1461 names.fromString("t" + 1462 resource.pos + 1463 target.syntheticNameChar()), 1464 syms.throwableType, 1465 currentMethodSym); 1466 JCVariableDecl paramTree = make.VarDef(param, null); 1467 JCStatement assign = make.Assignment(primaryException, make.Ident(param)); 1468 JCStatement rethrowStat = make.Throw(make.Ident(param)); 1469 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat)); 1470 JCCatch catchClause = make.Catch(paramTree, catchBlock); 1471 1472 int oldPos = make.pos; 1473 make.at(TreeInfo.endPos(block)); 1474 JCBlock finallyClause = makeArmFinallyClause(primaryException, expr); 1475 make.at(oldPos); 1476 JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1), 1477 List.<JCCatch>of(catchClause), 1478 finallyClause); 1479 stats.add(outerTry); 1480 return make.Block(0L, stats.toList()); 1481 } 1482 1483 private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) { 1484 // primaryException.addSuppressedException(catchException); 1485 VarSymbol catchException = 1486 new VarSymbol(0, make.paramName(2), 1487 syms.throwableType, 1488 currentMethodSym); 1489 JCStatement addSuppressionStatement = 1490 make.Exec(makeCall(make.Ident(primaryException), 1491 names.fromString("addSuppressedException"), 1492 List.<JCExpression>of(make.Ident(catchException)))); 1493 1494 // try { resource.close(); } catch (e) { primaryException.addSuppressedException(e); } 1495 JCBlock tryBlock = 1496 make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource))); 1497 JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null); 1498 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement)); 1499 List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock)); 1500 JCTry tryTree = make.Try(tryBlock, catchClauses, null); 1501 1502 // if (resource != null) resourceClose; 1503 JCExpression nullCheck = makeBinary(JCTree.NE, 1504 make.Ident(primaryException), 1505 makeNull()); 1506 JCIf closeIfStatement = make.If(nullCheck, 1507 tryTree, 1508 makeResourceCloseInvocation(resource)); 1509 return make.Block(0L, List.<JCStatement>of(closeIfStatement)); 1510 } 1511 1512 private JCStatement makeResourceCloseInvocation(JCExpression resource) { 1513 // create resource.close() method invocation 1514 JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil()); 1515 return make.Exec(resourceClose); 1516 } 1517 1518 /** Construct a tree that represents the outer instance 1519 * <C.this>. Never pick the current `this'. 1520 * @param pos The source code position to be used for the tree. 1521 * @param c The qualifier class. 1522 */ 1523 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) { 1524 List<VarSymbol> ots = outerThisStack; 1525 if (ots.isEmpty()) { 1526 log.error(pos, "no.encl.instance.of.type.in.scope", c); 1527 assert false; 1528 return makeNull(); 1529 } 1530 VarSymbol ot = ots.head; 1531 JCExpression tree = access(make.at(pos).Ident(ot)); 1532 TypeSymbol otc = ot.type.tsym; 1533 while (otc != c) { 1534 do { 1535 ots = ots.tail; 1536 if (ots.isEmpty()) { 1537 log.error(pos, 3503 if (tree.name == names._class) 3504 result = classOf(tree.selected); 3505 else if (tree.name == names._this || tree.name == names._super) 3506 result = makeThis(tree.pos(), tree.selected.type.tsym); 3507 else 3508 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); 3509 } 3510 3511 public void visitLetExpr(LetExpr tree) { 3512 tree.defs = translateVarDefs(tree.defs); 3513 tree.expr = translate(tree.expr, tree.type); 3514 result = tree; 3515 } 3516 3517 // There ought to be nothing to rewrite here; 3518 // we don't generate code. 3519 public void visitAnnotation(JCAnnotation tree) { 3520 result = tree; 3521 } 3522 3523 @Override 3524 public void visitTry(JCTry tree) { 3525 if (tree.resources.isEmpty()) { 3526 super.visitTry(tree); 3527 } else { 3528 result = makeArmTry(tree); 3529 } 3530 } 3531 3532 /************************************************************************** 3533 * main method 3534 *************************************************************************/ 3535 3536 /** Translate a toplevel class and return a list consisting of 3537 * the translated class and translated versions of all inner classes. 3538 * @param env The attribution environment current at the class definition. 3539 * We need this for resolving some additional symbols. 3540 * @param cdef The tree representing the class definition. 3541 */ 3542 public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) { 3543 ListBuffer<JCTree> translated = null; 3544 try { 3545 attrEnv = env; 3546 this.make = make; 3547 endPositions = env.toplevel.endPositions; 3548 currentClass = null; 3549 currentMethodDef = null; 3550 outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl)cdef : null; 3551 outermostMemberDef = null; |