freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [freemarker] branch 2.3-gae updated: Added special rule to allow using the directive name in the end-tag when ?with_args(...) was used in the start-tag, like <@myMacro?with_args(args)>...</@myMacro>.
Date Fri, 01 Nov 2019 18:40:55 GMT
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


The following commit(s) were added to refs/heads/2.3-gae by this push:
     new ea7cd6e  Added special rule to allow using the directive name in the end-tag when
?with_args(...) was used in the start-tag, like <@myMacro?with_args(args)>...</@myMacro>.
ea7cd6e is described below

commit ea7cd6ed00216cd2718a77ea3cd44e634e0ea8fd
Author: ddekany <ddekany@apache.org>
AuthorDate: Fri Nov 1 19:40:45 2019 +0100

    Added special rule to allow using the directive name in the end-tag when ?with_args(...)
was used in the start-tag, like <@myMacro?with_args(args)>...</@myMacro>.
---
 src/main/java/freemarker/core/MethodCall.java      |  4 ++
 src/main/javacc/FTL.jj                             | 13 +++-
 src/manual/en_US/book.xml                          | 16 +++++
 .../java/freemarker/core/EndTagSyntaxTest.java     | 76 ++++++++++++++++++++++
 4 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/src/main/java/freemarker/core/MethodCall.java b/src/main/java/freemarker/core/MethodCall.java
index 74e20a4..ab441aa 100644
--- a/src/main/java/freemarker/core/MethodCall.java
+++ b/src/main/java/freemarker/core/MethodCall.java
@@ -106,6 +106,10 @@ final class MethodCall extends Expression {
         return 1 + arguments.items.size();
     }
 
+    Expression getTarget() {
+        return target;
+    }
+
     @Override
     Object getParameterValue(int idx) {
         if (idx == 0) {
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index 184c8a4..cb80218 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -3585,8 +3585,17 @@ TemplateElement UnifiedMacroTransform() :
     start = <UNIFIED_CALL>
     exp = Expression()
     {
-        if (exp instanceof Identifier || (exp instanceof Dot && ((Dot) exp).onlyHasIdentifiers()))
{
-            startTagNameExp = exp;
+        // To allow <@foo.bar?withArgs(...)>...</@foo.bar>, but we also remove
superfluous (...):
+        Expression cleanedExp = exp;
+        if (cleanedExp instanceof MethodCall) {
+            Expression methodCallTarget = ((MethodCall) cleanedExp).getTarget();
+            if (methodCallTarget instanceof BuiltInsForCallables.with_argsBI) {
+                cleanedExp = ((BuiltInsForCallables.with_argsBI) methodCallTarget).target;
+            }
+        }
+
+        if (cleanedExp instanceof Identifier || (cleanedExp instanceof Dot && ((Dot)
cleanedExp).onlyHasIdentifiers())) {
+            startTagNameExp = cleanedExp;
         } else {
             startTagNameExp = null;
         }
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index afe59d7..a99606f 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -19869,6 +19869,14 @@ Same as:
           <programlisting role="output">  m2 does things with 1, 2, 3
   Delegate to m1:
   m1 does things with 1, 2, 3</programlisting>
+
+          <para>FreeMarker syntax allows using the name before the
+          <literal>?with_args(<replaceable>...</replaceable>)</literal>
in the
+          end-tag, just as if the
+          <literal>?with_args(<replaceable>...</replaceable>)</literal>
wasn't
+          there:</para>
+
+          <programlisting>&lt;@myMacro?with_args({'a': 1})&gt;...&lt;/<emphasis>@myMacro</emphasis>&gt;</programlisting>
         </section>
       </section>
     </chapter>
@@ -24273,6 +24281,14 @@ Or all above but with positional parameter passing (<link
             But
             <literal>&lt;@a_hash.foo&gt;<replaceable>...</replaceable>&lt;/@a_hash.foo&gt;</literal>
             is OK.</para>
+
+            <para>There's also a special rule that says that if the
+            <literal><replaceable>user_def_dir_exp</replaceable></literal>
+            ends with <literal><link
+            linkend="ref_builtin_with_args">?with_args(<replaceable>...</replaceable>)</link></literal>,
+            then that's ignored when the end-tag is matched, so you can write
+            something like
+            <literal>&lt;@myMacro?with_args(args)&gt;<replaceable>...</replaceable>&lt;/@myMacro&gt;</literal>.</para>
           </section>
 
           <section xml:id="ref_directive_userDefined_loopVar">
diff --git a/src/test/java/freemarker/core/EndTagSyntaxTest.java b/src/test/java/freemarker/core/EndTagSyntaxTest.java
new file mode 100644
index 0000000..f4e7500
--- /dev/null
+++ b/src/test/java/freemarker/core/EndTagSyntaxTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+package freemarker.core;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import freemarker.test.TemplateTest;
+
+public class EndTagSyntaxTest extends TemplateTest {
+
+    @Override
+    protected Configuration createConfiguration() throws Exception {
+        return new Configuration(Configuration.VERSION_2_3_29);
+    }
+
+    @Before
+    public void setup() {
+        addTemplate("common.ftl",
+                "<#macro m a=1>${a}[<#nested />]</#macro>" +
+                "<#assign ns={'m':m}>");
+        getConfiguration().addAutoInclude("common.ftl");
+    }
+
+    @Test
+    public void testSimple() throws IOException, TemplateException {
+        assertOutput("<@m>nested</@>", "1[nested]");
+        assertOutput("<@m a=2>nested</@>", "2[nested]");
+
+        assertOutput("<@ns.m>nested</@ns.m>", "1[nested]");
+        assertOutput("<@ns.m a=2>nested</@ns.m>", "2[nested]");
+
+        assertOutput("<@m>nested</@m>", "1[nested]");
+        assertOutput("<@m a=2>nested</@m>", "2[nested]");
+
+        assertOutput("<@ns.m>nested</@ns.m>", "1[nested]");
+        assertOutput("<@ns.m a=2>nested</@ns.m>", "2[nested]");
+
+        assertErrorContains("<@ns.m a=2>nested</@m>", "</@ns.m>");
+        assertErrorContains("<@m a=2>nested</@n>", "</@m>");
+    }
+
+    @Test
+    public void testWithArgs() throws IOException, TemplateException {
+        assertOutput("<@m?withArgs({})>nested</@m>", "1[nested]");
+        assertOutput("<@m?withArgs({}) a=2>nested</@m>", "2[nested]");
+
+        assertOutput("<@ns.m?withArgs({})>nested</@ns.m>", "1[nested]");
+        assertOutput("<@ns.m?withArgs({}) a=2>nested</@ns.m>", "2[nested]");
+
+        assertErrorContains("<@ns.m?withArgs({})>nested</@m>", "</@ns.m>");
+        assertErrorContains("<@m?withArgs({})>nested</@n>", "</@m>");
+    }
+
+}


Mime
View raw message