freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [10/11] incubator-freemarker git commit: FREEMARKER-83: Modified how .macro_caller_template_name works... now it has no surprising restrictions, and is simpler.
Date Fri, 09 Mar 2018 21:50:16 GMT
FREEMARKER-83: Modified how .macro_caller_template_name works... now it has no surprising restrictions,
and is simpler.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/7adecaee
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/7adecaee
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/7adecaee

Branch: refs/heads/2.3
Commit: 7adecaee25f2c5dddc8c75ff2aeb54fbefbf8458
Parents: 4a5eec4
Author: ddekany <ddekany@apache.org>
Authored: Fri Mar 9 22:38:35 2018 +0100
Committer: ddekany <ddekany@apache.org>
Committed: Fri Mar 9 22:38:35 2018 +0100

----------------------------------------------------------------------
 .../java/freemarker/core/BuiltinVariable.java   | 15 ++++----
 src/main/java/freemarker/core/Environment.java  | 36 ++------------------
 src/main/java/freemarker/core/Macro.java        |  6 ++--
 src/main/java/freemarker/core/UnifiedCall.java  |  2 +-
 src/manual/en_US/book.xml                       | 17 +++------
 .../core/MacroCallerTemplateNameTest.java       | 36 +++++++++++---------
 6 files changed, 38 insertions(+), 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7adecaee/src/main/java/freemarker/core/BuiltinVariable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltinVariable.java b/src/main/java/freemarker/core/BuiltinVariable.java
index 9b9b135..13dd67d 100644
--- a/src/main/java/freemarker/core/BuiltinVariable.java
+++ b/src/main/java/freemarker/core/BuiltinVariable.java
@@ -22,6 +22,7 @@ package freemarker.core;
 import java.util.Arrays;
 import java.util.Date;
 
+import freemarker.core.Macro.Context;
 import freemarker.template.Configuration;
 import freemarker.template.SimpleDate;
 import freemarker.template.SimpleScalar;
@@ -30,6 +31,7 @@ import freemarker.template.TemplateException;
 import freemarker.template.TemplateHashModel;
 import freemarker.template.TemplateModel;
 import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateScalarModel;
 import freemarker.template._TemplateAPI;
 import freemarker.template.utility.StringUtil;
 
