2013/7/16 <ma...@apache.org> > > Author: markt > Date: Tue Jul 16 20:01:47 2013 > New Revision: 1503857 > > URL: http://svn.apache.org/r1503857 > Log: > Fix handling of nested lambda expressions with method parameters. > > Removed: > tomcat/trunk/java/org/apache/el/parser/AstLambdaExpressionOrInvocation.java > Modified: > tomcat/trunk/java/javax/el/LambdaExpression.java > tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java > tomcat/trunk/java/org/apache/el/parser/ELParser.java > tomcat/trunk/java/org/apache/el/parser/ELParser.jjt > tomcat/trunk/java/org/apache/el/parser/ELParserTreeConstants.java > tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java > > 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=1503857&r1=1503856&r2=1503857&view=diff > ============================================================================== > --- tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java (original) > +++ tomcat/trunk/java/org/apache/el/parser/AstLambdaExpression.java Tue Jul 16 20:01:47 2013 > @@ -35,11 +35,15 @@ public class AstLambdaExpression extends > @Override > public Object getValue(EvaluationContext ctx) throws ELException { > > - // Two children - the formal parameters and the expression > + // First child is always parameters even if there aren't any > AstLambdaParameters formalParametersNode = > (AstLambdaParameters) children[0]; > Node[] formalParamNodes = formalParametersNode.children; > > + // Second child is a value expression > + ValueExpressionImpl ve = new ValueExpressionImpl("", children[1], > + ctx.getFunctionMapper(), ctx.getVariableMapper(), null); > + > // Build a LambdaExpression > List<String> formalParameters = new ArrayList<>(); > if (formalParamNodes != null) { > @@ -47,30 +51,29 @@ public class AstLambdaExpression extends > formalParameters.add(formalParamNode.getImage()); > } > } > - > - ValueExpressionImpl ve = new ValueExpressionImpl("", children[1], > - ctx.getFunctionMapper(), ctx.getVariableMapper(), null); > LambdaExpression le = new LambdaExpression(formalParameters, ve); > le.setELContext(ctx); > > if (formalParameters.isEmpty()) { > - // No formal parameters - should be able to simply invoke this > + // No formal parameters - invoke the expression > return le.invoke(ctx, (Object[]) null); > - } else { > - // Has parameters but they aren't provided so return the > - // LambdaExpression > - return le; > } > - } > > - @Override > - public Object invoke(EvaluationContext ctx, Class<?>[] paramTypes, > - Object[] paramValues) throws ELException { > - > - Object result = getValue(ctx); > + // If there are method parameters, need to invoke the expression with > + // those parameters. If there are multiple method parameters there > + // should be that many nested expressions. > + // If there are more nested expressions that parameters this will return > + // a LambdaExpression > + Object result = le; > + int i = 2; > + while (result instanceof LambdaExpression && i < jjtGetNumChildren()) { > + result = ((LambdaExpression) result).invoke( > + ((AstMethodParameters) children[i]).getParameters(ctx)); > + i++; > + } > > - if (result instanceof LambdaExpression) { > - result = ((LambdaExpression) result).invoke(ctx, paramValues); > + if (i < jjtGetNumChildren()) { > + throw new ELException(); > } > > return result;
Having the example from the test: (x->y->x-y)(2)(1) We may transform it like this: (()->y->2-y)()(1) So instead of returning right way when formalParameters.isEmpty() Shouldn't we have something like the one below in order to continue evaluation of the nested expression: --- org/apache/el/parser/AstLambdaExpression.java (revision 1504024) +++ org/apache/el/parser/AstLambdaExpression.java (working copy) @@ -54,9 +54,12 @@ LambdaExpression le = new LambdaExpression(formalParameters, ve); le.setELContext(ctx); + Object result = le; + int i = 2; if (formalParameters.isEmpty()) { // No formal parameters - invoke the expression - return le.invoke(ctx, (Object[]) null); + result = ((LambdaExpression) result).invoke(ctx, (Object[]) null); + i++; } // If there are method parameters, need to invoke the expression with @@ -64,8 +67,6 @@ // should be that many nested expressions. // If there are more nested expressions that parameters this will return // a LambdaExpression - Object result = le; - int i = 2; while (result instanceof LambdaExpression && i < jjtGetNumChildren()) { result = ((LambdaExpression) result).invoke( ((AstMethodParameters) children[i]).getParameters(ctx)); Regards Violeta > > 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=1503857&r1=1503856&r2=1503857&view=diff > ============================================================================== > --- tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java (original) > +++ tomcat/trunk/test/org/apache/el/parser/TestAstLambdaExpression.java Tue Jul 16 20:01:47 2013 > @@ -64,4 +64,14 @@ public class TestAstLambdaExpression { > Integer.class); > Assert.assertEquals(Integer.valueOf(120), result); > } > + > + > + @Test > + public void testSpec06() { > + ELProcessor processor = new ELProcessor(); > + Object result = > + processor.getValue("(x->y->x-y)(2)(1)", > + Integer.class); > + Assert.assertEquals(Integer.valueOf(1), result); > + } > } >