This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/master by this push:
     new 3067866  JEXL-298: de-interlace size/empty operators and size/empty 
method handling, simplified grammar, removed unused code, added test Task 
#JEXL-298 - Unable to call 'empty' and 'size' member methods with parameters
3067866 is described below

commit 306786606116839960dd131c49dfbd287533bb6d
Author: Henri Biestro <hbies...@gmail.com>
AuthorDate: Sun May 26 21:14:58 2019 +0200

    JEXL-298: de-interlace size/empty operators and size/empty method handling, 
simplified grammar, removed unused code, added test
    Task #JEXL-298 - Unable to call 'empty' and 'size' member methods with 
parameters
---
 RELEASE-NOTES.txt                                  |  1 +
 .../org/apache/commons/jexl3/JexlArithmetic.java   | 54 ++++++++-----
 .../org/apache/commons/jexl3/JexlOperator.java     |  6 +-
 .../apache/commons/jexl3/internal/Debugger.java    | 26 ++-----
 .../apache/commons/jexl3/internal/Interpreter.java | 40 ++++------
 .../apache/commons/jexl3/internal/Operators.java   | 14 ++--
 .../commons/jexl3/internal/ScriptVisitor.java      | 14 +---
 .../org/apache/commons/jexl3/parser/Parser.jjt     | 59 ++++++---------
 .../apache/commons/jexl3/parser/ParserVisitor.java |  6 +-
 src/site/xdoc/changes.xml                          | 18 ++---
 .../org/apache/commons/jexl3/ArithmeticTest.java   |  4 +-
 .../org/apache/commons/jexl3/ExceptionTest.java    |  8 +-
 .../org/apache/commons/jexl3/Issues200Test.java    | 88 ++++++++++++++++------
 13 files changed, 169 insertions(+), 169 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index b5f402e..b345cd7 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -78,6 +78,7 @@ Bugs Fixed in 3.2:
 * JEXL-301:      Array access operator does not fail on null object in 
non-strict arithmetic mode
 * JEXL-300:      Ant-ish variables should not use safe-access operator syntax
 * JEXL-299:      Improve message error when method could not be found
+* JEXL-298:      Unable to call 'empty' and 'size' member methods with 
parameters
 * JEXL-296:      Real literal in scientific format is not parsed without suffix
 * JEXL-291:      Using sandbox prevents array-syntax lookup by number in Map
 * JEXL-290:      Safe navigation fails on chained method calls
diff --git a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java 
b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
index 9ff61c4..094f2d7 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlArithmetic.java
@@ -825,13 +825,13 @@ public class JexlArithmetic {
         }
         throw new ArithmeticException("Object negate:(" + val + ")");
     }
-    
+
     /**
      * Whether negate called with a given argument will always return the same 
result.
      * <p>This is used to determine whether negate results on number literals 
can be cached.
      * If the result on calling negate with the same constant argument may 
change between calls,
      * which means the function is not deterministic, this method must return 
false.
-     * @see #isNegateStable() 
+     * @see #isNegateStable()
      * @return true if negate is idempotent, false otherwise
      */
     public boolean isNegateStable() {
@@ -867,7 +867,7 @@ public class JexlArithmetic {
         }
         throw new ArithmeticException("Object positivize:(" + val + ")");
     }