@@ -253,14 +255,13 @@ final class BuiltinVariable extends Expression {
             return GetOptionalTemplateMethod.INSTANCE_CC;
         }
         if (name == MACRO_CALLER_TEMPLATE_NAME || name == MACRO_CALLER_TEMPLATE_NAME_CC)
{
-            UnifiedCall caller;
-            try {
-                caller = env.getMacroCaller();
-            } catch (IllegalStateException e) {
-                throw new TemplateException("Failed to resolve ." + name + ": " + e.getMessage(),
e, env);
+            Context ctx = env.getCurrentMacroContext();
+            if (ctx == null) {
+                throw new TemplateException(
+                        "Can't get ." + name + " here, as there's no macro call in context.",
env);
             }
-            String name = caller.getTemplate().getName();
-            return name != null ? new SimpleScalar(name) : SimpleScalar.EMPTY_STRING;
+            String name = ctx.callPlace.getTemplate().getName();
+            return name != null ? new SimpleScalar(name) : TemplateScalarModel.EMPTY_STRING;
         }
         
         throw new _MiscTemplateException(this,

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7adecaee/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 5f20c26..2d4b585 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -281,36 +281,6 @@ public final class Environment extends Configurable {
     }
 
     /**
-     * Gets the non-{@code null} {@link UnifiedCall} of the caller of the macro whose context
we are in; note
-     * that you can't call this from everywhere. Specifically, the FTL call stack must not
contain {@code #nested} or a
-     * call to user-defined-directive after the stack entry of the {@code #macro} directive.
This practically means that
-     * this should be called on the top-level inside {@code #macro}, or inside some core
directives like {@code #if}.
-     * 
-     * @throws IllegalStateException
-     *             If there's no macro caller or it can't be figured out at this point of
the template execution.
-     */
-    UnifiedCall getMacroCaller() throws IllegalStateException {
-        for (int ln = instructionStackSize - 1; ln > 0; ln--) {
-            TemplateElement te = instructionStack[ln];
-            if (te instanceof Macro) {
-                TemplateElement macroCaller = instructionStack[ln - 1];
-                if (macroCaller instanceof UnifiedCall) {
-                    return (UnifiedCall) macroCaller;
-                }
-            }
-            // Avoid returning the caller of @nested in `<#macro called><@inner>${getMacroCallerHere()}</@></#macro>`;
-            // the #macro that defines "inner" would break our logic above.
-            if (te instanceof BodyInstruction) {
-                throw new IllegalStateException(
-                        "Can't get the location of the macro caller here, because you are
inside an user-defined "
-                        + "directive call that's nested inside the #macro directive. (You
may "
-                        + "need to get the caller location earlier, and store it in a local
variable for later use.)");
-            }
-        }
-        throw new IllegalStateException("There's no macro caller at this point.");
-    }
-
-    /**
      * Deletes cached values that meant to be valid only during a single template execution.
      */
     private void clearCachedValues() {
@@ -624,7 +594,7 @@ public final class Environment extends Configurable {
     void invokeNestedContent(BodyInstruction.Context bodyCtx) throws TemplateException, IOException
{
         Macro.Context invokingMacroContext = getCurrentMacroContext();
         LocalContextStack prevLocalContextStack = localContextStack;
-        TemplateElement[] nestedContentBuffer = invokingMacroContext.nestedContentBuffer;
+        TemplateElement[] nestedContentBuffer = invokingMacroContext.callPlace.getChildBuffer();
         if (nestedContentBuffer != null) {
             this.currentMacroContext = invokingMacroContext.prevMacroContext;
             currentNamespace = invokingMacroContext.nestedContentNamespace;
@@ -765,7 +735,7 @@ public final class Environment extends Configurable {
      */
     void invoke(Macro macro,
             Map namedArgs, List positionalArgs,
-            List bodyParameterNames, TemplateElement[] childBuffer) throws TemplateException,
IOException {
+            List bodyParameterNames, TemplateElement callPlace) throws TemplateException,
IOException {
         if (macro == Macro.DO_NOTHING_MACRO) {
             return;
         }
@@ -780,7 +750,7 @@ public final class Environment extends Configurable {
             elementPushed = false;
         }
         try {
-            final Macro.Context macroCtx = macro.new Context(this, childBuffer, bodyParameterNames);
+            final Macro.Context macroCtx = macro.new Context(this, callPlace, bodyParameterNames);
             // Causes the evaluation of argument expressions:
             setMacroContextLocalsFromArguments(macroCtx, macro, namedArgs, positionalArgs);
             

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7adecaee/src/main/java/freemarker/core/Macro.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Macro.java b/src/main/java/freemarker/core/Macro.java
index 2ea9c2c..9f743cb 100644
--- a/src/main/java/freemarker/core/Macro.java
+++ b/src/main/java/freemarker/core/Macro.java
@@ -154,17 +154,17 @@ public final class Macro extends TemplateElement implements TemplateModel
{
 
     class Context implements LocalContext {
         final Environment.Namespace localVars; 
-        final TemplateElement[] nestedContentBuffer;
+        final TemplateElement callPlace;
         final Environment.Namespace nestedContentNamespace;
         final List nestedContentParameterNames;
         final LocalContextStack prevLocalContextStack;
         final Context prevMacroContext;
         
         Context(Environment env, 
-                TemplateElement[] nestedContentBuffer,
+                TemplateElement callPlace,
                 List nestedContentParameterNames) {
             this.localVars = env.new Namespace(); 
-            this.nestedContentBuffer = nestedContentBuffer;
+            this.callPlace = callPlace;
             this.nestedContentNamespace = env.getCurrentNamespace();
             this.nestedContentParameterNames = nestedContentParameterNames;
             this.prevLocalContextStack = env.getLocalContextStack();

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7adecaee/src/main/java/freemarker/core/UnifiedCall.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/UnifiedCall.java b/src/main/java/freemarker/core/UnifiedCall.java
index f445cd3..68777d3 100644
--- a/src/main/java/freemarker/core/UnifiedCall.java
+++ b/src/main/java/freemarker/core/UnifiedCall.java
@@ -80,7 +80,7 @@ final class UnifiedCall extends TemplateElement implements DirectiveCallPlace
{
                         + "Functions can only be called from expressions, like in ${f()},
${x + f()} or ",
                         "<@someDirective someParam=f() />", ".");
             }    
-            env.invoke(macro, namedArgs, positionalArgs, bodyParameterNames, getChildBuffer());
+            env.invoke(macro, namedArgs, positionalArgs, bodyParameterNames, this);
         } else {
             boolean isDirectiveModel = tm instanceof TemplateDirectiveModel; 
             if (isDirectiveModel || tm instanceof TemplateTransformModel) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7adecaee/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 6c9c8bb..f45a516 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -23316,19 +23316,10 @@ There was no specific handler for node y
             </indexterm><literal>macro_caller_template_name</literal>:
Returns
           the name (path) of the template from which the current macro was
           called. It's mostly useful if you want to resolve paths relative to
-          the caller template. If the caller template is nameless, this will
-          be an empty string (not a missing value). Reading this variable will
-          cause error if you aren't inside a macro call, also if you are
-          inside an user-defined directive call
-          (<literal>&lt;@<replaceable>...</replaceable>&gt;</literal>)
that's
-          nested inside the <literal>macro</literal> directive (as in
-          <literal>&lt;#macro
-          m&gt;&lt;@x&gt;${.macro_caller_template_name}&lt;#-- FAILS!
-          --&gt;&lt;/@&gt;&lt;/#macro&gt;</literal>). (Note that
if <link
-          linkend="pgui_config_incompatible_improvements">incompatible
-          improvements</link> is set to less than 2.3.28, then when using this
-          variable in an argument to a macro, it will be incorrectly evaluated
-          to the caller of the called macro.)</para>
+          the caller template. To serve that purpose better, if the caller
+          template is nameless, this will be an empty string (not a missing
+          value). Reading this variable will cause error if you aren't inside
+          a macro call.</para>
         </listitem>
 
         <listitem>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7adecaee/src/test/java/freemarker/core/MacroCallerTemplateNameTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/MacroCallerTemplateNameTest.java b/src/test/java/freemarker/core/MacroCallerTemplateNameTest.java
index 32b1d4e..5a26b8f 100644
--- a/src/test/java/freemarker/core/MacroCallerTemplateNameTest.java
+++ b/src/test/java/freemarker/core/MacroCallerTemplateNameTest.java
@@ -35,28 +35,31 @@ public class MacroCallerTemplateNameTest extends TemplateTest {
 
     @Test
     public void testNoCaller() throws Exception {
-        assertErrorContains("${.macroCallerTemplateName}", "no macro caller", ".macroCallerTemplateName");
-        assertErrorContains("${.macro_caller_template_name}", "no macro caller", ".macro_caller_template_name");
+        assertErrorContains("${.macroCallerTemplateName}", "no macro call", ".macroCallerTemplateName");
+        assertErrorContains("${.macro_caller_template_name}", "no macro call", ".macro_caller_template_name");
 
         assertErrorContains(""
                 + "<#macro m><#nested></#macro>"
                 + "<@m>${.macroCallerTemplateName}</@>",
-                "nested", ".macroCallerTemplateName");
+                "no macro call", ".macroCallerTemplateName");
 
-        assertErrorContains(""
+        addTemplate("main.ftl", "${.macroCallerTemplateName}");
+        assertErrorContainsForNamed("main.ftl", "no macro call");
+    }
+
+    @Test
+    public void testNested() throws Exception {
+        assertOutput(""
                 + "<#macro m><#nested></#macro>"
                 + "<#macro m2><@m>${.macroCallerTemplateName}</@></#macro>"
-                + "<@m2/>",
-                "nested", ".macroCallerTemplateName");
+                + "[<@m2/>]",
+                "[]");
         assertOutput(""
                 + "<#macro m2>${.macroCallerTemplateName}</#macro>"
                 + "[<@m2/>]",
                 "[]");
-
-        addTemplate("main.ftl", "${.macroCallerTemplateName}");
-        assertErrorContainsForNamed("main.ftl", "no macro caller");
     }
-
+    
     @Test
     public void testSameTemplateCaller() throws Exception {
         addTemplate("main.ftl", ""
@@ -127,13 +130,12 @@ public class MacroCallerTemplateNameTest extends TemplateTest {
                 + "</#macro>"
                 + "<#macro m2><@m .macroCallerTemplateName /></#macro>");
         
-        assertOutputForNamed("main.ftl", ""
-                + "x: main.ftl; y: main.ftl; caller: main.ftl;"
-                + "x: main.ftl; y: inc.ftl; caller: inc.ftl;");
-        getConfiguration().setIncompatibleImprovements(Configuration.VERSION_2_3_27);
-        assertOutputForNamed("main.ftl", ""
-                + "x: main.ftl; y: main.ftl; caller: main.ftl;"
-                + "x: inc.ftl; y: inc.ftl; caller: inc.ftl;");
+        for (int i = 0; i < 2; i++) {
+            assertOutputForNamed("main.ftl", ""
+                    + "x: main.ftl; y: main.ftl; caller: main.ftl;"
+                    + "x: main.ftl; y: inc.ftl; caller: inc.ftl;");
+            getConfiguration().setIncompatibleImprovements(Configuration.VERSION_2_3_27);
// Has no effect
+        }
     }
     
     @Test


Mime
View raw message