Exception transparency - lone throws (no checked exceptions)
Stephen Colebourne
scolebourne at joda.org
Wed Jun 16 20:08:39 PDT 2010
For completeness, I spent a couple of hours tonight implementing
lone-throws and catch-throws. It was pretty easy. The patch is below.
(This patch is based on an old version of the JDK, originally based on
the FCM branch of Kijaro. Applying it to the current head will almost
certainly fail)
Stephen
http://www.jroller.com/scolebourne/entry/exception_transparency_and_lone_throws
Index: langtools/src/share/classes/com/sun/source/tree/CatchTree.java
===================================================================
--- . (revision 109)
+++ . (working copy)
@@ -43,4 +43,5 @@
public interface CatchTree extends Tree {
VariableTree getParameter();
BlockTree getBlock();
+ boolean getCatchThrows(); // LONE-THROWS
}
Index: langtools/src/share/classes/com/sun/source/tree/MethodTree.java
===================================================================
--- . (revision 109)
+++ . (working copy)
@@ -54,6 +54,7 @@
List<? extends TypeParameterTree> getTypeParameters();
List<? extends VariableTree> getParameters();
List<? extends ExpressionTree> getThrows();
+ boolean getThrowAny(); // LONE-THROWS
BlockTree getBody();
Tree getDefaultValue(); // for annotation types
}
Index: langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
===================================================================
--- . (revision 131)
+++ . (working copy)
@@ -657,7 +657,12 @@
for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
if (l.head.getTag() == JCTree.METHODDEF) {
scan(l.head);
- errorUncaught();
+ if (!((JCMethodDecl) l.head).throwAny) { // LONE-THROWS
+ errorUncaught();
+ } else {
+ pendingExits = ListBuffer.lb();
+ System.out.println("Checked to Unchecked");
+ }
}
}
@@ -793,6 +798,8 @@
pendingExits.append(exit);
}
}
+ errorUncaught();
+
} finally {
classDef = classDefPrev;
thrown = thrownPrev;
@@ -1045,6 +1052,7 @@
log.error(l.head.pos(),
"except.already.caught", exc);
} else if (!chk.isUnchecked(l.head.pos(), exc) &&
+ !l.head.catchThrows && // LONE-THROWS
exc.tsym != syms.throwableType.tsym &&
exc.tsym != syms.exceptionType.tsym &&
!chk.intersects(exc, thrownInTry)) {
Index: langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java
===================================================================
--- . (revision 141)
+++ . (working copy)
@@ -442,7 +442,7 @@
syms.noSuchFieldErrorType,
syms.noSymbol),
null),
- make.Block(0, List.<JCStatement>nil())));
+ make.Block(0,
List.<JCStatement>nil()), false)); // LONE-THROWS
for (Map.Entry<VarSymbol,Integer> e : values.entrySet()) {
VarSymbol enumerator = e.getKey();
Integer mappedValue = e.getValue();
@@ -1644,7 +1644,7 @@
// catchBlock := "catch ($catchParam) $rethrowStmt"
JCCatch catchBlock = make.Catch(make.VarDef(catchParam, null),
- rethrowStmt);
+ rethrowStmt, false); // LONE-THROWS
// tryCatch := "try $returnResult $catchBlock"
JCStatement tryCatch = make.Try(returnResult,
Index: langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
===================================================================
--- . (revision 115)
+++ . (working copy)
@@ -436,6 +436,7 @@
List.<JCTypeParameter>nil(),
List.<JCVariableDecl>nil(),
List.<JCExpression>nil(), // thrown
+ false, // LONE-THROWS
null, //make.Block(0,
Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
null);
memberEnter(values, env);
@@ -450,6 +451,7 @@
names.fromString("name"),
make.Type(syms.stringType), null)),
List.<JCExpression>nil(), // thrown
+ false, // LONE-THROWS
null, //make.Block(0,
Tree.emptyList.prepend(make.Return(make.Ident(names._null)))),
null);
memberEnter(valueOf, env);
@@ -465,6 +467,7 @@
List.<JCTypeParameter>nil(),
List.<JCVariableDecl>nil(),
List.<JCExpression>nil(),
+ false, // LONE-THROWS
null,
null);
memberEnter(ordinal, env);
@@ -477,6 +480,7 @@
List.<JCTypeParameter>nil(),
List.<JCVariableDecl>nil(),
List.<JCExpression>nil(),
+ false, // LONE-THROWS
null,
null);
memberEnter(name, env);
@@ -1070,6 +1074,7 @@
make.TypeParams(typarams),
params,
make.Types(thrown),
+ false, // LONE-THROWS
make.Block(0, stats),
null);
return result;
Index: langtools/src/share/classes/com/sun/tools/javac/parser/Parser.java
===================================================================
--- . (revision 131)
+++ . (working copy)
@@ -1933,6 +1933,12 @@
JCCatch catchClause() {
int pos = S.pos();
accept(CATCH);
+ boolean catchThrows = false;
+ if (S.token() == THROWS) {
+ catchThrows = true;
+ accept(THROWS);
+ System.out.println("Found catch throws");
+ }
accept(LPAREN);
JCVariableDecl formal =
variableDeclaratorId(optFinal(Flags.PARAMETER),
qualident(), false); // FCM-MREF
@@ -1938,7 +1944,7 @@
variableDeclaratorId(optFinal(Flags.PARAMETER),
qualident(), false); // FCM-MREF
accept(RPAREN);
JCBlock body = block();
- return F.at(pos).Catch(formal, body);
+ return F.at(pos).Catch(formal, body, catchThrows); // LONE-THROWS
}
/** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
@@ -2674,7 +2680,7 @@
pos = S.pos();
List<JCTree> err = isVoid
?
List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
- List.<JCVariableDecl>nil(),
List.<JCExpression>nil(), null, null)))
+ List.<JCVariableDecl>nil(),
List.<JCExpression>nil(), false, null, null))) // LONE-THROWS
: null;
return List.<JCTree>of(syntaxError(S.pos(),
err, "expected", keywords.token2string(LPAREN)));
}
@@ -2709,9 +2715,15 @@
// throws clause
List<JCExpression> thrown = List.nil();
+ boolean throwAny = false;
if (S.token() == THROWS) {
S.nextToken();
- thrown = qualidentList();
+ if (S.token() == LBRACE) {
+ System.out.println("Found lone-throws");
+ throwAny = true;
+ } else {
+ thrown = qualidentList();
+ }
}
// main body
@@ -2740,7 +2752,7 @@
}
JCMethodDecl result =
toP(F.at(pos).MethodDef(mods, name, type, typarams,
- params, thrown,
+ params, thrown, throwAny,
body, defaultValue));
attach(result, dc);
return result;
Index: langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java
===================================================================
--- . (revision 141)
+++ . (working copy)
@@ -649,6 +649,7 @@
public List<JCTypeParameter> typarams;
public List<JCVariableDecl> params;
public List<JCExpression> thrown;
+ public boolean throwAny; // LONE-THROWS
public JCBlock body;
public JCExpression defaultValue; // for annotation types
public MethodSymbol sym;
@@ -658,6 +659,7 @@
List<JCTypeParameter> typarams,
List<JCVariableDecl> params,
List<JCExpression> thrown,
+ boolean throwAny, // LONE-THROWS
JCBlock body,
JCExpression defaultValue,
MethodSymbol sym)
@@ -668,6 +670,7 @@
this.typarams = typarams;
this.params = params;
this.thrown = thrown;
+ this.throwAny = throwAny; // LONE-THROWS
this.body = body;
this.defaultValue = defaultValue;
this.sym = sym;
@@ -688,6 +691,7 @@
public List<JCExpression> getThrows() {
return thrown;
}
+ public boolean getThrowAny() { return throwAny; }
public JCBlock getBody() { return body; }
public JCTree getDefaultValue() { // for annotation types
return defaultValue;
@@ -1067,9 +1071,11 @@
public static class JCCatch extends JCTree implements CatchTree {
public JCVariableDecl param;
public JCBlock body;
- protected JCCatch(JCVariableDecl param, JCBlock body) {
+ public boolean catchThrows; // LONE-THROWS
+ protected JCCatch(JCVariableDecl param, JCBlock body, boolean
catchThrows) {
this.param = param;
this.body = body;
+ this.catchThrows = catchThrows; // LONE-THROWS
}
@Override
public void accept(Visitor v) { v.visitCatch(this); }
@@ -1077,6 +1083,7 @@
public Kind getKind() { return Kind.CATCH; }
public JCVariableDecl getParameter() { return param; }
public JCBlock getBlock() { return body; }
+ public boolean getCatchThrows() { return catchThrows; } // LONE-THROWS
@Override
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitCatch(this, d);
@@ -2233,6 +2240,7 @@
List<JCTypeParameter> typarams,
List<JCVariableDecl> params,
List<JCExpression> thrown,
+ boolean throwAny, // LONE-THROWS
JCBlock body,
JCExpression defaultValue);
JCVariableDecl VarDef(JCModifiers mods,
@@ -2253,7 +2261,7 @@
JCCase Case(JCExpression pat, List<JCStatement> stats);
JCSynchronized Synchronized(JCExpression lock, JCBlock body);
JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer);
- JCCatch Catch(JCVariableDecl param, JCBlock body);
+ JCCatch Catch(JCVariableDecl param, JCBlock body, boolean catchThrows);
JCConditional Conditional(JCExpression cond,
JCExpression thenpart,
JCExpression elsepart);
Index: langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java
===================================================================
--- . (revision 131)
+++ . (working copy)
@@ -461,7 +461,9 @@
print(")");
if (tree.thrown.nonEmpty()) {
print(" throws ");
- printExprs(tree.thrown);
+ if (!tree.throwAny) {
+ printExprs(tree.thrown); // LONE-THROWS
+ }
}
if (tree.body != null) {
print(" ");
@@ -683,7 +685,7 @@
public void visitCatch(JCCatch tree) {
try {
- print(" catch (");
+ print(tree.catchThrows ? " catch throws (" : " catch (");
// LONE-THROWS
printExpr(tree.param);
print(") ");
printStat(tree.body);
Index: langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java
===================================================================
--- . (revision 131)
+++ . (working copy)
@@ -133,7 +133,7 @@
JCCatch t = (JCCatch) node;
JCVariableDecl param = copy(t.param, p);
JCBlock body = copy(t.body, p);
- return M.at(t.pos).Catch(param, body);
+ return M.at(t.pos).Catch(param, body, t.catchThrows); // LONE-THROWS
}
public JCTree visitClass(ClassTree node, P p) {
@@ -241,7 +241,7 @@
List<JCExpression> thrown = copy(t.thrown, p);
JCBlock body = copy(t.body, p);
JCExpression defaultValue = copy(t.defaultValue, p);
- return M.at(t.pos).MethodDef(mods, t.name, restype, typarams,
params, thrown, body, defaultValue);
+ return M.at(t.pos).MethodDef(mods, t.name, restype, typarams,
params, thrown, t.throwAny, body, defaultValue); // LONE-THROWS
}
public JCTree visitMethodInvocation(MethodInvocationTree node, P p) {
Index: langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java
===================================================================
--- . (revision 131)
+++ . (working copy)
@@ -171,6 +171,7 @@
List<JCTypeParameter> typarams,
List<JCVariableDecl> params,
List<JCExpression> thrown,
+ boolean throwAny, // LONE-THROWS
JCBlock body,
JCExpression defaultValue)
{
@@ -180,6 +181,7 @@
typarams,
params,
thrown,
+ throwAny, // LONE-THROWS
body,
defaultValue,
null);
@@ -263,8 +265,8 @@
return tree;
}
- public JCCatch Catch(JCVariableDecl param, JCBlock body) {
- JCCatch tree = new JCCatch(param, body);
+ public JCCatch Catch(JCVariableDecl param, JCBlock body, boolean
catchThrows) { // LONE-THROWS
+ JCCatch tree = new JCCatch(param, body, catchThrows);
tree.pos = pos;
return tree;
}
@@ -801,6 +803,7 @@
TypeParams(mtype.getTypeArguments()),
Params(mtype.getParameterTypes(), m),
Types(mtype.getThrownTypes()),
+ false, // LONE-THROWS
body,
null,
m).setPos(pos).setType(mtype);
More information about the lambda-dev
mailing list