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 makeTry(JCTry tree) { 1410 if (tree.resources.isEmpty()) { 1411 return tree; 1412 } 1413 make_at(tree.pos()); 1414 JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0); 1415 if (tree.catchers.isEmpty() && tree.finalizer == null) 1416 result = translate(armBlock); 1417 else 1418 result = translate(make.Try(armBlock, tree.catchers, tree.finalizer)); 1419 return result; 1420 } 1421 1422 private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) { 1423 if (resources.isEmpty()) 1424 return block; 1425 1426 // Add resource declaration or expression to block statements 1427 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); 1428 JCTree resource = resources.head; 1429 JCExpression expr = null; 1430 if (resource instanceof JCVariableDecl) { 1431 JCVariableDecl var = (JCVariableDecl) resource; 1432 expr = make.Ident(var.sym); 1433 stats.add(var); 1434 } else { 1435 assert resource instanceof JCExpression; 1436 VarSymbol syntheticArmVar = 1437 new VarSymbol(SYNTHETIC | FINAL, 1438 names.fromString("armVar" + 1439 resource.pos + 1440 target.syntheticNameChar()), 1441 resource.type, 1442 currentMethodSym); 1443 JCVariableDecl syntheticArmVarDecl = make.VarDef(syntheticArmVar, (JCExpression)resource); 1444 expr = (JCExpression)make.Ident(syntheticArmVar); 1445 stats.add(syntheticArmVarDecl); 1446 } 1447 1448 // Add primaryException declaration 1449 VarSymbol primaryException = 1450 new VarSymbol(SYNTHETIC, 1451 names.fromString("primaryException" + 1452 resource.pos + 1453 target.syntheticNameChar()), 1454 syms.throwableType, 1455 currentMethodSym); 1456 JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull()); 1457 stats.add(primaryExceptionTreeDecl); 1458 1459 // Create catch clause that saves exception and then rethrows it 1460 VarSymbol param = 1461 new VarSymbol(FINAL|SYNTHETIC, 1462 names.fromString("t" + 1463 resource.pos + 1464 target.syntheticNameChar()), 1465 syms.throwableType, 1466 currentMethodSym); 1467 JCVariableDecl paramTree = make.VarDef(param, null); 1468 JCStatement assign = make.Assignment(primaryException, make.Ident(param)); 1469 JCStatement rethrowStat = make.Throw(make.Ident(param)); 1470 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat)); 1471 JCCatch catchClause = make.Catch(paramTree, catchBlock); 1472 1473 int oldPos = make.pos; 1474 make.at(TreeInfo.endPos(block)); 1475 JCBlock finallyClause = makeArmFinallyClause(primaryException, expr); 1476 make.at(oldPos); 1477 JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1), 1478 List.<JCCatch>of(catchClause), 1479 finallyClause); 1480 stats.add(outerTry); 1481 return make.Block(0L, stats.toList()); 1482 } 1483 1484 private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) { 1485 // primaryException.addSuppressedException(catchException); 1486 VarSymbol catchException = 1487 new VarSymbol(0, make.paramName(2), 1488 syms.throwableType, 1489 currentMethodSym); 1490 JCStatement addSuppressionStatement = 1491 make.Exec(makeCall(make.Ident(primaryException), 1492 names.fromString("addSuppressedException"), 1493 List.<JCExpression>of(make.Ident(catchException)))); 1494 1495 // try { resource.close(); } catch (e) { primaryException.addSuppressedException(e); } 1496 JCBlock tryBlock = 1497 make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource))); 1498 JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null); 1499 JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement)); 1500 List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock)); 1501 JCTry tryTree = make.Try(tryBlock, catchClauses, null); 1502 1503 // if (resource != null) resourceClose; 1504 JCExpression nullCheck = makeBinary(JCTree.NE, 1505 make.Ident(primaryException), 1506 makeNull()); 1507 JCIf closeIfStatement = make.If(nullCheck, 1508 tryTree, 1509 makeResourceCloseInvocation(resource)); 1510 return make.Block(0L, List.<JCStatement>of(closeIfStatement)); 1511 } 1512 1513 private JCStatement makeResourceCloseInvocation(JCExpression resource) { 1514 // create resource.close() method invocation 1515 Type autoCloseableType = types.asSuper(resource.type, syms.autoCloseableType.tsym); 1516 Symbol closeMethod = autoCloseableType.tsym.members().lookup(names.close).sym; 1517 JCExpression closeInvocation = make.Select(resource, closeMethod); 1518 JCMethodInvocation resourceClose = make.Apply(List.<JCExpression>nil(), 1519 closeInvocation, 1520 List.<JCExpression>nil()); 1521 resourceClose.type = closeMethod.type.getReturnType(); 1522 return make.Exec(resourceClose); 1523 } 1524 1525 /** Construct a tree that represents the outer instance 1526 * <C.this>. Never pick the current `this'. 1527 * @param pos The source code position to be used for the tree. 1528 * @param c The qualifier class. 1529 */ 1530 JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) { 1531 List<VarSymbol> ots = outerThisStack; 1532 if (ots.isEmpty()) { 1533 log.error(pos, "no.encl.instance.of.type.in.scope", c); 1534 assert false; 1535 return makeNull(); 1536 } 1537 VarSymbol ot = ots.head; 1538 JCExpression tree = access(make.at(pos).Ident(ot)); 1539 TypeSymbol otc = ot.type.tsym; 1540 while (otc != c) { 1541 do { 1542 ots = ots.tail; 1543 if (ots.isEmpty()) { 1544 log.error(pos, 3510 if (tree.name == names._class) 3511 result = classOf(tree.selected); 3512 else if (tree.name == names._this || tree.name == names._super) 3513 result = makeThis(tree.pos(), tree.selected.type.tsym); 3514 else 3515 result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); 3516 } 3517 3518 public void visitLetExpr(LetExpr tree) { 3519 tree.defs = translateVarDefs(tree.defs); 3520 tree.expr = translate(tree.expr, tree.type); 3521 result = tree; 3522 } 3523 3524 // There ought to be nothing to rewrite here; 3525 // we don't generate code. 3526 public void visitAnnotation(JCAnnotation tree) { 3527 result = tree; 3528 } 3529 3530 @Override 3531 public void visitTry(JCTry tree) { 3532 super.visitTry(tree); 3533 result = makeTry(tree); 3534 } 3535 3536 /************************************************************************** 3537 * main method 3538 *************************************************************************/ 3539 3540 /** Translate a toplevel class and return a list consisting of 3541 * the translated class and translated versions of all inner classes. 3542 * @param env The attribution environment current at the class definition. 3543 * We need this for resolving some additional symbols. 3544 * @param cdef The tree representing the class definition. 3545 */ 3546 public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) { 3547 ListBuffer<JCTree> translated = null; 3548 try { 3549 attrEnv = env; 3550 this.make = make; 3551 endPositions = env.toplevel.endPositions; 3552 currentClass = null; 3553 currentMethodDef = null; 3554 outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl)cdef : null; 3555 outermostMemberDef = null; |