Implement "try..catch..finally" and "throw" statements, and array creation with bounds.
Enable "maven test".
diff --git a/pom.xml b/pom.xml
index 25a3a26..ad595c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -106,6 +106,16 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.15</version>
+ <configuration>
+ <includes>
+ <include>net/hydromatic/linq4j/test/Linq4jSuite.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/CatchBlock.java b/src/main/java/net/hydromatic/linq4j/expressions/CatchBlock.java
index 30ae279..ee7f54c 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/CatchBlock.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/CatchBlock.java
@@ -21,6 +21,14 @@
* Represents a catch statement in a try block.
*/
public class CatchBlock {
+ public final ParameterExpression parameter;
+ public final Statement body;
+
+ public CatchBlock(ParameterExpression parameter,
+ Statement body) {
+ this.parameter = parameter;
+ this.body = body;
+ }
}
// End CatchBlock.java
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/ExpressionWriter.java b/src/main/java/net/hydromatic/linq4j/expressions/ExpressionWriter.java
index d991530..3a12e33 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/ExpressionWriter.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/ExpressionWriter.java
@@ -188,6 +188,13 @@
return this;
}
+ public void backUp() {
+ if (buf.lastIndexOf("\n") == buf.length() - 1) {
+ buf.delete(buf.length() - 1, buf.length());
+ indentPending = false;
+ }
+ }
+
private static class Indent extends ArrayList<String> {
public Indent(int initialCapacity) {
super(initialCapacity);
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/Expressions.java b/src/main/java/net/hydromatic/linq4j/expressions/Expressions.java
index 6c2db22..7a12eac 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/Expressions.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/Expressions.java
@@ -444,36 +444,9 @@
* reference to the caught Exception object for use in the handler
* body.
*/
- public static CatchBlock catch_(ParameterExpression expression0,
- Expression expression1) {
- throw Extensions.todo();
- }
-
- /**
- * Creates a CatchBlock representing a catch statement.
- */
- public static CatchBlock catch_(Type type, Expression expression) {
- throw Extensions.todo();
- }
-
- /**
- * Creates a CatchBlock representing a catch statement with an
- * Exception filter and a reference to the caught Exception
- * object.
- */
- public static CatchBlock catch_(ParameterExpression expression0,
- Expression expression1, Expression expression2) {
- throw Extensions.todo();
- }
-
- /**
- * Creates a CatchBlock representing a catch statement with an
- * Exception filter but no reference to the caught Exception
- * object.
- */
- public static CatchBlock catch_(Type type, Expression expression0,
- Expression expression1) {
- throw Extensions.todo();
+ public static CatchBlock catch_(ParameterExpression parameter,
+ Statement statement) {
+ return new CatchBlock(parameter, statement);
}
/**
@@ -1811,8 +1784,13 @@
*/
public static BinaryExpression multiplyAssignChecked(Expression left,
Expression right, Method method, LambdaExpression lambdaExpression) {
- return makeBinary(ExpressionType.MultiplyAssignChecked, left, right, false,
- method, lambdaExpression);
+ return makeBinary(
+ ExpressionType.MultiplyAssignChecked,
+ left,
+ right,
+ false,
+ method,
+ lambdaExpression);
}
/**
@@ -1986,18 +1964,9 @@
* Creates a NewArrayExpression that represents creating an array
* that has a specified rank.
*/
- public static NewArrayExpression newArrayBounds(Type type,
- Iterable<? extends Expression> expressions) {
- throw Extensions.todo();
- }
-
- /**
- * Creates a NewArrayExpression that represents creating an array
- * that has a specified rank, using varargs.
- */
- public static NewArrayExpression newArrayBounds(Type type,
- Expression... expressions) {
- return newArrayBounds(type, toList(expressions));
+ public static NewArrayExpression newArrayBounds(Type type, int dimension,
+ Expression bound) {
+ return new NewArrayExpression(type, dimension, bound, null);
}
/**
@@ -2009,7 +1978,7 @@
*/
public static NewArrayExpression newArrayInit(Type type,
Iterable<? extends Expression> expressions) {
- return new NewArrayExpression(type, toList(expressions));
+ return new NewArrayExpression(type, 1, null, toList(expressions));
}
/**
@@ -2021,7 +1990,31 @@
*/
public static NewArrayExpression newArrayInit(Type type,
Expression... expressions) {
- return newArrayInit(type, toList(expressions));
+ return new NewArrayExpression(type, 1, null, toList(expressions));
+ }
+
+ /**
+ * Creates a NewArrayExpression that represents creating a
+ * n-dimensional array and initializing it from a list of
+ * elements.
+ *
+ * @param type Element type of the array.
+ */
+ public static NewArrayExpression newArrayInit(Type type, int dimension,
+ Iterable<? extends Expression> expressions) {
+ return new NewArrayExpression(type, dimension, null, toList(expressions));
+ }
+
+ /**
+ * Creates a NewArrayExpression that represents creating an
+ * n-dimensional array and initializing it from a list of
+ * elements, using varargs.
+ *
+ * @param type Element type of the array.
+ */
+ public static NewArrayExpression newArrayInit(Type type, int dimension,
+ Expression... expressions) {
+ return new NewArrayExpression(type, dimension, null, toList(expressions));
}
/**
@@ -2732,19 +2725,10 @@
}
/**
- * Creates a UnaryExpression that represents a throwing of an
- * exception.
+ * Creates a statement that represents the throwing of an exception.
*/
- public static UnaryExpression throw_(Expression expression) {
- throw Extensions.todo();
- }
-
- /**
- * Creates a UnaryExpression that represents a throwing of an
- * exception with a given type.
- */
- public static UnaryExpression throw_(Expression expression, Type type) {
- throw Extensions.todo();
+ public static ThrowStatement throw_(Expression expression) {
+ return new ThrowStatement(expression);
}
/**
@@ -2752,52 +2736,46 @@
* number of catch statements and neither a fault nor finally
* block.
*/
- public static TryStatement tryCatch(Expression body,
+ public static TryStatement tryCatch(Statement body,
+ Iterable<? extends CatchBlock> handlers) {
+ return new TryStatement(body, toList(handlers), null);
+ }
+
+ /**
+ * Creates a TryExpression representing a try block with any
+ * number of catch statements and neither a fault nor finally
+ * block, with varargs.
+ */
+ public static TryStatement tryCatch(Statement body,
CatchBlock... handlers) {
- throw Extensions.todo();
+ return new TryStatement(body, toList(handlers), null);
}
/**
* Creates a TryExpression representing a try block with any
* number of catch statements and a finally block.
*/
- public static TryStatement tryCatchFinally(Expression body,
- CatchBlock... handlers) {
- throw Extensions.todo();
+ public static TryStatement tryCatchFinally(Statement body,
+ Iterable<? extends CatchBlock> handlers, Statement finally_) {
+ return new TryStatement(body, toList(handlers), finally_);
}
/**
- * Creates a TryExpression representing a try block with a fault
- * block and no catch statements.
+ * Creates a TryExpression representing a try block with any
+ * number of catch statements and a finally block, with varargs.
*/
- public static TryStatement tryFault(Expression body, Expression fault) {
- throw Extensions.todo();
+ public static TryStatement tryCatchFinally(Statement body, Statement finally_,
+ CatchBlock... handlers) {
+ return new TryStatement(body, toList(handlers), finally_);
}
/**
* Creates a TryExpression representing a try block with a
* finally block and no catch statements.
*/
- public static TryStatement tryFinally(Expression body, Expression fault) {
- throw Extensions.todo();
- }
-
- /**
- * Creates a Type object that represents a generic System.Action
- * delegate type that has specific type arguments.
- */
- public static boolean tryGetActionType(Class[] typeArgs,
- Class[] outActionType) {
- throw Extensions.todo();
- }
-
- /**
- * Creates a Type object that represents a generic System.Func
- * delegate type that has specific type arguments. The last type
- * argument specifies the return type of the created delegate.
- */
- public static boolean tryGetFuncType(Class[] typeArgs, Class[] outFuncType) {
- throw Extensions.todo();
+ public static TryStatement tryFinally(Statement body, Statement finally_) {
+ return new TryStatement(body, Collections.<CatchBlock>emptyList(),
+ finally_);
}
/**
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/FunctionExpression.java b/src/main/java/net/hydromatic/linq4j/expressions/FunctionExpression.java
index 45892a5..09bb186 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/FunctionExpression.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/FunctionExpression.java
@@ -124,16 +124,14 @@
List<String> boxBridgeArgs = new ArrayList<String>();
for (ParameterExpression parameterExpression : parameterList) {
final Type parameterType = parameterExpression.getType();
- final String parameterTypeName = Types.className(parameterType);
- final String parameterBoxTypeName = Types.boxClassName(parameterType);
- params.add(parameterTypeName + " " + parameterExpression.name);
-
- bridgeParams.add("Object " + parameterExpression.name);
+ final Type parameterBoxType = Types.box(parameterType);
+ final String parameterBoxTypeName = Types.className(parameterBoxType);
+ params.add(parameterExpression.declString());
+ bridgeParams.add(parameterExpression.declString(Object.class));
bridgeArgs.add("(" + parameterBoxTypeName + ") "
+ parameterExpression.name);
- boxBridgeParams.add(parameterBoxTypeName + " "
- + parameterExpression.name);
+ boxBridgeParams.add(parameterExpression.declString(parameterBoxType));
boxBridgeArgs.add(parameterExpression.name
+ (Primitive.is(parameterType)
? "." + Primitive.of(parameterType).primitiveName + "Value()"
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/MethodDeclaration.java b/src/main/java/net/hydromatic/linq4j/expressions/MethodDeclaration.java
index 306d46e..1d062db 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/MethodDeclaration.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/MethodDeclaration.java
@@ -57,13 +57,7 @@
writer.append(resultType).append(' ').append(name).list("(", ", ", ")",
new AbstractList<String>() {
public String get(int index) {
- ParameterExpression parameter = parameters.get(index);
- final String modifiers = Modifier.toString(parameter.modifier);
- return modifiers
- + (modifiers.isEmpty() ? "" : " ")
- + Types.className(parameter.getType())
- + " "
- + parameter.name;
+ return parameters.get(index).declString();
}
public int size() {
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/NewArrayExpression.java b/src/main/java/net/hydromatic/linq4j/expressions/NewArrayExpression.java
index 1cd3fcc..2b42a5f 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/NewArrayExpression.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/NewArrayExpression.java
@@ -25,23 +25,41 @@
* new array.
*/
public class NewArrayExpression extends Expression {
+ public final int dimension;
+ public final Expression bound;
public final List<Expression> expressions;
- public NewArrayExpression(Type type, List<Expression> expressions) {
- super(ExpressionType.NewArrayInit, Types.arrayType(type));
+ public NewArrayExpression(Type type, int dimension, Expression bound,
+ List<Expression> expressions) {
+ super(ExpressionType.NewArrayInit, Types.arrayType(type, dimension));
+ this.dimension = dimension;
+ this.bound = bound;
this.expressions = expressions;
}
@Override
public Expression accept(Visitor visitor) {
- List<Expression> expressions = Expressions.acceptExpressions(
- this.expressions, visitor);
- return visitor.visit(this, expressions);
+ List<Expression> expressions =
+ this.expressions == null
+ ? null
+ : Expressions.acceptExpressions(this.expressions, visitor);
+ Expression bound = Expressions.accept(this.bound, visitor);
+ return visitor.visit(this, dimension, bound, expressions);
}
@Override
void accept(ExpressionWriter writer, int lprec, int rprec) {
- writer.append("new ").append(type).list(" {\n", ",\n", "}", expressions);
+ writer.append("new ").append(Types.getComponentTypeN(type));
+ for (int i = 0; i < dimension; i++) {
+ if (i == 0 && bound != null) {
+ writer.append('[').append(bound).append(']');
+ } else {
+ writer.append("[]");
+ }
+ }
+ if (expressions != null) {
+ writer.list(" {\n", ",\n", "}", expressions);
+ }
}
}
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/ParameterExpression.java b/src/main/java/net/hydromatic/linq4j/expressions/ParameterExpression.java
index 81bbe56..1fe6a50 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/ParameterExpression.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/ParameterExpression.java
@@ -17,6 +17,7 @@
*/
package net.hydromatic.linq4j.expressions;
+import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
/**
@@ -51,6 +52,19 @@
void accept(ExpressionWriter writer, int lprec, int rprec) {
writer.append(name);
}
+
+ String declString() {
+ return declString(type);
+ }
+
+ String declString(Type type) {
+ final String modifiers = Modifier.toString(modifier);
+ return modifiers
+ + (modifiers.isEmpty() ? "" : " ")
+ + Types.className(type)
+ + " "
+ + name;
+ }
}
// End ParameterExpression.java
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/ThrowStatement.java b/src/main/java/net/hydromatic/linq4j/expressions/ThrowStatement.java
new file mode 100644
index 0000000..1129295
--- /dev/null
+++ b/src/main/java/net/hydromatic/linq4j/expressions/ThrowStatement.java
@@ -0,0 +1,42 @@
+/*
+// Licensed to Julian Hyde under one or more contributor license
+// agreements. See the NOTICE file distributed with this work for
+// additional information regarding copyright ownership.
+//
+// Julian Hyde licenses this file to you under the Apache License,
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+package net.hydromatic.linq4j.expressions;
+
+/**
+ * Represents a {@code throw} statement.
+ */
+public class ThrowStatement extends Statement {
+ public final Expression expression;
+
+ public ThrowStatement(Expression expression) {
+ super(ExpressionType.Throw, Void.TYPE);
+ this.expression = expression;
+ }
+
+ @Override
+ public Statement accept(Visitor visitor) {
+ return visitor.visit(this);
+ }
+
+ @Override
+ void accept0(ExpressionWriter writer) {
+ writer.append("throw ").append(expression).append(';').newlineAndIndent();
+ }
+}
+
+// End ThrowStatement.java
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/TryStatement.java b/src/main/java/net/hydromatic/linq4j/expressions/TryStatement.java
index 35dac9f..4624956 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/TryStatement.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/TryStatement.java
@@ -17,18 +17,42 @@
*/
package net.hydromatic.linq4j.expressions;
+import java.util.List;
+
/**
- * Represents a try/catch/finally/fault block.
+ * Represents a {@code try ... catch ... finally} block.
*/
public class TryStatement extends Statement {
- public TryStatement(ExpressionType nodeType) {
- super(nodeType, Void.TYPE);
+ public final Statement body;
+ public final List<CatchBlock> catchBlocks;
+ public final Statement finally_;
+
+ public TryStatement(Statement body, List<CatchBlock> catchBlocks,
+ Statement finally_) {
+ super(ExpressionType.Try, body.getType());
+ this.body = body;
+ this.catchBlocks = catchBlocks;
+ this.finally_ = finally_;
}
@Override
public Statement accept(Visitor visitor) {
return visitor.visit(this);
}
+
+ @Override
+ void accept0(ExpressionWriter writer) {
+ writer.append("try ").append(Blocks.toBlock(body));
+ for (CatchBlock catchBlock : catchBlocks) {
+ writer.backUp();
+ writer.append(" catch (").append(catchBlock.parameter.declString())
+ .append(") ").append(Blocks.toBlock(catchBlock.body));
+ }
+ if (finally_ != null) {
+ writer.backUp();
+ writer.append(" finally ").append(Blocks.toBlock(finally_));
+ }
+ }
}
// End TryStatement.java
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/Types.java b/src/main/java/net/hydromatic/linq4j/expressions/Types.java
index 8951e04..1e5e07c 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/Types.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/Types.java
@@ -198,6 +198,16 @@
return null; // not an array type
}
+ static Type getComponentTypeN(Type type) {
+ for (;;) {
+ final Type oldType = type;
+ type = getComponentType(type);
+ if (type == null) {
+ return oldType;
+ }
+ }
+ }
+
/**
* Boxes a type, if it is primitive, and returns the type name.
* The type is abbreviated if it is in the "java.lang" package.
@@ -507,6 +517,13 @@
return Array.newInstance(toClass(type), 0).getClass();
}
+ static Type arrayType(Type type, int dimension) {
+ for (int i = 0; i < dimension; i++) {
+ type = arrayType(type);
+ }
+ return type;
+ }
+
static Type arrayType(Type type) {
if (type instanceof Class) {
Class clazz = (Class) type;
diff --git a/src/main/java/net/hydromatic/linq4j/expressions/Visitor.java b/src/main/java/net/hydromatic/linq4j/expressions/Visitor.java
index 8e05276..e08ef7e 100644
--- a/src/main/java/net/hydromatic/linq4j/expressions/Visitor.java
+++ b/src/main/java/net/hydromatic/linq4j/expressions/Visitor.java
@@ -58,6 +58,10 @@
return forStatement;
}
+ public Statement visit(ThrowStatement throwStatement) {
+ return throwStatement;
+ }
+
public DeclarationStatement visit(DeclarationStatement declarationStatement,
ParameterExpression parameter, Expression initializer) {
return declarationStatement.parameter == parameter
@@ -143,12 +147,21 @@
return invocationExpression;
}
- public Expression visit(NewArrayExpression newArrayExpression,
- List<Expression> expressions) {
- return expressions.equals(newArrayExpression.expressions)
+ static <T> boolean eq(T t0, T t1) {
+ return t0 == t1 || t0 != null && t1 != null && t0.equals(t1);
+ }
+
+ public Expression visit(NewArrayExpression newArrayExpression, int dimension,
+ Expression bound, List<Expression> expressions) {
+ return eq(expressions, newArrayExpression.expressions)
+ && eq(bound, newArrayExpression.bound)
? newArrayExpression
- : Expressions.newArrayInit(Types.getComponentType(
- newArrayExpression.type), expressions);
+ : expressions == null
+ ? Expressions.newArrayBounds(
+ Types.getComponentTypeN(newArrayExpression.type), dimension, bound)
+ : Expressions.newArrayInit(
+ Types.getComponentTypeN(newArrayExpression.type),
+ dimension, expressions);
}
public Expression visit(ListInitExpression listInitExpression) {
diff --git a/src/test/java/net/hydromatic/linq4j/function/FunctionTest.java b/src/test/java/net/hydromatic/linq4j/function/FunctionTest.java
index db50930..50e2551 100644
--- a/src/test/java/net/hydromatic/linq4j/function/FunctionTest.java
+++ b/src/test/java/net/hydromatic/linq4j/function/FunctionTest.java
@@ -17,16 +17,11 @@
*/
package net.hydromatic.linq4j.function;
-import net.hydromatic.linq4j.expressions.Types;
-
import org.junit.Assert;
import org.junit.Test;
import java.util.*;
-import static org.junit.Assert.assertEquals;
-
-
/**
* Test for {@link Functions}.
*/
diff --git a/src/test/java/net/hydromatic/linq4j/test/ExpressionTest.java b/src/test/java/net/hydromatic/linq4j/test/ExpressionTest.java
index 03f5a6c..4f1015a 100644
--- a/src/test/java/net/hydromatic/linq4j/test/ExpressionTest.java
+++ b/src/test/java/net/hydromatic/linq4j/test/ExpressionTest.java
@@ -332,6 +332,7 @@
paramX, "length", Collections.<Expression>emptyList()),
Arrays.asList(paramX))));
+ // 1-dimensional array with initializer
assertEquals(
"new String[] {\n"
+ " \"foo\",\n"
@@ -340,10 +341,48 @@
Expressions.toString(
Expressions.newArrayInit(
String.class,
- Arrays.<Expression>asList(
- Expressions.constant("foo"),
- Expressions.constant(null),
- Expressions.constant("bar\"baz")))));
+ Expressions.constant("foo"),
+ Expressions.constant(null),
+ Expressions.constant("bar\"baz"))));
+
+ // 2-dimensional array with initializer
+ assertEquals(
+ "new String[][] {\n"
+ + " new String[] {\n"
+ + " \"foo\",\n"
+ + " \"bar\"},\n"
+ + " null,\n"
+ + " new String[] {\n"
+ + " null}}",
+ Expressions.toString(
+ Expressions.newArrayInit(
+ String.class,
+ 2,
+ Expressions.constant(new String[] {"foo", "bar"}),
+ Expressions.constant(null),
+ Expressions.constant(new String[] {null}))));
+
+ // 1-dimensional array
+ assertEquals(
+ "new String[x + 1]",
+ Expressions.toString(
+ Expressions.newArrayBounds(
+ String.class,
+ 1,
+ Expressions.add(
+ Expressions.parameter(0, int.class, "x"),
+ Expressions.constant(1)))));
+
+ // 3-dimensional array
+ assertEquals(
+ "new String[x + 1][][]",
+ Expressions.toString(
+ Expressions.newArrayBounds(
+ String.class,
+ 3,
+ Expressions.add(
+ Expressions.parameter(0, int.class, "x"),
+ Expressions.constant(1)))));
assertEquals(
"(int) ((String) (Object) \"foo\").length()",
@@ -652,6 +691,95 @@
Expressions.toString(node));
}
+ @Test public void testWriteTryCatchFinally() {
+ final ParameterExpression cce_ =
+ Expressions.parameter(Modifier.FINAL, ClassCastException.class, "cce");
+ final ParameterExpression re_ =
+ Expressions.parameter(0, RuntimeException.class, "re");
+ Node node =
+ Expressions.tryCatchFinally(
+ Expressions.block(
+ Expressions.return_(null,
+ Expressions.call(
+ Expressions.constant("foo"),
+ "length"))),
+ Expressions.statement(
+ Expressions.call(
+ Expressions.constant("foo"),
+ "toUpperCase")),
+ Expressions.catch_(cce_,
+ Expressions.return_(null, Expressions.constant(null))),
+ Expressions.catch_(re_,
+ Expressions.throw_(
+ Expressions.new_(IndexOutOfBoundsException.class))));
+ assertEquals(
+ "try {\n"
+ + " return \"foo\".length();\n"
+ + "} catch (final ClassCastException cce) {\n"
+ + " return null;\n"
+ + "} catch (RuntimeException re) {\n"
+ + " throw new IndexOutOfBoundsException();\n"
+ + "} finally {\n"
+ + " \"foo\".toUpperCase();\n"
+ + "}\n",
+ Expressions.toString(node));
+ }
+
+ @Test public void testWriteTryFinally() {
+ final ParameterExpression cce_ =
+ Expressions.parameter(Modifier.FINAL, ClassCastException.class, "cce");
+ final ParameterExpression re_ =
+ Expressions.parameter(0, RuntimeException.class, "re");
+ Node node =
+ Expressions.ifThen(
+ Expressions.constant(true),
+ Expressions.tryFinally(
+ Expressions.block(
+ Expressions.return_(null,
+ Expressions.call(
+ Expressions.constant("foo"),
+ "length"))),
+ Expressions.statement(
+ Expressions.call(
+ Expressions.constant("foo"),
+ "toUpperCase"))));
+ assertEquals(
+ "if (true) {\n"
+ + " try {\n"
+ + " return \"foo\".length();\n"
+ + " } finally {\n"
+ + " \"foo\".toUpperCase();\n"
+ + " }\n"
+ + "}\n",
+ Expressions.toString(node));
+ }
+
+ @Test public void testWriteTryCatch() {
+ final ParameterExpression cce_ =
+ Expressions.parameter(Modifier.FINAL, ClassCastException.class, "cce");
+ final ParameterExpression re_ =
+ Expressions.parameter(0, RuntimeException.class, "re");
+ Node node =
+ Expressions.tryCatch(
+ Expressions.block(
+ Expressions.return_(null,
+ Expressions.call(Expressions.constant("foo"), "length"))),
+ Expressions.catch_(cce_,
+ Expressions.return_(null, Expressions.constant(null))),
+ Expressions.catch_(re_,
+ Expressions.return_(null,
+ Expressions.call(re_, "toString"))));
+ assertEquals(
+ "try {\n"
+ + " return \"foo\".length();\n"
+ + "} catch (final ClassCastException cce) {\n"
+ + " return null;\n"
+ + "} catch (RuntimeException re) {\n"
+ + " return re.toString();\n"
+ + "}\n",
+ Expressions.toString(node));
+ }
+
@Test public void testType() {
// Type of ternary operator is the gcd of its arguments.
assertEquals(