-        
+
     /**
      * Whether positivize called with a given argument will always return the 
same result.
      * <p>This is used to determine whether positivize results on number 
literals can be cached.
@@ -878,7 +878,7 @@ public class JexlArithmetic {
     public boolean isPositivizeStable() {
         return true;
     }
-    
+
     /**
      * Test if left contains right (right matches/in left).
      * <p>Beware that this method arguments are the opposite of the operator 
arguments.
@@ -968,27 +968,41 @@ public class JexlArithmetic {
 
     /**
      * Check for emptiness of various types: Number, Collection, Array, Map, 
String.
+     * <p>Override or overload this method to add new signatures to the size 
operators.
+     * @param object the object to check the emptiness of
+     * @return the boolean or false if object is not null
+     * @since 3.2
+     */
+    public Boolean empty(Object object) {
+        Boolean e = isEmpty(object);
+        return e == null ? Boolean.TRUE  : e;
+    }
+
+    /**
+     * Check for emptiness of various types: Number, Collection, Array, Map, 
String.
      *
      * @param object the object to check the emptiness of
      * @return the boolean or null if there is no arithmetic solution
      */
     public Boolean isEmpty(Object object) {
-        if (object instanceof Number) {
-            double d = ((Number) object).doubleValue();
-            return Double.isNaN(d) || d == 0.d ? Boolean.TRUE : Boolean.FALSE;
-        }
-        if (object instanceof CharSequence) {
-            return ((CharSequence) object).length() == 0 ? Boolean.TRUE : 
Boolean.FALSE;
-        }
-        if (object.getClass().isArray()) {
-            return Array.getLength(object) == 0 ? Boolean.TRUE : Boolean.FALSE;
-        }
-        if (object instanceof Collection<?>) {
-            return ((Collection<?>) object).isEmpty() ? Boolean.TRUE : 
Boolean.FALSE;
-        }
-        // Map isn't a collection
-        if (object instanceof Map<?, ?>) {
-            return ((Map<?, ?>) object).isEmpty() ? Boolean.TRUE : 
Boolean.FALSE;
+        if (object != null) {
+            if (object instanceof Number) {
+                double d = ((Number) object).doubleValue();
+                return Double.isNaN(d) || d == 0.d ? Boolean.TRUE : 
Boolean.FALSE;
+            }
+            if (object instanceof CharSequence) {
+                return ((CharSequence) object).length() == 0 ? Boolean.TRUE : 
Boolean.FALSE;
+            }
+            if (object.getClass().isArray()) {
+                return Array.getLength(object) == 0 ? Boolean.TRUE : 
Boolean.FALSE;
+            }
+            if (object instanceof Collection<?>) {
+                return ((Collection<?>) object).isEmpty() ? Boolean.TRUE : 
Boolean.FALSE;
+            }
+            // Map isn't a collection
+            if (object instanceof Map<?, ?>) {
+                return ((Map<?, ?>) object).isEmpty() ? Boolean.TRUE : 
Boolean.FALSE;
+            }
         }
         return null;
     }
diff --git a/src/main/java/org/apache/commons/jexl3/JexlOperator.java 
b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
index f510612..7cbaaba 100644
--- a/src/main/java/org/apache/commons/jexl3/JexlOperator.java
+++ b/src/main/java/org/apache/commons/jexl3/JexlOperator.java
@@ -191,7 +191,7 @@ public enum JexlOperator {
      * @see JexlArithmetic#negate
      */
     NEGATE("-", "negate", 1),
-    
+
     /**
      * Positivize operator.
      * <br><strong>Syntax:</strong> <code>+x</code>
@@ -203,8 +203,8 @@ public enum JexlOperator {
     /**
      * Empty operator.
      * <br><strong>Syntax:</strong> <code>empty x</code> or 
<code>empty(x)</code>
-     * <br><strong>Method:</strong> <code>boolean isEmpty(L x);</code>.
-     * @see JexlArithmetic#isEmpty
+     * <br><strong>Method:</strong> <code>boolean empty(L x);</code>.
+     * @see JexlArithmetic#empty
      */
     EMPTY("empty", "empty", 1),
 
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java 
b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
index c3cfd35..43339f9 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Debugger.java
@@ -40,7 +40,6 @@ import org.apache.commons.jexl3.parser.ASTEQNode;
 import org.apache.commons.jexl3.parser.ASTERNode;
 import org.apache.commons.jexl3.parser.ASTEWNode;
 import org.apache.commons.jexl3.parser.ASTEmptyFunction;
-import org.apache.commons.jexl3.parser.ASTEmptyMethod;
 import org.apache.commons.jexl3.parser.ASTExtendedLiteral;
 import org.apache.commons.jexl3.parser.ASTFalseNode;
 import org.apache.commons.jexl3.parser.ASTForeachStatement;
@@ -84,7 +83,6 @@ import org.apache.commons.jexl3.parser.ASTSetOrNode;
 import org.apache.commons.jexl3.parser.ASTSetSubNode;
 import org.apache.commons.jexl3.parser.ASTSetXorNode;
 import org.apache.commons.jexl3.parser.ASTSizeFunction;
-import org.apache.commons.jexl3.parser.ASTSizeMethod;
 import org.apache.commons.jexl3.parser.ASTStringLiteral;
 import org.apache.commons.jexl3.parser.ASTSubNode;
 import org.apache.commons.jexl3.parser.ASTTernaryNode;
@@ -132,7 +130,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
      */
     public Debugger() {
     }
-    
+
     /**
      * Resets this debugger state.
      */
@@ -145,7 +143,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
         indent = 2;
         depth = Integer.MAX_VALUE;
     }
-    
+
     /**
      * Position the debugger on the root of an expression.
      * @param jscript the expression
@@ -255,7 +253,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
     public void setIndentation(int level) {
         indentation(level);
     }
-    
+
     /**
      * Sets the indentation level.
      * @param level the number of spaces for indentation, none if less or 
equal to zero
@@ -270,7 +268,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
         indentLevel = 0;
         return this;
     }
-    
+
     /**
      * Sets this debugger relative maximum depth.
      * @param rdepth the maximum relative depth from the debugged node
@@ -554,13 +552,6 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
     }
 
     @Override
-    protected Object visit(ASTEmptyMethod node, Object data) {
-        accept(node.jjtGetChild(0), data);
-        check(node, ".empty()", data);
-        return data;
-    }
-
-    @Override
     protected Object visit(ASTEQNode node, Object data) {
         return infixChildren(node, " == ", false, data);
     }
@@ -938,13 +929,6 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
     }
 
     @Override
-    protected Object visit(ASTSizeMethod node, Object data) {
-        accept(node.jjtGetChild(0), data);
-        check(node, ".size()", data);
-        return data;
-    }
-
-    @Override
     protected Object visit(ASTStringLiteral node, Object data) {
         String img = node.getLiteral().replace("'", "\\'");
         return check(node, "'" + img + "'", data);
@@ -995,7 +979,7 @@ public class Debugger extends ParserVisitor implements 
JexlInfo.Detail {
     protected Object visit(ASTUnaryPlusNode node, Object data) {
         return prefixChild(node, "+", data);
     }
-    
+
     @Override
     protected Object visit(ASTVar node, Object data) {
         builder.append("var ");
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java 
b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
index 8dd9a0a..f0aaa66 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Interpreter.java
@@ -49,7 +49,6 @@ import org.apache.commons.jexl3.parser.ASTEQNode;
 import org.apache.commons.jexl3.parser.ASTERNode;
 import org.apache.commons.jexl3.parser.ASTEWNode;
 import org.apache.commons.jexl3.parser.ASTEmptyFunction;
-import org.apache.commons.jexl3.parser.ASTEmptyMethod;
 import org.apache.commons.jexl3.parser.ASTExtendedLiteral;
 import org.apache.commons.jexl3.parser.ASTFalseNode;
 import org.apache.commons.jexl3.parser.ASTForeachStatement;
@@ -95,7 +94,6 @@ import org.apache.commons.jexl3.parser.ASTSetOrNode;
 import org.apache.commons.jexl3.parser.ASTSetSubNode;
 import org.apache.commons.jexl3.parser.ASTSetXorNode;
 import org.apache.commons.jexl3.parser.ASTSizeFunction;
-import org.apache.commons.jexl3.parser.ASTSizeMethod;
 import org.apache.commons.jexl3.parser.ASTStringLiteral;
 import org.apache.commons.jexl3.parser.ASTSubNode;
 import org.apache.commons.jexl3.parser.ASTTernaryNode;
@@ -147,7 +145,7 @@ public class Interpreter extends InterpreterBase {
         super(ii, jexla);
         frame = ii.frame;
     }
-        
+
     /**
      * Swaps the current thread local interpreter.
      * @param inter the interpreter or null
@@ -231,7 +229,7 @@ public class Interpreter extends InterpreterBase {
         }
         return null;
     }
-    
+
     /**
      * Gets an attribute of an object.
      *
@@ -252,7 +250,7 @@ public class Interpreter extends InterpreterBase {
     public void setAttribute(Object object, Object attribute, Object value) {
         setAttribute(object, attribute, value, null);
     }
-    
+
     @Override
     protected Object visit(ASTAddNode node, Object data) {
         Object left = node.jjtGetChild(0).jjtAccept(this, data);
@@ -527,7 +525,7 @@ public class Interpreter extends InterpreterBase {
             throw new JexlException(valNode, "- error", xrt);
         }
     }
-    
+
     @Override
     protected Object visit(ASTUnaryPlusNode node, Object data) {
         // use cached value if literal
@@ -553,7 +551,7 @@ public class Interpreter extends InterpreterBase {
             throw new JexlException(valNode, "- error", xrt);
         }
     }
-    
+
     @Override
     protected Object visit(ASTBitwiseComplNode node, Object data) {
         Object arg = node.jjtGetChild(0).jjtAccept(this, data);
@@ -898,12 +896,6 @@ public class Interpreter extends InterpreterBase {
     }
 
     @Override
-    protected Object visit(ASTSizeMethod node, Object data) {
-        Object val = node.jjtGetChild(0).jjtAccept(this, data);
-        return operators.size(node, val);
-    }
-
-    @Override
     protected Object visit(ASTEmptyFunction node, Object data) {
         try {
             Object value = node.jjtGetChild(0).jjtAccept(this, data);
@@ -914,12 +906,6 @@ public class Interpreter extends InterpreterBase {
     }
 
     @Override
-    protected Object visit(ASTEmptyMethod node, Object data) {
-        Object val = node.jjtGetChild(0).jjtAccept(this, data);
-        return operators.empty(node, val);
-    }
-
-    @Override
     protected Object visit(ASTJexlScript node, Object data) {
         if (node instanceof ASTJexlLambda && !((ASTJexlLambda) 
node).isTopLevel()) {
             return new Closure(this, (ASTJexlLambda) node);
@@ -951,7 +937,7 @@ public class Interpreter extends InterpreterBase {
             return null;
         }
     }
-    
+
     @Override
     protected Object visit(ASTIdentifier node, Object data) {
         cancelCheck(node);
@@ -968,7 +954,7 @@ public class Interpreter extends InterpreterBase {
                 && !(context.has(name))
                 && !node.isTernaryProtected()) {
                 return jexl.safe
-                        ? null 
+                        ? null
                         : unsolvableVariable(node, name, !(node.getSymbol() >= 
0 || context.has(name)));
             }
             return value;
@@ -1037,7 +1023,7 @@ public class Interpreter extends InterpreterBase {
         Object id = evalIdentifier(node);
         return getAttribute(data, id, node);
     }
-    
+
     @Override
     protected Object visit(ASTReference node, Object data) {
         cancelCheck(node);
@@ -1083,7 +1069,7 @@ public class Interpreter extends InterpreterBase {
                 } else {
                     antish = false;
                 }
-            } 
+            }
             // attempt to evaluate the property within the object 
(visit(ASTIdentifierAccess node))
             object = objectNode.jjtAccept(this, object);
             cancelCheck(node);
@@ -1158,7 +1144,7 @@ public class Interpreter extends InterpreterBase {
         }
         return object;
     }
-    
+
     @Override
     protected Object visit(ASTAssignment node, Object data) {
         return executeAssign(node, null, data);
@@ -1488,7 +1474,7 @@ public class Interpreter extends InterpreterBase {
                 } else if (context.has(methodName)) {
                     functor = context.get(methodName);
                     isavar = functor != null;
-                } 
+                }
                 // name is a variable, cant be cached
                 cacheable &= !isavar;
             }
@@ -1509,7 +1495,7 @@ public class Interpreter extends InterpreterBase {
             // safe lhs
             return null;
         }
-        
+
         // solving the call site
         CallDispatcher call = new CallDispatcher(node, cacheable);
         try {
@@ -1517,7 +1503,7 @@ public class Interpreter extends InterpreterBase {
             Object eval = call.tryEval(target, methodName, argv);
             if (JexlEngine.TRY_FAILED != eval) {
                 return eval;
-            } 
+            }
             boolean functorp = false;
             boolean narrow = false;
             // pseudo loop to try acquiring methods without and with argument 
narrowing
diff --git a/src/main/java/org/apache/commons/jexl3/internal/Operators.java 
b/src/main/java/org/apache/commons/jexl3/internal/Operators.java
index 5efd656..be52c79 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/Operators.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/Operators.java
@@ -318,21 +318,21 @@ public class Operators {
         if (object == null) {
             return Boolean.TRUE;
         }
-        final JexlArithmetic arithmetic = interpreter.arithmetic;
-        final JexlUberspect uberspect = interpreter.uberspect;
         Object result = Operators.this.tryOverload(node, JexlOperator.EMPTY, 
object);
         if (result != JexlEngine.TRY_FAILED) {
             return result;
         }
+        final JexlArithmetic arithmetic = interpreter.arithmetic;
         result = arithmetic.isEmpty(object);
         if (result == null) {
+            final JexlUberspect uberspect = interpreter.uberspect;
             result = false;
             // check if there is an isEmpty method on the object that returns a
             // boolean and if so, just use it
             JexlMethod vm = uberspect.getMethod(object, "isEmpty", 
Interpreter.EMPTY_PARAMS);
             if (returnsBoolean(vm)) {
                 try {
-                    result = (Boolean) vm.invoke(object, 
Interpreter.EMPTY_PARAMS);
+                    result = vm.invoke(object, Interpreter.EMPTY_PARAMS);
                 } catch (Exception xany) {
                     interpreter.operatorError(node, JexlOperator.EMPTY, xany);
                 }
@@ -347,27 +347,27 @@ public class Operators {
      * <p>Note that the result may not be an integer.
      *
      * @param node   the node that gave the value to size
-     * @param object the object to get the size of.
+     * @param object the object to get the size of
      * @return the evaluation result
      */
     protected Object size(JexlNode node, Object object) {
         if (object == null) {
             return 0;
         }
-        final JexlArithmetic arithmetic = interpreter.arithmetic;
-        final JexlUberspect uberspect = interpreter.uberspect;
         Object result = Operators.this.tryOverload(node, JexlOperator.SIZE, 
object);
         if (result != JexlEngine.TRY_FAILED) {
             return result;
         }
+        final JexlArithmetic arithmetic = interpreter.arithmetic;
         result = arithmetic.size(object);
         if (result == null) {
+            final JexlUberspect uberspect = interpreter.uberspect;
             // check if there is a size method on the object that returns an
             // integer and if so, just use it
             JexlMethod vm = uberspect.getMethod(object, "size", 
Interpreter.EMPTY_PARAMS);
             if (vm != null && (Integer.TYPE.equals(vm.getReturnType()) || 
Integer.class.equals(vm.getReturnType()))) {
                 try {
-                    result = (Integer) vm.invoke(object, 
Interpreter.EMPTY_PARAMS);
+                    result = vm.invoke(object, Interpreter.EMPTY_PARAMS);
                 } catch (Exception xany) {
                     interpreter.operatorError(node, JexlOperator.SIZE, xany);
                 }
diff --git a/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java 
b/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
index ca33ca3..94e946a 100644
--- a/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
+++ b/src/main/java/org/apache/commons/jexl3/internal/ScriptVisitor.java
@@ -40,7 +40,6 @@ import org.apache.commons.jexl3.parser.ASTEQNode;
 import org.apache.commons.jexl3.parser.ASTERNode;
 import org.apache.commons.jexl3.parser.ASTEWNode;
 import org.apache.commons.jexl3.parser.ASTEmptyFunction;
-import org.apache.commons.jexl3.parser.ASTEmptyMethod;
 import org.apache.commons.jexl3.parser.ASTExtendedLiteral;
 import org.apache.commons.jexl3.parser.ASTFalseNode;
 import org.apache.commons.jexl3.parser.ASTForeachStatement;
@@ -84,7 +83,6 @@ import org.apache.commons.jexl3.parser.ASTSetOrNode;
 import org.apache.commons.jexl3.parser.ASTSetSubNode;
 import org.apache.commons.jexl3.parser.ASTSetXorNode;
 import org.apache.commons.jexl3.parser.ASTSizeFunction;
-import org.apache.commons.jexl3.parser.ASTSizeMethod;
 import org.apache.commons.jexl3.parser.ASTStringLiteral;
 import org.apache.commons.jexl3.parser.ASTSubNode;
 import org.apache.commons.jexl3.parser.ASTTernaryNode;
@@ -326,7 +324,7 @@ public class ScriptVisitor extends ParserVisitor {
     protected Object visit(ASTUnaryPlusNode node, Object data) {
         return visitNode(node, data);
     }
-    
+
     @Override
     protected Object visit(ASTBitwiseComplNode node, Object data) {
         return visitNode(node, data);
@@ -408,11 +406,6 @@ public class ScriptVisitor extends ParserVisitor {
     }
 
     @Override
-    protected Object visit(ASTEmptyMethod node, Object data) {
-        return visitNode(node, data);
-    }
-
-    @Override
     protected Object visit(ASTSizeFunction node, Object data) {
         return visitNode(node, data);
     }
@@ -428,11 +421,6 @@ public class ScriptVisitor extends ParserVisitor {
     }
 
     @Override
-    protected Object visit(ASTSizeMethod node, Object data) {
-        return visitNode(node, data);
-    }
-
-    @Override
     protected Object visit(ASTConstructorNode node, Object data) {
         return visitNode(node, data);
     }
diff --git a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt 
b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
index edede88..4cc2426 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
+++ b/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt
@@ -113,35 +113,35 @@ TOKEN_MGR_DECLS : {
 
 <*> TOKEN : /* KEYWORDS */
 {
-      < IF : "if" > { popDot(); } 
-    | < ELSE : "else" > { popDot(); } 
-    | < FOR : "for" > { popDot(); } 
-    | < WHILE : "while" > { popDot(); } 
-    | < DO : "do" > { popDot(); } 
-    | < NEW : "new" >  { popDot(); } 
-    | < VAR : "var" >  { popDot(); } 
+      < IF : "if" > { popDot(); }
+    | < ELSE : "else" > { popDot(); }
+    | < FOR : "for" > { popDot(); }
+    | < WHILE : "while" > { popDot(); }
+    | < DO : "do" > { popDot(); }
+    | < NEW : "new" >  { popDot(); }
+    | < VAR : "var" >  { popDot(); }
     | < EMPTY : "empty" > { popDot(); } /* Revert state to default if was 
DOT_ID. */
     | < SIZE : "size" > { popDot(); } /* Revert state to default if was 
DOT_ID. */
-    | < NULL : "null" >  { popDot(); } 
-    | < TRUE : "true" > { popDot(); } 
-    | < FALSE : "false" >  { popDot(); } 
-    | < RETURN : "return" > { popDot(); } 
-    | < FUNCTION : "function" >  { popDot(); } 
+    | < NULL : "null" >  { popDot(); }
+    | < TRUE : "true" > { popDot(); }
+    | < FALSE : "false" >  { popDot(); }
+    | < RETURN : "return" > { popDot(); }
+    | < FUNCTION : "function" >  { popDot(); }
     | < LAMBDA : "->" >
-    | < BREAK : "break" > { popDot(); } 
-    | < CONTINUE : "continue" > { popDot(); } 
-    | < PRAGMA : "#pragma" > { popDot(); } 
+    | < BREAK : "break" > { popDot(); }
+    | < CONTINUE : "continue" > { popDot(); }
+    | < PRAGMA : "#pragma" > { popDot(); }
 }
 
 <*> TOKEN : { /* SEPARATORS */
-      < LPAREN : "(">  
+      < LPAREN : "(">
     | < RPAREN : ")">
     | < LCURLY : "{" >
     | < RCURLY : "}" >
     | < LBRACKET : "[" >
     | < RBRACKET : "]" >
     | < SEMICOL : ";" >
-    | < COLON : ":" > 
+    | < COLON : ":" >
     | < COMMA : "," >
     | < DOT : "." > { pushDot(); } /* Lexical state is now DOT_ID */
     | < QDOT : "?." > { pushDot(); } /* Lexical state is now DOT_ID */
@@ -244,7 +244,7 @@ TOKEN_MGR_DECLS : {
 <DEFAULT, REGISTERS> TOKEN : /* LITERALS */
 {
  <INTEGER_LITERAL:
-      <DECIMAL_LITERAL> (<INT_SFX>)? 
+      <DECIMAL_LITERAL> (<INT_SFX>)?
     | <HEX_LITERAL> (<INT_SFX>)?
     | <OCTAL_LITERAL> (<INT_SFX>)?
  >
@@ -252,7 +252,7 @@ TOKEN_MGR_DECLS : {
     | <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+>
     | <#OCTAL_LITERAL: "0" (["0"-"7"])*>
     | <#INT_SFX : ["l","L","h","H"]>
-| 
+|
 <FLOAT_LITERAL:
       (["0"-"9"])+ "." (["0"-"9"])+ (<FLT_SFX>)?
     | (["0"-"9"])+ (".")? (<FLT_SFX>)
@@ -328,8 +328,8 @@ void Statement() #void : {}
 {
     <SEMICOL>
     | LOOKAHEAD(<ANNOTATION>) AnnotatedStatement()
-    | LOOKAHEAD(Expression()) ExpressionStatement() 
-    | Block() 
+    | LOOKAHEAD(Expression()) ExpressionStatement()
+    | Block()
     | IfStatement()
     | ForeachStatement()
     | WhileStatement()
@@ -768,20 +768,11 @@ void SetLiteral() : {}
     <LCURLY> (Expression() ( <COMMA> Expression() )*)? <RCURLY>
 }
 
+
 /***************************************
  *      Functions & Methods
  ***************************************/
 
-void EmptyMethod() #EmptyMethod() : {}
-{
-    <EMPTY> <LPAREN> <RPAREN>
-}
-
-void SizeMethod() #SizeMethod() : {}
-{
-    <SIZE> <LPAREN> <RPAREN>
-}
-
 void Arguments() #Arguments : {}
 {
      <LPAREN> (Expression() (<COMMA> Expression())* )? <RPAREN>
@@ -855,7 +846,7 @@ Token dotName() #void :
 }
 {
    ( t = <DOT_IDENTIFIER> | t=<IF> | t=<ELSE> | t=<FOR> | t=<WHILE> | t=<DO> | 
t=<NEW>| t=<EMPTY> | t=<SIZE> | t=<TRUE> | t=<FALSE> | t=<NULL>
-   | t=<_OR> | t=<_AND>| t=<NOT> | t=<NE> | t=<EQ> | t=<GT> | t=<GE> | t=<LT> 
| t=<LE> 
+   | t=<_OR> | t=<_AND>| t=<NOT> | t=<NE> | t=<EQ> | t=<GT> | t=<GE> | t=<LT> 
| t=<LE>
    | t=<VAR> | t=<FUNCTION> ) { return t ;}
 }
 
@@ -927,10 +918,6 @@ void PrimaryExpression() #void : {}
 
 void MethodCall() #void : {}
 {
-    LOOKAHEAD(<DOT> <SIZE>) (<DOT> <SIZE> <LPAREN> <RPAREN>) #SizeMethod(1)
-    |
-    LOOKAHEAD(<DOT> <EMPTY>) (<DOT> <EMPTY> <LPAREN> <RPAREN>) #EmptyMethod(1)
-    |
     (MemberAccess() (LOOKAHEAD(<LPAREN>) Arguments())+) #MethodNode(>1)
 }
 
diff --git a/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java 
b/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
index a3d0d59..5aa1296 100644
--- a/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
+++ b/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java
@@ -113,7 +113,7 @@ public abstract class ParserVisitor {
     protected abstract Object visit(ASTModNode node, Object data);
 
     protected abstract Object visit(ASTUnaryMinusNode node, Object data);
-    
+
     protected abstract Object visit(ASTUnaryPlusNode node, Object data);
 
     protected abstract Object visit(ASTBitwiseComplNode node, Object data);
@@ -148,16 +148,12 @@ public abstract class ParserVisitor {
 
     protected abstract Object visit(ASTEmptyFunction node, Object data);
 
-    protected abstract Object visit(ASTEmptyMethod node, Object data);
-
     protected abstract Object visit(ASTSizeFunction node, Object data);
 
     protected abstract Object visit(ASTFunctionNode node, Object data);
 
     protected abstract Object visit(ASTMethodNode node, Object data);
 
-    protected abstract Object visit(ASTSizeMethod node, Object data);
-
     protected abstract Object visit(ASTConstructorNode node, Object data);
 
     protected abstract Object visit(ASTArrayAccess node, Object data);
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index 1bf8259..6a0b99f 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -26,7 +26,7 @@
     </properties>
     <body>
         <release version="3.2" date="unreleased">
-            <action dev="henrib" type="fix" issue="JEXL-305 due-to="Dmitri 
Blinov">
+            <action dev="henrib" type="fix" issue="JEXL-305" due-to="Dmitri 
Blinov">
                 Script debugger produces incorrect syntax
             </action>
             <action dev="henrib" type="fix" issue="JEXL-304" due-to="Marcus 
Warm">
@@ -38,25 +38,25 @@
             <action dev="henrib" type="fix" issue="JEXL-301" due-to="Dmitri 
Blinov">
                 Array access operator does not fail on null object in 
non-strict arithmetic mode
             </action>
-            <action dev="henrib" type="fix" issue="JEXL-296" due-to="Dmitri 
Blinov">
-                Ant-ish variables should not use safe-access operator syntax
-            </action>
             <action dev="henrib" type="fix" issue="JEXL-299" due-to="Jarek 
Cecho">
                 Improve message error when method could not be found
             </action>
+            <action dev="henrib" type="fix" issue="JEXL-298" due-to="Dmitri 
Blinov">
+                Unable to call 'empty' and 'size' member methods with 
parameters
+            </action>
             <action dev="henrib" type="fix" issue="JEXL-296" due-to="Dmitri 
Blinov">
                 Real literal in scientific format is not parsed without suffix
             </action>
-            <action dev="henrib" type="add" issue="JEXL-295"> 
+            <action dev="henrib" type="add" issue="JEXL-295">
                 Add unary plus operator
             </action>
             <action dev="henrib" type="add" issue="JEXL-292" due-to="Dmitri 
Blinov">
                 Allow specifying custom Permissions class for Uberspect to be 
used later by Introspector
             </action>
-            <action dev="henrib" type="fix" issue="JEXL-291" due-to="David 
Costanzo"> 
+            <action dev="henrib" type="fix" issue="JEXL-291" due-to="David 
Costanzo">
                 Using sandbox prevents array-syntax lookup by number in Map
             </action>
-            <action dev="henrib" type="fix" issue="JEXL-290"> 
+            <action dev="henrib" type="fix" issue="JEXL-290">
                 Safe navigation fails on chained method calls
             </action>
             <action dev="henrib" type="fix" issue="JEXL-289" due-to="Dmitri 
Blinov">
@@ -68,10 +68,10 @@
             <action dev="henrib" type="fix" issue="JEXL-287" due-to="Dmitri 
Blinov">
                 Wrong resolution of local variables
             </action>
-            <action dev="henrib" type="fix" issue="JEXL-286" due-to="Dmitri 
Blinov"> 
+            <action dev="henrib" type="fix" issue="JEXL-286" due-to="Dmitri 
Blinov">
                 For statement without a body should update its variable
             </action>
-            <action dev="henrib" type="fix" issue="JEXL-285"> 
+            <action dev="henrib" type="fix" issue="JEXL-285">
                 For statement variable may seem unaffected by iteration
             </action>
             <action dev="henrib" type="fix" issue="JEXL-282" due-to="Dmitri 
Blinov">
diff --git a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java 
b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
index 811073d..9ec7f75 100644
--- a/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ArithmeticTest.java
@@ -156,7 +156,7 @@ public class ArithmeticTest extends JexlTestCase {
             asserter.assertExpression("-aBigDecimal", new BigDecimal("-8.8"));
         }
     }
-    
+
     /**
      * test some simple mathematical calculations
      */
@@ -185,7 +185,7 @@ public class ArithmeticTest extends JexlTestCase {
             asserter.assertExpression("+aBigDecimal", new BigDecimal("8.8"));
         }
     }
-    
+
     /**
      * test some simple mathematical calculations
      */
diff --git a/src/test/java/org/apache/commons/jexl3/ExceptionTest.java 
b/src/test/java/org/apache/commons/jexl3/ExceptionTest.java
index e767eda..2f744a2 100644
--- a/src/test/java/org/apache/commons/jexl3/ExceptionTest.java
+++ b/src/test/java/org/apache/commons/jexl3/ExceptionTest.java
@@ -101,7 +101,7 @@ public class ExceptionTest extends JexlTestCase {
             Throwable xth = xany.getCause();
             Assert.assertEquals(NullPointerException.class, xth.getClass());
         }
-        
+
         try {
             jexl.invokeMethod(npe, "foo", 42);
             Assert.fail("Should have thrown JexlException.Method");
@@ -262,16 +262,16 @@ public class ExceptionTest extends JexlTestCase {
             }
         } catch(JexlException xjexl) {
             if (!strict || silent) {
-                Assert.fail("should not have thrown an exception");
+                Assert.fail(src + ": should not have thrown an exception");
             }
         }
         if (strict) {
             if (silent && l.count("warn") == 0) {
-                Assert.fail("should have generated a warning");
+                Assert.fail(src + ": should have generated a warning");
             }
         } else {
             if (l.count("debug") == 0) {
-                Assert.fail("should have generated a debug");
+                Assert.fail(src + ": should have generated a debug");
             }
             Assert.assertEquals(42, r);
         }
diff --git a/src/test/java/org/apache/commons/jexl3/Issues200Test.java 
b/src/test/java/org/apache/commons/jexl3/Issues200Test.java
index 009f7fe..cc28fc3 100644
--- a/src/test/java/org/apache/commons/jexl3/Issues200Test.java
+++ b/src/test/java/org/apache/commons/jexl3/Issues200Test.java
@@ -389,7 +389,7 @@ public class Issues200Test extends JexlTestCase {
         result = script.execute(ctx);
         Assert.assertEquals(10, result);
     }
-      
+
     @Test
     public void test230() throws Exception {
         JexlEngine jexl = new JexlBuilder().cache(4).create();
@@ -572,8 +572,8 @@ public class Issues200Test extends JexlTestCase {
         result = script.execute(ctxt);
         Assert.assertTrue(result instanceof JexlScript);
     }
-    
-    
+
+
     @Test
     public void test274() throws Exception {
         JexlEngine jexl = new 
JexlBuilder().strict(true).safe(true).stackOverflow(5).create();
@@ -600,8 +600,8 @@ public class Issues200Test extends JexlTestCase {
             String sxs = xstack.toString();
             Assert.assertTrue(sxs.contains("jvm"));
         }
-    } 
-               
+    }
+
     @Test
     public void test278() throws Exception {
         String[] srcs = new String[]{
@@ -620,7 +620,7 @@ public class Issues200Test extends JexlTestCase {
         ctxt.set("union", "42");
         Object value;
         JexlScript jc;
-        for(int i = 0; i < srcs.length; ++i) { 
+        for(int i = 0; i < srcs.length; ++i) {
             String src = srcs[i];
             try {
                 jc = jexl.createScript(src);
@@ -635,7 +635,7 @@ public class Issues200Test extends JexlTestCase {
             Assert.assertEquals(src, ctls[i], value);
         }
     }
-    
+
     public static class Context279 extends MapContext {
         public String identity(String x) {
             return x;
@@ -721,7 +721,7 @@ public class Issues200Test extends JexlTestCase {
             ctxt.set("z.y", null);
         }
     }
-    
+
     @Test
     public void test279b() throws Exception {
         Object result;
@@ -733,10 +733,15 @@ public class Issues200Test extends JexlTestCase {
         script = jexl.createScript(src);
         result = script.execute(ctxt, "abc");
         Assert.assertEquals("a", result);
-        result = script.execute(ctxt, (Object) null);
+        result = null;
+        try {
+            result = script.execute(ctxt, (Object) null);
+        } catch(JexlException xany) {
+            Assert.assertNotNull(xany.getMessage());
+        }
         Assert.assertNull(result);
-    } 
-    
+    }
+
     @Test
     public void test285() throws Exception {
         List<String> out = new ArrayList<String>(6);
@@ -760,7 +765,7 @@ public class Issues200Test extends JexlTestCase {
         List<String> ctl = Arrays.asList("g", "h", "i", "j", "k", "l");
         Assert.assertEquals(ctl, out);
     }
- 
+
     @Test
     public void test285a() throws Exception {
         List<String> out = new ArrayList<String>(6);
@@ -778,13 +783,13 @@ public class Issues200Test extends JexlTestCase {
         List<String> ctl = Arrays.asList("g", "h", "i", "j", "k", "l");
         Assert.assertEquals(ctl, out);
     }
-    
+
     @Test
     public void test285b() throws Exception {
         List<String> out = new ArrayList<String>(6);
         JexlContext ctxt = new MapContext();
         ctxt.set("$out", out);
-        String src = 
+        String src =
                   "for(b: ['g','h','i']) { $out.add(b); }\n"
                 + "for(var b: ['j','k','l']) { $out.add(b);}\n"
                 + "$out.size()";
@@ -796,14 +801,14 @@ public class Issues200Test extends JexlTestCase {
         List<String> ctl = Arrays.asList("g", "h", "i", "j", "k", "l");
         Assert.assertEquals(ctl, out);
     }
-    
+
     @Test
     public void test286() {
         String s286 = "var x = 0; for(x : 1..2){}; return x";
         JexlEngine jexl = new JexlBuilder().strict(true).create();
         Assert.assertEquals(2, jexl.createScript(s286).execute(null));
     }
-    
+
     @Test
     public void test287() {
         JexlContext ctxt = new MapContext();
@@ -848,7 +853,7 @@ public class Issues200Test extends JexlTestCase {
         }
         Assert.assertNull(result);
     }
-            
+
     @Test
     public void test289() {
         JexlContext ctxt = new MapContext();
@@ -861,7 +866,7 @@ public class Issues200Test extends JexlTestCase {
         result = script.execute(ctxt);
         Assert.assertNull(result);
     }
-    
+
     @Test
     public void test290a() throws Exception {
         Object result;
@@ -888,7 +893,7 @@ public class Issues200Test extends JexlTestCase {
                     } else {
                         Assert.assertTrue(src + ": " + xmethod.toString(), 
xmethod.toString().contains("nothing"));
                     }
-                } 
+                }
             }
         }
     }
@@ -908,7 +913,7 @@ public class Issues200Test extends JexlTestCase {
             Assert.assertNull(result);
         }
     }
-    
+
     @Test
     public void test291() throws Exception {
         final String str = "{1:'one'}[1]";
@@ -925,7 +930,7 @@ public class Issues200Test extends JexlTestCase {
         value = e.evaluate(ctxt);
         Assert.assertEquals("one", value);
     }
-        
+
     @Test
     public void testTemplate6565a() throws Exception {
         JexlEngine jexl = new JexlBuilder().create();
@@ -948,7 +953,7 @@ public class Issues200Test extends JexlTestCase {
         Assert.assertNotNull(refactored);
         Assert.assertEquals(source, refactored);
     }
-    
+
     @Test
     public void testTemplate6565b() throws Exception {
         JexlEngine jexl = new JexlBuilder().create();
@@ -971,4 +976,43 @@ public class Issues200Test extends JexlTestCase {
         Assert.assertNotNull(refactored);
         Assert.assertEquals(source, refactored);
     }
+
+    public static class Cls298 {
+        int sz = 42;
+
+        public int size() {
+            return sz;
+        }
+
+        public int size(int x) {
+            return sz + x;
+        }
+
+        public boolean isEmpty() {
+            return sz <= 0;
+        }
+    }
+
+    @Test
+    public void test298() throws Exception {
+        Cls298 c298 = new Cls298();
+        JexlContext ctxt = new MapContext();
+        JexlEngine jexl = new JexlBuilder().create();
+
+        String str = "c.size()";
+        JexlScript e = jexl.createScript(str, "c");
+        Object value = e.execute(ctxt, c298);
+        Assert.assertEquals(str, 42, value);
+
+        str = "size c";
+        e = jexl.createScript(str, "c");
+        value = e.execute(ctxt, c298);
+        Assert.assertEquals(str, 42, value);
+
+        str = "c.size(127)";
+        e = jexl.createScript(str, "c");
+        value = e.execute(ctxt, c298);
+        Assert.assertEquals(str, 169, value);
+
+    }
 }

Reply via email to