public JCStatement transform(Tree.TryCatchStatement t) {
Tree.TryClause tryClause = t.getTryClause();
at(tryClause);
JCBlock tryBlock = transform(tryClause.getBlock());
Tree.ResourceList resList = tryClause.getResourceList();
if (resList != null) {
ArrayList<Tree.Resource> resources = new ArrayList<Tree.Resource>(resList.getResources());
Collections.reverse(resources);
for (Tree.Resource res : resources) {
List<JCStatement> stats = List.nil();
Tree.Expression resExpr;
String resVarName;
if (res.getExpression() != null) {
resExpr = res.getExpression();
resVarName = naming.newTemp("try");
} else if (res.getVariable() != null) {
Tree.Variable var = res.getVariable();
resExpr = var.getSpecifierExpression().getExpression();
resVarName = var.getIdentifier().getText();
} else {
throw new BugException(res, "missing resource expression");
}
boolean isDestroyable = typeFact().getDestroyableDeclaration().getType().isSupertypeOf(resExpr.getTypeModel());
ProducedType resVarType = resExpr.getTypeModel();
ProducedType resVarExpectedType = isDestroyable
? typeFact().getDestroyableDeclaration().getType()
: typeFact().getObtainableDeclaration().getType();
// CloseableType $var = resource-expression
JCExpression expr = expressionGen().transformExpression(resExpr);
JCExpression javaType = makeJavaType(resVarType);
JCVariableDecl var = makeVar(FINAL, resVarName, javaType, expr);
stats = stats.append(var);
// $var.open() /// ((Closeable)$var).open()
if (!isDestroyable) {
JCExpression resVar0 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation openCall = make().Apply(null, makeQualIdent(resVar0, "obtain"), List.<JCExpression>nil());
stats = stats.append(make().Exec(openCall));
}
// Exception $tpmex = null;
String innerExTmpVarName = naming.newTemp("ex");
JCExpression innerExType = makeJavaType(typeFact().getThrowableDeclaration().getType(), JT_CATCH);
JCVariableDecl innerExTmpVar = makeVar(innerExTmpVarName, innerExType, makeNull());
stats = stats.append(innerExTmpVar);
// $tmpex = ex;
List<JCStatement> innerCatchStats = List.nil();
Name innerCatchVarName = naming.tempName("ex");
JCAssign exTmpAssign = make().Assign(makeUnquotedIdent(innerExTmpVarName), make().Ident(innerCatchVarName));
innerCatchStats = innerCatchStats.append(make().Exec(exTmpAssign));
// throw ex;
JCThrow innerCatchThrow = make().Throw(make().Ident(innerCatchVarName));
innerCatchStats = innerCatchStats.append(innerCatchThrow);
JCBlock innerCatchBlock = make().Block(0, innerCatchStats);
// $var.close() /// ((Closeable)$var).close()
JCExpression exarg = makeUnquotedIdent(innerExTmpVarName);
JCExpression resVar1 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation closeCall = make().Apply(null, makeQualIdent(resVar1, isDestroyable ? "destroy" : "release"), List.<JCExpression>of(exarg));
JCBlock closeTryBlock = make().Block(0, List.<JCStatement>of(make().Exec(closeCall)));
// try { $var.close() } catch (Exception closex) { $tmpex.addSuppressed(closex); }
Name closeCatchVarName = naming.tempName("closex");
JCExpression closeCatchExType = makeJavaType(typeFact().getThrowableDeclaration().getType(), JT_CATCH);
JCVariableDecl closeCatchVar = make().VarDef(make().Modifiers(Flags.FINAL), closeCatchVarName, closeCatchExType, null);
JCExpression addarg = make().Ident(closeCatchVarName);
JCMethodInvocation addSuppressedCall = make().Apply(null, makeQualIdent(makeUnquotedIdent(innerExTmpVarName), "addSuppressed"), List.<JCExpression>of(addarg));
JCCatch closeCatch = make().Catch(closeCatchVar, make().Block(0, List.<JCStatement>of(make().Exec(addSuppressedCall))));
JCTry closeTry = at(res).Try(closeTryBlock, List.<JCCatch>of(closeCatch), null);
// $var.close() /// ((Closeable)$var).close()
JCExpression exarg2 = makeUnquotedIdent(innerExTmpVarName);
JCExpression resVar2 = expressionGen().applyErasureAndBoxing(makeUnquotedIdent(resVarName), resVarType, true, BoxingStrategy.BOXED, resVarExpectedType);
JCMethodInvocation closeCall2 = make().Apply(null, makeQualIdent(resVar2, isDestroyable ? "destroy" : "release"), List.<JCExpression>of(exarg2));
// if ($tmpex != null) { ... } else { ... }
JCBinary closeCatchCond = make().Binary(JCTree.NE, makeUnquotedIdent(innerExTmpVarName), makeNull());
JCIf closeCatchIf = make().If(closeCatchCond, closeTry, make().Exec(closeCall2));
// try { .... } catch (Exception ex) { $tmpex=ex; throw ex; }
// finally { try { $var.close() } catch (Exception closex) { } }
JCExpression innerCatchExType = makeJavaType(typeFact().getThrowableDeclaration().getType(), JT_CATCH);
JCVariableDecl innerCatchVar = make().VarDef(make().Modifiers(Flags.FINAL), innerCatchVarName, innerCatchExType, null);
JCCatch innerCatch = make().Catch(innerCatchVar, innerCatchBlock);
JCBlock innerFinallyBlock = make().Block(0, List.<JCStatement>of(closeCatchIf));
JCTry innerTry = at(res).Try(tryBlock, List.<JCCatch>of(innerCatch), innerFinallyBlock);
stats = stats.append(innerTry);
tryBlock = at(res).Block(0, stats);
}
}
final List<JCCatch> catches;
if (usePolymorphicCatches(t.getCatchClauses())) {
catches = transformCatchesPolymorphic(t.getCatchClauses());
} else {
catches = transformCatchesIfElseIf(t.getCatchClauses());
}
final JCBlock finallyBlock;
Tree.FinallyClause finallyClause = t.getFinallyClause();
if (finallyClause != null) {
at(finallyClause);
finallyBlock = transform(finallyClause.getBlock());
} else {