mirror of https://github.com/apache/lucene.git
LUCENE-6451: Expressions now support bindings keys that look like zero arg functions
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1675926 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
665725e27e
commit
458f504202
|
@ -82,6 +82,9 @@ New Features
|
|||
When used, you should typically disable RPT's pruneLeafyBranches option.
|
||||
(Nick Knize, David Smiley)
|
||||
|
||||
* LUCENE-6451: Expressions now support bindings keys that look like
|
||||
zero arg functions (Jack Conradson via Ryan Ernst)
|
||||
|
||||
Optimizations
|
||||
|
||||
* LUCENE-6379: IndexWriter.deleteDocuments(Query...) now detects if
|
||||
|
|
|
@ -235,31 +235,33 @@ public class JavascriptCompiler {
|
|||
int arguments = current.getChildCount() - 1;
|
||||
|
||||
Method method = functions.get(call);
|
||||
if (method == null) {
|
||||
throw new IllegalArgumentException("Unrecognized method call (" + call + ").");
|
||||
if (method == null && (arguments > 0 || !call.contains("."))) {
|
||||
throw new IllegalArgumentException("Unrecognized function call (" + call + ").");
|
||||
} else if (method != null) {
|
||||
int arity = method.getParameterTypes().length;
|
||||
if (arguments != arity) {
|
||||
throw new IllegalArgumentException("Expected (" + arity + ") arguments for function call (" +
|
||||
call + "), but found (" + arguments + ").");
|
||||
}
|
||||
|
||||
for (int argument = 1; argument <= arguments; ++argument) {
|
||||
recursiveCompile(current.getChild(argument), Type.DOUBLE_TYPE);
|
||||
}
|
||||
|
||||
gen.invokeStatic(Type.getType(method.getDeclaringClass()),
|
||||
org.objectweb.asm.commons.Method.getMethod(method));
|
||||
|
||||
gen.cast(Type.DOUBLE_TYPE, expected);
|
||||
break;
|
||||
} else {
|
||||
text = call + "()";
|
||||
// intentionally fall through to the variable case to allow this non-static
|
||||
// method to be forwarded to the bindings for processing
|
||||
}
|
||||
|
||||
int arity = method.getParameterTypes().length;
|
||||
if (arguments != arity) {
|
||||
throw new IllegalArgumentException("Expected (" + arity + ") arguments for method call (" +
|
||||
call + "), but found (" + arguments + ").");
|
||||
}
|
||||
|
||||
for (int argument = 1; argument <= arguments; ++argument) {
|
||||
recursiveCompile(current.getChild(argument), Type.DOUBLE_TYPE);
|
||||
}
|
||||
|
||||
gen.invokeStatic(Type.getType(method.getDeclaringClass()),
|
||||
org.objectweb.asm.commons.Method.getMethod(method));
|
||||
|
||||
gen.cast(Type.DOUBLE_TYPE, expected);
|
||||
break;
|
||||
case JavascriptParser.VARIABLE:
|
||||
int index;
|
||||
|
||||
// normalize quotes
|
||||
text = normalizeQuotes(text);
|
||||
|
||||
|
||||
if (externalsMap.containsKey(text)) {
|
||||
index = externalsMap.get(text);
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.apache.lucene.expressions.js;
|
|||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -42,7 +43,7 @@ public class TestCustomFunctions extends LuceneTestCase {
|
|||
JavascriptCompiler.compile("sqrt(20)", functions, getClass().getClassLoader());
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertTrue(e.getMessage().contains("Unrecognized method"));
|
||||
assertTrue(e.getMessage().contains("Unrecognized function"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ public class TestCustomFunctions extends LuceneTestCase {
|
|||
Expression expr = JavascriptCompiler.compile("foo()", functions, getClass().getClassLoader());
|
||||
assertEquals(5, expr.evaluate(0, null), DELTA);
|
||||
}
|
||||
|
||||
|
||||
public static double oneArgMethod(double arg1) { return 3 + arg1; }
|
||||
|
||||
/** tests a method with one arguments */
|
||||
|
@ -91,7 +92,28 @@ public class TestCustomFunctions extends LuceneTestCase {
|
|||
Expression expr = JavascriptCompiler.compile("foo() + bar(3)", functions, getClass().getClassLoader());
|
||||
assertEquals(11, expr.evaluate(0, null), DELTA);
|
||||
}
|
||||
|
||||
|
||||
/** tests invalid methods that are not allowed to become variables to be mapped */
|
||||
public void testInvalidVariableMethods() {
|
||||
try {
|
||||
JavascriptCompiler.compile("method()");
|
||||
fail();
|
||||
} catch (ParseException exception) {
|
||||
fail();
|
||||
} catch (IllegalArgumentException exception) {
|
||||
//expected
|
||||
}
|
||||
|
||||
try {
|
||||
JavascriptCompiler.compile("method.method(1)");
|
||||
fail();
|
||||
} catch (ParseException exception) {
|
||||
fail();
|
||||
} catch (IllegalArgumentException exception) {
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
public static String bogusReturnType() { return "bogus!"; }
|
||||
|
||||
/** wrong return type: must be double */
|
||||
|
|
|
@ -50,6 +50,15 @@ public class TestJavascriptCompiler extends LuceneTestCase {
|
|||
doTestValidVariable("mixed[23]['key'].sub.sub[1]");
|
||||
doTestValidVariable("mixed[23]['key'].sub.sub[1].sub");
|
||||
doTestValidVariable("mixed[23]['key'].sub.sub[1].sub['abc']");
|
||||
doTestValidVariable("method.method()");
|
||||
doTestValidVariable("method.getMethod()");
|
||||
doTestValidVariable("method.METHOD()");
|
||||
doTestValidVariable("method['key'].method()");
|
||||
doTestValidVariable("method['key'].getMethod()");
|
||||
doTestValidVariable("method['key'].METHOD()");
|
||||
doTestValidVariable("method[23][\"key\"].method()", "method[23]['key'].method()");
|
||||
doTestValidVariable("method[23][\"key\"].getMethod()", "method[23]['key'].getMethod()");
|
||||
doTestValidVariable("method[23][\"key\"].METHOD()", "method[23]['key'].METHOD()");
|
||||
}
|
||||
|
||||
void doTestValidVariable(String variable) throws Exception {
|
||||
|
@ -164,14 +173,14 @@ public class TestJavascriptCompiler extends LuceneTestCase {
|
|||
JavascriptCompiler.compile("tan()");
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(expected.getMessage().contains("arguments for method call"));
|
||||
assertTrue(expected.getMessage().contains("arguments for function call"));
|
||||
}
|
||||
|
||||
try {
|
||||
JavascriptCompiler.compile("tan(1, 1)");
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(expected.getMessage().contains("arguments for method call"));
|
||||
assertTrue(expected.getMessage().contains("arguments for function call"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue