Author: markt Date: Thu Jul 18 20:56:44 2013 New Revision: 1504657 URL: http://svn.apache.org/r1504657 Log: Yet more adventures with lambda expressions. I suspect - but haven't yet checked - that there is scope to make the code more efficient and/or reduce duplication.
Modified: tomcat/trunk/java/org/apache/el/parser/AstFunction.java tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java Modified: tomcat/trunk/java/org/apache/el/parser/AstFunction.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstFunction.java?rev=1504657&r1=1504656&r2=1504657&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstFunction.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstFunction.java Thu Jul 18 20:56:44 2013 @@ -98,12 +98,18 @@ public final class AstFunction extends S // Build arguments int i = 0; while (obj instanceof LambdaExpression && - i < this.jjtGetNumChildren()) { + i < jjtGetNumChildren()) { Node args = jjtGetChild(i); obj = ((LambdaExpression) obj).invoke( ((AstMethodParameters) args).getParameters(ctx)); i++; } + if (i < jjtGetNumChildren()) { + // Haven't consumed all the sets of parameters therefore + // there were too many sets of parameters + throw new ELException(MessageFactory.get( + "error.lambda.tooManyMethodParameterSets")); + } return obj; } } Modified: tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java?rev=1504657&r1=1504656&r2=1504657&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java (original) +++ tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java Thu Jul 18 20:56:44 2013 @@ -36,22 +36,39 @@ public class AstLambdaExpression extends @Override public Object getValue(EvaluationContext ctx) throws ELException { - // Check that there are not more sets of method parameters than there - // are nested lambda expressions + // Check; + // - that there are not more sets of method parameters than there are + // nested lambda expressions + // - if any of the nested expressions declare formal parameters int methodParameterSetCount = jjtGetNumChildren() - 2; - if (methodParameterSetCount > 0) { - // We know this node is an expression - methodParameterSetCount--; - Node n = this.jjtGetChild(1); - while (methodParameterSetCount > 0) { - if (n.jjtGetNumChildren() <2 || - !(n.jjtGetChild(0) instanceof AstLambdaParameters)) { - throw new ELException(MessageFactory.get( - "error.lambda.tooManyMethodParameterSets")); + boolean declaresParameters = false; + // We know this node is an expression + int lambdaExpressionCount = 1; + // child at index 1 is the expression + Node n = jjtGetChild(1); + while (n instanceof AstLambdaExpression) { + lambdaExpressionCount++; + if (n.jjtGetChild(0) instanceof AstLambdaParameters) { + if (!declaresParameters && + n.jjtGetChild(0).jjtGetNumChildren() > 0) { + declaresParameters = true; } n = n.jjtGetChild(1); - methodParameterSetCount--; + } else { + n = null; + } + } + if (methodParameterSetCount > lambdaExpressionCount) { + throw new ELException(MessageFactory.get( + "error.lambda.tooManyMethodParameterSets")); + } + // Also need to check parents for declaration of formal parameters + n = parent; + while (!declaresParameters && n instanceof AstLambdaExpression) { + if (n.jjtGetChild(0).jjtGetNumChildren() > 0) { + declaresParameters = true; } + n = n.jjtGetParent(); } // First child is always parameters even if there aren't any @@ -74,10 +91,9 @@ public class AstLambdaExpression extends le.setELContext(ctx); if (jjtGetNumChildren() == 2) { - if (formalParameters.isEmpty() && - !(parent instanceof AstLambdaExpression)) { - // No formal parameters or method parameters and not a nested - // expression so invoke the expression. + if (formalParameters.isEmpty() && !declaresParameters) { + // No formal parameters or method parameters and not nested + // inside another lambda expression so invoke the expression. return le.invoke(ctx, (Object[]) null); } else { // Has formal parameters but no method parameters or is a nested Modified: tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java?rev=1504657&r1=1504656&r2=1504657&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java (original) +++ tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java Thu Jul 18 20:56:44 2013 @@ -147,11 +147,80 @@ public class TestAstLambdaExpression { @Test - public void testLambdaAsFunction() { + public void testNested07() { + ELProcessor processor = new ELProcessor(); + Object result = + processor.getValue("()->()->()->42", + Integer.class); + Assert.assertEquals(Integer.valueOf(42), result); + } + + + @Test + public void testLambdaAsFunction01() { ELProcessor processor = new ELProcessor(); Object result = processor.getValue("v = (x->y->x-y); v(2)(1)", Integer.class); Assert.assertEquals(Integer.valueOf(1), result); } + + + @Test + public void testLambdaAsFunction02() { + ELProcessor processor = new ELProcessor(); + Object result = + processor.getValue("v = (()->y->2-y); v()(1)", + Integer.class); + Assert.assertEquals(Integer.valueOf(1), result); + } + + + @Test + public void testLambdaAsFunction03() { + ELProcessor processor = new ELProcessor(); + Object result = + processor.getValue("v = (()->y->()->2-y); v()(1)()", + Integer.class); + Assert.assertEquals(Integer.valueOf(1), result); + } + + + @Test(expected=ELException.class) + public void testLambdaAsFunction04() { + ELProcessor processor = new ELProcessor(); + // More method parameters than there are nested lambda expressions + processor.getValue("v = (()->y->()->2-y); v()(1)()()", + Integer.class); + } + + + @Test + public void testLambdaAsFunction05() { + ELProcessor processor = new ELProcessor(); + Object result = + processor.getValue("v = (()->y->()->x->x-y); v()(1)()(2)", + Integer.class); + Assert.assertEquals(Integer.valueOf(1), result); + } + + + @Test + public void testLambdaAsFunction06() { + ELProcessor processor = new ELProcessor(); + Object result = + processor.getValue("v = (()->y->()->()->x->x-y); v()(1)()()(2)", + Integer.class); + Assert.assertEquals(Integer.valueOf(1), result); + } + + + @Test + public void testLambdaAsFunction07() { + ELProcessor processor = new ELProcessor(); + Object result = + processor.getValue("v = (()->y->()->()->x->x-y); v()(1)()(3)(2)", + Integer.class); + Assert.assertEquals(Integer.valueOf(1), result); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org