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)}