From a46d5535cbca36fc44762355f27f61131391f48b Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Thu, 7 Jan 2016 23:38:14 +0000 Subject: [PATCH] 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 --- lucene/CHANGES.txt | 4 +- .../expressions/js/JavascriptCompiler.java | 42 ++++++++----------- .../expressions/js/TestCustomFunctions.java | 1 - 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index cc2b351d60d..43174975b24 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -227,8 +227,8 @@ Other ctor inside InvocationTargetException. (Uwe Schindler) * LUCENE-6965: Expression's JavascriptCompiler now throw ParseException - with bad function names or bad arity instead of IllegalArgumentException - (Tomás Fernández Löbbe) + with bad function names or bad arity instead of IllegalArgumentException. + (Tomás Fernández Löbbe, Uwe Schindler, Ryan Ernst) * LUCENE-6964: String-based signatures in JavascriptCompiler replaced with better compile-time-checked MethodType; generated class files diff --git a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java index b43a7323bed..83734f87406 100644 --- a/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java +++ b/lucene/expressions/src/java/org/apache/lucene/expressions/js/JavascriptCompiler.java @@ -249,7 +249,7 @@ public final class JavascriptCompiler { EVALUATE_METHOD, null, null, classWriter); // to completely hide the ANTLR visitor we use an anonymous impl: - JavascriptBaseVisitor visitor = new JavascriptBaseVisitor() { + new JavascriptBaseVisitor() { private final Deque typeStack = new ArrayDeque<>(); @Override @@ -295,9 +295,10 @@ public final class JavascriptCompiler { int arity = method.getParameterTypes().length; if (arguments != arity) { - throw new ParseRuntimeException( - "Expected (" + arity + ") arguments for function call (" + text + "), but found (" + arguments + ").", - ctx.start.getStartIndex()); + throwChecked(new ParseException( + "Invalid expression '" + sourceText + "': Expected (" + + arity + ") arguments for function call (" + text + "), but found (" + arguments + ").", + ctx.start.getStartIndex())); } typeStack.push(Type.DOUBLE_TYPE); @@ -331,7 +332,8 @@ public final class JavascriptCompiler { gen.invokeVirtual(FUNCTION_VALUES_TYPE, DOUBLE_VAL_METHOD); gen.cast(Type.DOUBLE_TYPE, typeStack.peek()); } 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; @@ -622,15 +624,17 @@ public final class JavascriptCompiler { throw new IllegalStateException("Invalid expected type: " + typeStack.peek()); } } - }; - - try { - visitor.visit(parseTree); - } catch (final ParseRuntimeException e) { - ParseException exception = new ParseException("Invalid expression '" + sourceText + "': " + e.getMessage(), e.position); - exception.initCause(e); - throw exception; - } + + /** Needed to throw checked ParseException in this visitor (that does not allow it). */ + private void throwChecked(Throwable t) { + this.throwChecked0(t); + } + + @SuppressWarnings("unchecked") + private void throwChecked0(Throwable t) throws T { + throw (T) t; + } + }.visit(parseTree); gen.returnValue(); gen.endMethod(); @@ -713,16 +717,6 @@ public final class JavascriptCompiler { 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. */ private static void checkFunction(Method method) { // check that the Method is public in some public reachable class: diff --git a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java index 53938d03514..5c7dfec2662 100644 --- a/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java +++ b/lucene/expressions/src/test/org/apache/lucene/expressions/js/TestCustomFunctions.java @@ -105,7 +105,6 @@ public class TestCustomFunctions extends LuceneTestCase { //expected assertEquals("Invalid expression 'method()': Unrecognized function call (method).", expected.getMessage()); assertEquals(0, expected.getErrorOffset()); - assertTrue(expected.getCause() != null && expected.getCause() != expected); } try {