LUCENE-6965: Changed exception handling in JavascriptCompiler using "sneaky rethrow"

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1723642 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Uwe Schindler 2016-01-07 23:38:14 +00:00
parent 5bfbcfdfc9
commit a46d5535cb
3 changed files with 20 additions and 27 deletions

View File

@ -227,8 +227,8 @@ Other
ctor inside InvocationTargetException. (Uwe Schindler) ctor inside InvocationTargetException. (Uwe Schindler)
* LUCENE-6965: Expression's JavascriptCompiler now throw ParseException * LUCENE-6965: Expression's JavascriptCompiler now throw ParseException
with bad function names or bad arity instead of IllegalArgumentException with bad function names or bad arity instead of IllegalArgumentException.
(Tomás Fernández Löbbe) (Tomás Fernández Löbbe, Uwe Schindler, Ryan Ernst)
* LUCENE-6964: String-based signatures in JavascriptCompiler replaced * LUCENE-6964: String-based signatures in JavascriptCompiler replaced
with better compile-time-checked MethodType; generated class files with better compile-time-checked MethodType; generated class files

View File

@ -249,7 +249,7 @@ public final class JavascriptCompiler {
EVALUATE_METHOD, null, null, classWriter); EVALUATE_METHOD, null, null, classWriter);
// to completely hide the ANTLR visitor we use an anonymous impl: // to completely hide the ANTLR visitor we use an anonymous impl:
JavascriptBaseVisitor<Void> visitor = new JavascriptBaseVisitor<Void>() { new JavascriptBaseVisitor<Void>() {
private final Deque<Type> typeStack = new ArrayDeque<>(); private final Deque<Type> typeStack = new ArrayDeque<>();
@Override @Override
@ -295,9 +295,10 @@ public final class JavascriptCompiler {
int arity = method.getParameterTypes().length; int arity = method.getParameterTypes().length;
if (arguments != arity) { if (arguments != arity) {
throw new ParseRuntimeException( throwChecked(new ParseException(
"Expected (" + arity + ") arguments for function call (" + text + "), but found (" + arguments + ").", "Invalid expression '" + sourceText + "': Expected (" +
ctx.start.getStartIndex()); arity + ") arguments for function call (" + text + "), but found (" + arguments + ").",
ctx.start.getStartIndex()));
} }
typeStack.push(Type.DOUBLE_TYPE); typeStack.push(Type.DOUBLE_TYPE);
@ -331,7 +332,8 @@ public final class JavascriptCompiler {
gen.invokeVirtual(FUNCTION_VALUES_TYPE, DOUBLE_VAL_METHOD); gen.invokeVirtual(FUNCTION_VALUES_TYPE, DOUBLE_VAL_METHOD);
gen.cast(Type.DOUBLE_TYPE, typeStack.peek()); gen.cast(Type.DOUBLE_TYPE, typeStack.peek());
} else { } else {
throw new ParseRuntimeException("Unrecognized function call (" + text + ").", ctx.start.getStartIndex()); throwChecked(new ParseException("Invalid expression '" + sourceText + "': Unrecognized function call (" +
text + ").", ctx.start.getStartIndex()));
} }
return null; return null;
@ -622,16 +624,18 @@ public final class JavascriptCompiler {
throw new IllegalStateException("Invalid expected type: " + typeStack.peek()); throw new IllegalStateException("Invalid expected type: " + typeStack.peek());
} }
} }
};
try { /** Needed to throw checked ParseException in this visitor (that does not allow it). */
visitor.visit(parseTree); private void throwChecked(Throwable t) {
} catch (final ParseRuntimeException e) { this.<Error>throwChecked0(t);
ParseException exception = new ParseException("Invalid expression '" + sourceText + "': " + e.getMessage(), e.position);
exception.initCause(e);
throw exception;
} }
@SuppressWarnings("unchecked")
private <T extends Throwable> void throwChecked0(Throwable t) throws T {
throw (T) t;
}
}.visit(parseTree);
gen.returnValue(); gen.returnValue();
gen.endMethod(); gen.endMethod();
@ -713,16 +717,6 @@ public final class JavascriptCompiler {
DEFAULT_FUNCTIONS = Collections.unmodifiableMap(map); DEFAULT_FUNCTIONS = Collections.unmodifiableMap(map);
} }
@SuppressWarnings("serial")
private final static class ParseRuntimeException extends RuntimeException {
final int position;
public ParseRuntimeException(String msg, int position) {
super(msg);
this.position = position;
}
}
/** Check Method signature for compatibility. */ /** Check Method signature for compatibility. */
private static void checkFunction(Method method) { private static void checkFunction(Method method) {
// check that the Method is public in some public reachable class: // check that the Method is public in some public reachable class:

View File

@ -105,7 +105,6 @@ public class TestCustomFunctions extends LuceneTestCase {
//expected //expected
assertEquals("Invalid expression 'method()': Unrecognized function call (method).", expected.getMessage()); assertEquals("Invalid expression 'method()': Unrecognized function call (method).", expected.getMessage());
assertEquals(0, expected.getErrorOffset()); assertEquals(0, expected.getErrorOffset());
assertTrue(expected.getCause() != null && expected.getCause() != expected);
} }
try { try {