freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [05/21] incubator-freemarker git commit: FREEMARKER-63: Very early state. Simplified capturing assignment implementation
Date Mon, 07 Aug 2017 22:32:07 GMT
FREEMARKER-63:  Very early state. Simplified capturing assignment implementation


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

Branch: refs/heads/3
Commit: 146c42572c440dd4ef911d437239d3e54a7fe95b
Parents: fbbfadb
Author: ddekany <ddekany@apache.org>
Authored: Thu Jul 27 18:43:05 2017 +0200
Committer: ddekany <ddekany@apache.org>
Committed: Thu Jul 27 19:13:54 2017 +0200

----------------------------------------------------------------------
 .../core/CapturingAssignmentTest.java           | 63 ++++++++++++++
 .../core/ASTDirCapturingAssignment.java         | 87 +++++---------------
 .../org/apache/freemarker/core/Environment.java | 50 +++++------
 .../apache/freemarker/test/TemplateTest.java    |  2 +-
 4 files changed, 112 insertions(+), 90 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/146c4257/freemarker-core-test/src/test/java/org/apache/freemarker/core/CapturingAssignmentTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CapturingAssignmentTest.java
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CapturingAssignmentTest.java
new file mode 100644
index 0000000..44cf134
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CapturingAssignmentTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+import org.apache.freemarker.test.TemplateTest;
+import org.junit.Test;
+
+public class CapturingAssignmentTest extends TemplateTest {
+
+    @Test
+    public void testAssign() throws IOException, TemplateException {
+        assertOutput("<#assign x></#assign>[${x}]", "[]");
+        assertOutput("<#assign x><p>${1 + 1}</#assign>${x + '&'}",
"<p>2&");
+        assertOutput("<#ftl outputFormat='HTML'><#assign x><p>${1 + 1}</#assign>${x
+ '&'}", "<p>2&amp;");
+    }
+
+    @Test
+    public void testAssignNs() throws IOException, TemplateException {
+        addTemplate("lib.ftl", "");
+        assertOutput("<#import 'lib.ftl' as lib>"
+                + "<#assign x in lib></#assign>[${lib.x}]", "[]");
+        assertOutput("<#import 'lib.ftl' as lib>"
+                + "<#assign x in lib><p>${1 + 1}</#assign>${lib.x + '&'}",
"<p>2&");
+        assertOutput("<#ftl outputFormat='HTML'>"
+                + "<#import 'lib.ftl' as lib>"
+                + "<#assign x in lib><p>${1 + 1}</#assign>${lib.x + '&'}",
"<p>2&amp;");
+    }
+
+    @Test
+    public void testGlobal() throws IOException, TemplateException {
+        assertOutput("<#global x></#global>[${.globals.x}]", "[]");
+        assertOutput("<#global x><p>${1 + 1}</#global>${.globals.x + '&'}",
"<p>2&");
+        assertOutput("<#ftl outputFormat='HTML'><#global x><p>${1 + 1}</#global>${.globals.x
+ '&'}", "<p>2&amp;");
+    }
+
+    @Test
+    public void testLocal() throws IOException, TemplateException {
+        assertOutput("<#macro m><#local x></#local>[${x}]</#macro><@m/>${x!}",
"[]");
+        assertOutput("<#macro m><#local x><p>${1 + 1}</#local>${x
+ '&'}</#macro><@m/>${x!}", "<p>2&");
+        assertOutput("<#ftl outputFormat='HTML'>"
+                + "<#macro m><#local x><p>${1 + 1}</#local>${x +
'&'}</#macro><@m/>${x!}", "<p>2&amp;");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/146c4257/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
index 28edbf2..77fc8fa 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
@@ -21,14 +21,12 @@ package org.apache.freemarker.core;
 
 import java.io.IOException;
 import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Map;
 
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.TemplateModelException;
-import org.apache.freemarker.core.model.TemplateTransformModel;
 import org.apache.freemarker.core.model.impl.SimpleScalar;
 import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
+import org.apache.freemarker.core.util.BugException;
 
 /**
  * AST directive node: Like {@code <#local x>...</#local>}.
@@ -51,21 +49,29 @@ final class ASTDirCapturingAssignment extends ASTDirective {
     @Override
     ASTElement[] accept(Environment env) throws TemplateException, IOException {
         ASTElement[] children = getChildBuffer();
+
+        TemplateModel capturedValue;
         if (children != null) {
-            env.visitAndTransform(children, new CaptureOutput(env), null);
+            StringWriter out = new StringWriter();
+            env.visit(children, out);
+            capturedValue = capturedStringToModel(out.toString());
+        } else {
+            capturedValue = capturedStringToModel("");
+        }
+
+        if (namespaceExp != null) {
+            Environment.Namespace ns = (Environment.Namespace) namespaceExp.eval(env);
+            ns.put(varName, capturedValue);
+        } else if (scope == ASTDirAssignment.NAMESPACE) {
+            env.setVariable(varName, capturedValue);
+        } else if (scope == ASTDirAssignment.GLOBAL) {
+            env.setGlobalVariable(varName, capturedValue);
+        } else if (scope == ASTDirAssignment.LOCAL) {
+            env.setLocalVariable(varName, capturedValue);
         } else {
-            TemplateModel value = capturedStringToModel("");
-            if (namespaceExp != null) {
-                Environment.Namespace ns = (Environment.Namespace) namespaceExp.eval(env);
-                ns.put(varName, value);
-            } else if (scope == ASTDirAssignment.NAMESPACE) {
-                env.setVariable(varName, value);
-            } else if (scope == ASTDirAssignment.GLOBAL) {
-                env.setGlobalVariable(varName, value);
-            } else if (scope == ASTDirAssignment.LOCAL) {
-                env.setLocalVariable(varName, value);
-            }
+            throw new BugException("Unhandled scope");
         }
+
         return null;
     }
 
@@ -73,57 +79,6 @@ final class ASTDirCapturingAssignment extends ASTDirective {
         return markupOutputFormat == null ? new SimpleScalar(s) : markupOutputFormat.fromMarkup(s);
     }
 
-    private class CaptureOutput implements TemplateTransformModel {
-        private final Environment env;
-        private final Environment.Namespace fnsModel;
-        
-        CaptureOutput(Environment env) throws TemplateException {
-            this.env = env;
-            TemplateModel nsModel = null;
-            if (namespaceExp != null) {
-                nsModel = namespaceExp.eval(env);
-                if (!(nsModel instanceof Environment.Namespace)) {
-                    throw new NonNamespaceException(namespaceExp, nsModel, env);
-                }
-            }
-            fnsModel = (Environment.Namespace ) nsModel; 
-        }
-        
-        @Override
-        public Writer getWriter(Writer out, Map args) {
-            return new StringWriter() {
-                @Override
-                public void close() throws IOException {
-                    TemplateModel result;
-                    try {
-                        result = capturedStringToModel(toString());
-                    } catch (TemplateModelException e) {
-                        // [Java 1.6] e to cause
-                        throw new IOException("Failed to invoke FTL value from captured string:
" + e);
-                    }
-                    switch(scope) {
-                        case ASTDirAssignment.NAMESPACE: {
-                            if (fnsModel != null) {
-                                fnsModel.put(varName, result);
-                            } else {
-                                env.setVariable(varName, result);
-                            }
-                            break;
-                        }
-                        case ASTDirAssignment.LOCAL: {
-                            env.setLocalVariable(varName, result);
-                            break;
-                        }
-                        case ASTDirAssignment.GLOBAL: {
-                            env.setGlobalVariable(varName, result);
-                            break;
-                        }
-                    }
-                }
-            };
-        }
-    }
-    
     @Override
     protected String dump(boolean canonical) {
         StringBuilder sb = new StringBuilder();

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/146c4257/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
index 875366f..3be9fb5 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
@@ -499,32 +499,36 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
             ASTElement[] childBuffer,
             final StringToIndexMap loopVarNames, final TemplateModel[] loopVarValues,
             Writer out)
-            throws IOException, TemplateException {
-        // TODO [FM][CF] The plan is that `out` will be the root read only sink, so then
this won't be here.
-        Writer prevOut = this.out;
-        this.out = out;
-        try {
-            if (loopVarNames == null) {
-                visit(childBuffer);
-            } else {
-                pushLocalContext(new LocalContext() {
-                    @Override
-                    public TemplateModel getLocalVariable(String name) throws TemplateModelException
{
-                        int index = loopVarNames.get(name);
-                        return index != -1 ? loopVarValues[index] : null;
-                    }
+        throws IOException, TemplateException {
+        if (loopVarNames == null) { // This is by far the most frequent case
+            visit(childBuffer, out);
+        } else {
+            pushLocalContext(new LocalContext() {
+                @Override
+                public TemplateModel getLocalVariable(String name) throws TemplateModelException
{
+                    int index = loopVarNames.get(name);
+                    return index != -1 ? loopVarValues[index] : null;
+                }
 
-                    @Override
-                    public Collection<String> getLocalVariableNames() throws TemplateModelException
{
-                        return loopVarNames.getKeys();
-                    }
-                });
-                try {
-                    visit(childBuffer);
-                } finally {
-                    popLocalContext();
+                @Override
+                public Collection<String> getLocalVariableNames() throws TemplateModelException
{
+                    return loopVarNames.getKeys();
                 }
+            });
+            try {
+                visit(childBuffer, out);
+            } finally {
+                popLocalContext();
             }
+        }
+    }
+
+    void visit(ASTElement[] childBuffer, Writer out) throws IOException, TemplateException
{
+        // TODO [FM][CF] The plan is that `out` will be the root read only sink, so then
it will work differently
+        Writer prevOut = this.out;
+        this.out = out;
+        try {
+            visit(childBuffer);
         } finally {
             this.out = prevOut;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/146c4257/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
----------------------------------------------------------------------
diff --git a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
index 3ee5fb2..9e588d4 100644
--- a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
+++ b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
@@ -58,7 +58,7 @@ public abstract class TemplateTest {
     private Map<String, String> addedTemplates = new HashMap<>();
 
     /**
-     * Gets the {@link Configuration} used, automaticlly creating and setting if it wasn't
yet.
+     * Gets the {@link Configuration} used, automatically creating and setting if it wasn't
yet.
      */
     protected final Configuration getConfiguration() {
         if (configuration == null) {


Mime
View raw message