You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2019/08/17 20:16:32 UTC

[freemarker] 03/04: Finished local lambda expression AST API (overlooked this TODO in 2.3.29)

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

ddekany pushed a commit to branch 2.3-gae
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 0e0c2f953b470a48845b7d08f61cb4e6588d8264
Author: ddekany <dd...@apache.org>
AuthorDate: Sat Aug 17 19:45:24 2019 +0200

    Finished local lambda expression AST API (overlooked this TODO in 2.3.29)
---
 .../freemarker/core/LocalLambdaExpression.java     | 23 ++++---
 src/manual/en_US/book.xml                          |  3 +-
 src/test/java/freemarker/core/ASTTest.java         |  4 ++
 src/test/resources/freemarker/core/ast-lambda.ast  | 72 ++++++++++++++++++++++
 src/test/resources/freemarker/core/ast-lambda.ftl  | 23 +++++++
 5 files changed, 117 insertions(+), 8 deletions(-)

diff --git a/src/main/java/freemarker/core/LocalLambdaExpression.java b/src/main/java/freemarker/core/LocalLambdaExpression.java
index b7d1896..ece8d37 100644
--- a/src/main/java/freemarker/core/LocalLambdaExpression.java
+++ b/src/main/java/freemarker/core/LocalLambdaExpression.java
@@ -83,22 +83,31 @@ final class LocalLambdaExpression extends Expression {
 
     @Override
     int getParameterCount() {
-        return 2;
+        return lho.getParameters().size() + 1;
     }
 
     @Override
     Object getParameterValue(int idx) {
-        // TODO [lambda] should be similar to #function
-        switch (idx) {
-        case 0: return lho;
-        case 1: return rho;
-        default: throw new IndexOutOfBoundsException();
+        int paramCount = getParameterCount();
+        if (idx < paramCount - 1) {
+            return lho.getParameters().get(idx);
+        } else if (idx == paramCount - 1) {
+            return rho;
+        } else {
+            throw new IndexOutOfBoundsException();
         }
     }
 
     @Override
     ParameterRole getParameterRole(int idx) {
-        return ParameterRole.forBinaryOperatorOperand(idx);
+        int paramCount = getParameterCount();
+        if (idx < paramCount - 1) {
+            return ParameterRole.ARGUMENT_NAME;
+        } else if (idx == paramCount - 1) {
+            return ParameterRole.VALUE;
+        } else {
+            throw new IndexOutOfBoundsException();
+        }
     }
 
     LambdaParameterList getLambdaParameterList() {
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index a49e8ea..afb00b2 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -28689,7 +28689,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
           <itemizedlist>
             <listitem>
-              <para>[TODO]</para>
+              <para>Bug fixed: AST traversal API now can properly traverse the
+              inside of lambda expressions (such as the parameter list)</para>
             </listitem>
           </itemizedlist>
         </section>
diff --git a/src/test/java/freemarker/core/ASTTest.java b/src/test/java/freemarker/core/ASTTest.java
index 8a7dee1..b1b308e 100644
--- a/src/test/java/freemarker/core/ASTTest.java
+++ b/src/test/java/freemarker/core/ASTTest.java
@@ -69,6 +69,10 @@ public class ASTTest extends FileTestCase {
         testAST("ast-nestedignoredchildren");
     }
 
+    public void testLambda() throws Exception {
+        testAST("ast-lambda");
+    }
+
     public void testLocations() throws Exception {
         testASTWithLocations("ast-locations");
     }
diff --git a/src/test/resources/freemarker/core/ast-lambda.ast b/src/test/resources/freemarker/core/ast-lambda.ast
new file mode 100644
index 0000000..2b02f53
--- /dev/null
+++ b/src/test/resources/freemarker/core/ast-lambda.ast
@@ -0,0 +1,72 @@
+#mixed_content  // f.c.MixedContent
+    #text  // f.c.TextBlock
+        - content: "1 "  // String
+    ${...}  // f.c.DollarVariable
+        - content: ?filter(...)  // f.c.BuiltInsForSequences$filterBI
+            - left-hand operand: x  // f.c.Identifier
+            - right-hand operand: "filter"  // String
+            - argument value: ->  // f.c.LocalLambdaExpression
+                - argument name: x  // f.c.Identifier
+                - value: !  // f.c.NotExpression
+                    - right-hand operand: x  // f.c.Identifier
+    #text  // f.c.TextBlock
+        - content: "\n2 "  // String
+    ${...}  // f.c.DollarVariable
+        - content: ?filter(...)  // f.c.BuiltInsForSequences$filterBI
+            - left-hand operand: x  // f.c.Identifier
+            - right-hand operand: "filter"  // String
+            - argument value: ->  // f.c.LocalLambdaExpression
+                - argument name: x  // f.c.Identifier
+                - value: !  // f.c.NotExpression
+                    - right-hand operand: x  // f.c.Identifier
+    #text  // f.c.TextBlock
+        - content: "\n3 "  // String
+    ${...}  // f.c.DollarVariable
+        - content: ?filter(...)  // f.c.BuiltInsForSequences$filterBI
+            - left-hand operand: x  // f.c.Identifier
+            - right-hand operand: "filter"  // String
+            - argument value: ->  // f.c.LocalLambdaExpression
+                - argument name: x  // f.c.Identifier
+                - value: (...)  // f.c.ParentheticalExpression
+                    - enclosed operand: !  // f.c.NotExpression
+                        - right-hand operand: x  // f.c.Identifier
+    #text  // f.c.TextBlock
+        - content: "\n4 "  // String
+    ${...}  // f.c.DollarVariable
+        - content: ?filter(...)  // f.c.BuiltInsForSequences$filterBI
+            - left-hand operand: x  // f.c.Identifier
+            - right-hand operand: "filter"  // String
+            - argument value: ->  // f.c.LocalLambdaExpression
+                - argument name: x  // f.c.Identifier
+                - value: ||  // f.c.OrExpression
+                    - left-hand operand: ==  // f.c.ComparisonExpression
+                        - left-hand operand: +  // f.c.AddConcatExpression
+                            - left-hand operand: x  // f.c.Identifier
+                            - right-hand operand: 1  // f.c.NumberLiteral
+                        - right-hand operand: 2  // f.c.NumberLiteral
+                    - right-hand operand: ==  // f.c.ComparisonExpression
+                        - left-hand operand: /  // f.c.ArithmeticExpression
+                            - left-hand operand: x  // f.c.Identifier
+                            - right-hand operand: 2  // f.c.NumberLiteral
+                            - AST-node subtype: "2"  // Integer
+                        - right-hand operand: 4  // f.c.NumberLiteral
+    #text  // f.c.TextBlock
+        - content: "\n5 "  // String
+    ${...}  // f.c.DollarVariable
+        - content: ?filter(...)  // f.c.BuiltInsForSequences$filterBI
+            - left-hand operand: x  // f.c.Identifier
+            - right-hand operand: "filter"  // String
+            - argument value: ->  // f.c.LocalLambdaExpression
+                - argument name: x  // f.c.Identifier
+                - value: ?hasContent  // f.c.BuiltInsForExistenceHandling$has_contentBI
+                    - left-hand operand: ?filter(...)  // f.c.BuiltInsForSequences$filterBI
+                        - left-hand operand: x  // f.c.Identifier
+                        - right-hand operand: "filter"  // String
+                        - argument value: ->  // f.c.LocalLambdaExpression
+                            - argument name: y  // f.c.Identifier
+                            - value: ==  // f.c.ComparisonExpression
+                                - left-hand operand: y  // f.c.Identifier
+                                - right-hand operand: 1  // f.c.NumberLiteral
+                    - right-hand operand: "hasContent"  // String
+    #text  // f.c.TextBlock
+        - content: "\n"  // String
diff --git a/src/test/resources/freemarker/core/ast-lambda.ftl b/src/test/resources/freemarker/core/ast-lambda.ftl
new file mode 100644
index 0000000..974d3c0
--- /dev/null
+++ b/src/test/resources/freemarker/core/ast-lambda.ftl
@@ -0,0 +1,23 @@
+<#--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+1 ${x?filter(x -> !x)}
+2 ${x?filter((x) -> !x)}
+3 ${x?filter((x) -> (!x))}
+4 ${x?filter(x -> x + 1 == 2 || x / 2 == 4)}
+5 ${x?filter(x -> x?filter(y -> y == 1)?hasContent)}