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 2017/05/15 21:23:48 UTC
[32/51] [abbrv] [partial] incubator-freemarker git commit:
Restructured project so that freemarker-test-utils depends on freemarker-core
(and hence can provide common classes for testing templates,
and can use utility classes defined in the core). As a c
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java
new file mode 100644
index 0000000..4602b67
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java
@@ -0,0 +1,79 @@
+/*
+ * 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.test.templatesuite.models;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.model.TemplateHashModel;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateScalarModel;
+import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
+import org.apache.freemarker.core.model.impl.SimpleHash;
+import org.apache.freemarker.core.util.HtmlEscape;
+import org.apache.freemarker.core.util.StandardCompress;
+
+/**
+ * Part of the TestTransform testcase suite.
+ */
+public class TransformHashWrapper implements TemplateHashModel,
+ TemplateScalarModel {
+
+ private ObjectWrapper ow = new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build();
+ private SimpleHash m_cHashModel = new SimpleHash(ow);
+
+ /** Creates new TransformHashWrapper */
+ public TransformHashWrapper() {
+ m_cHashModel.put( "htmlEscape", new HtmlEscape() );
+ m_cHashModel.put( "compress", new StandardCompress() );
+ m_cHashModel.put( "escape", new TransformMethodWrapper1() );
+ m_cHashModel.put( "special", new TransformMethodWrapper2() );
+ }
+
+ /**
+ * Gets a <tt>TemplateModel</tt> from the hash.
+ *
+ * @param key the name by which the <tt>TemplateModel</tt>
+ * is identified in the template.
+ * @return the <tt>TemplateModel</tt> referred to by the key,
+ * or null if not found.
+ */
+ @Override
+ public TemplateModel get(String key) throws TemplateModelException {
+ return m_cHashModel.get( key );
+ }
+
+ /**
+ * @return true if this object is empty.
+ */
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ /**
+ * Returns the scalar's value as a String.
+ * @return the String value of this scalar.
+ */
+ @Override
+ public String getAsString() {
+ return "Utility transformations";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper1.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper1.java b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper1.java
new file mode 100644
index 0000000..8311134
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper1.java
@@ -0,0 +1,49 @@
+/*
+ * 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.test.templatesuite.models;
+
+import java.util.List;
+
+import org.apache.freemarker.core.model.TemplateMethodModel;
+import org.apache.freemarker.core.util.HtmlEscape;
+import org.apache.freemarker.core.util.XmlEscape;
+
+/**
+ * Simple test of the interaction between MethodModels and TransformModels.
+ */
+public class TransformMethodWrapper1 implements TemplateMethodModel {
+
+ /**
+ * Executes a method call.
+ *
+ * @param arguments a <tt>List</tt> of <tt>String</tt> objects containing
+ * the values of the arguments passed to the method.
+ * @return the <tt>TemplateModel</tt> produced by the method, or null.
+ */
+ @Override
+ public Object exec(List arguments) {
+
+ if (( arguments.size() > 0 ) && ( arguments.get( 0 ).toString().equals( "xml" ))) {
+ return new XmlEscape();
+ } else {
+ return new HtmlEscape();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper2.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper2.java b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper2.java
new file mode 100644
index 0000000..96eb1a5
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformMethodWrapper2.java
@@ -0,0 +1,64 @@
+/*
+ * 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.test.templatesuite.models;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.freemarker.core.model.TemplateMethodModel;
+
+/**
+ * Another test of the interaction between MethodModels and TransformModels.
+ */
+public class TransformMethodWrapper2 implements TemplateMethodModel {
+
+ /**
+ * Executes a method call.
+ *
+ * @param arguments a <tt>List</tt> of <tt>String</tt> objects containing
+ * the values of the arguments passed to the method.
+ * @return the <tt>TemplateModel</tt> produced by the method, or null.
+ */
+ @Override
+ public Object exec(List arguments) {
+ TransformModel1 cTransformer = new TransformModel1();
+ Iterator iArgument = arguments.iterator();
+
+ // Sets up properties of the Transform model based on the arguments
+ // passed into this method
+
+ while ( iArgument.hasNext() ) {
+ String aArgument = (String) iArgument.next();
+
+ if ( aArgument.equals( "quote" )) {
+ cTransformer.setQuotes( true );
+ } else if ( aArgument.equals( "tag" )) {
+ cTransformer.setTags( true );
+ } else if ( aArgument.equals( "ampersand" )) {
+ cTransformer.setAmpersands( true );
+ } else {
+ cTransformer.setComment( aArgument );
+ }
+ }
+
+ // Now return the transform class.
+ return cTransformer;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformModel1.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformModel1.java b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformModel1.java
new file mode 100644
index 0000000..0875679
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformModel1.java
@@ -0,0 +1,175 @@
+/*
+ * 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.test.templatesuite.models;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.freemarker.core.model.TemplateTransformModel;
+
+/**
+ * A TemplateTransformModel that includes properties. These properties can be
+ * set at model construction time, or, for the purposes of this demonstration,
+ * can be passed in from a wrapper TemplateMethodModel.
+ */
+public class TransformModel1 implements TemplateTransformModel {
+
+ private boolean m_bAmpersands = false;
+ private boolean m_bQuotes = false;
+ private boolean m_bTags = false;
+ private String m_aComment = "";
+
+ private static final int READER_BUFFER_SIZE = 4096;
+
+ @Override
+ public Writer getWriter(final Writer out,
+ final Map args) {
+ final StringBuilder buf = new StringBuilder();
+ return new Writer(out) {
+ @Override
+ public void write(char cbuf[], int off, int len) {
+ buf.append(cbuf, off, len);
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws IOException {
+ StringReader sr = new StringReader(buf.toString());
+ StringWriter sw = new StringWriter();
+ transform(sr, sw);
+ out.write(sw.toString());
+ }
+ };
+ }
+
+
+ /**
+ * Indicates whether we escape ampersands. This property can be set either
+ * while the model is being constructed, or via a property passed in through
+ * a <code>TemplateMethodModel</code>.
+ */
+ public void setAmpersands( boolean bAmpersands ) {
+ m_bAmpersands = bAmpersands;
+ }
+
+ /**
+ * Indicates whether we escape quotes. This property can be set either
+ * while the model is being constructed, or via a property passed in through
+ * a <code>TemplateMethodModel</code>.
+ */
+ public void setQuotes( boolean bQuotes ) {
+ m_bQuotes = bQuotes;
+ }
+
+ /**
+ * Indicates whether we escape tags. This property can be set either
+ * while the model is being constructed, or via a property passed in through
+ * a <code>TemplateMethodModel</code>.
+ */
+ public void setTags( boolean bTags ) {
+ m_bTags = bTags;
+ }
+
+ /**
+ * Sets a comment for this transformation. This property can be set either
+ * while the model is being constructed, or via a property passed in through
+ * a <code>TemplateMethodModel</code>.
+ */
+ public void setComment( String aComment ) {
+ m_aComment = aComment;
+ }
+
+ /**
+ * Performs a transformation/filter on FreeMarker output.
+ *
+ * @param source the input to be transformed
+ * @param output the destination of the transformation
+ */
+ public void transform(Reader source, Writer output)
+ throws IOException {
+ // Output the source, converting unsafe certain characters to their
+ // equivalent entities.
+ int n = 0;
+ boolean bCommentSent = false;
+ char[] aBuffer = new char[ READER_BUFFER_SIZE ];
+ int i = source.read( aBuffer );
+ while (i >= 0) {
+ for ( int j = 0; j < i; j++ ) {
+ char c = aBuffer[j];
+ switch (c) {
+ case '&':
+ if ( m_bAmpersands ) {
+ output.write("&");
+ } else {
+ output.write( c );
+ }
+ break;
+ case '<':
+ if ( m_bTags ) {
+ output.write("<");
+ } else {
+ output.write( c );
+ }
+ break;
+ case '>':
+ if ( m_bTags ) {
+ output.write(">");
+ } else {
+ output.write( c );
+ }
+ break;
+ case '"':
+ if ( m_bQuotes ) {
+ output.write(""");
+ } else {
+ output.write( c );
+ }
+ break;
+ case '\'':
+ if ( m_bQuotes ) {
+ output.write("'");
+ } else {
+ output.write( c );
+ }
+ break;
+ case '*':
+ if ( ! bCommentSent ) {
+ output.write( m_aComment );
+ bCommentSent = true;
+ } else {
+ output.write( c );
+ }
+ break;
+ default:
+ output.write(c);
+ }
+ n++;
+ }
+ i = source.read( aBuffer );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/VarArgTestModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/VarArgTestModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/VarArgTestModel.java
new file mode 100644
index 0000000..940cb17
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/models/VarArgTestModel.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.test.templatesuite.models;
+
+import java.util.Date;
+
+public class VarArgTestModel {
+
+ public int bar(Integer... xs) {
+ int sum = 0;
+ for (Integer x : xs) {
+ if (x != null) {
+ sum *= 100;
+ sum += x;
+ }
+ }
+ return sum;
+ }
+
+ public int bar2(int first, int... xs) {
+ int sum = 0;
+ for (int x : xs) {
+ sum *= 100;
+ sum += x;
+ }
+ return -(sum * 100 + first);
+ }
+
+ public int overloaded(int x, int y) {
+ return x * 100 + y;
+ }
+
+ public int overloaded(int... xs) {
+ int sum = 0;
+ for (int x : xs) {
+ sum *= 100;
+ sum += x;
+ }
+ return -sum;
+ }
+
+ public String noVarArgs(String s, boolean b, int i, Date d) {
+ return s + ", " + b + ", " + i + ", " + d.getTime();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/package.html
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/package.html b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/package.html
new file mode 100644
index 0000000..cabffb0
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/test/templatesuite/package.html
@@ -0,0 +1,42 @@
+<!--
+ 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.
+-->
+<html>
+<head>
+</head>
+<body>
+
+<p>JUnit test-suite that processes FreeMarker templates and compare their
+output to reference files.</p>
+
+<p>To add a test-case, go to
+<tt>src/test/resources/freemarker/test/templatesuite/</tt> and inside that
+directory:</p>
+<ol>
+ <li>Add a template to under <tt>templates/</tt> with whatever meaningful
+ file name</li>
+ <li>Add the expected output to <tt>references/</tt> with exactly the same
+ file name</li>
+ <li>Add a new <tt>testcase</tt> elemen to <tt>testcases.xml</tt></li>
+ <li>If you want to add items to the data-model or do something else special,
+ modify the <tt>setUp()</tt> method in
+ <tt>src/test/java/freemarker/test/templatesuite/TemplateTestCase.java</tt>
+ </li>
+</ol>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ast
new file mode 100644
index 0000000..1cdd496
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ast
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+#mixed_content // o.a.f.c.ASTImplicitParent
+ #text // o.a.f.c.ASTStaticText
+ - content: "1 " // String
+ @ // o.a.f.c.ASTDirUserDefined
+ - callee: foo // o.a.f.c.ASTExpVariable
+ - argument name: "x" // String
+ - argument value: 1 // o.a.f.c.ASTExpNumberLiteral
+ - argument name: "y" // String
+ - argument value: 2 // o.a.f.c.ASTExpNumberLiteral
+ - target loop variable: "b1" // String
+ - target loop variable: "b2" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "x" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n2 " // String
+ @ // o.a.f.c.ASTDirUserDefined
+ - callee: . // o.a.f.c.ASTExpDot
+ - left-hand operand: ns // o.a.f.c.ASTExpVariable
+ - right-hand operand: "bar" // String
+ - argument value: 1 // o.a.f.c.ASTExpNumberLiteral
+ - argument value: 2 // o.a.f.c.ASTExpNumberLiteral
+ - target loop variable: "b1" // String
+ - target loop variable: "b2" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "y" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n3 " // String
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 123 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 123 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: ns // o.a.f.c.ASTExpVariable
+ #global // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 123 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "3" // Integer
+ - namespace: null // Null
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n4 " // String
+ #if-#elseif-#else-container // o.a.f.c.ASTDirIfElseIfElseContainer
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf
+ - condition: == // o.a.f.c.ASTExpComparison
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: x // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: 0 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText
+ - content: "foo" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: y // o.a.f.c.ASTExpVariable
+ #text // o.a.f.c.ASTStaticText
+ - content: "bar" // String
+ #else // o.a.f.c.ASTDirIfOrElseOrElseIf
+ - condition: null // Null
+ - AST-node subtype: "1" // Integer
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: "static" // o.a.f.c.ASTExpStringLiteral
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: dynamic "..." // o.a.f.c.ASTExpStringLiteral
+ - value part: "x" // String
+ - value part: ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: * // o.a.f.c.ArithmeticExpression
+ - left-hand operand: baaz // o.a.f.c.ASTExpVariable
+ - right-hand operand: 10 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "1" // Integer
+ - value part: "y" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n5 " // String
+ #switch // o.a.f.c.ASTDirSwitch
+ - value: x // o.a.f.c.ASTExpVariable
+ #case // o.a.f.c.ASTDirCase
+ - condition: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText
+ - content: "one" // String
+ #case // o.a.f.c.ASTDirCase
+ - condition: 2 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText
+ - content: "two" // String
+ #default // o.a.f.c.ASTDirCase
+ - condition: null // Null
+ - AST-node subtype: "1" // Integer
+ #text // o.a.f.c.ASTStaticText
+ - content: "more" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n6 " // String
+ #macro // o.a.f.c.ASTDirMacro
+ - assignment target: "foo" // String
+ - parameter name: "x" // String
+ - parameter default: null // Null
+ - parameter name: "y" // String
+ - parameter default: 2 // o.a.f.c.ASTExpNumberLiteral
+ - parameter name: "z" // String
+ - parameter default: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: y // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - catch-all parameter name: "q" // String
+ - AST-node subtype: "0" // Integer
+ #nested // o.a.f.c.ASTDirNested
+ - passed value: x // o.a.f.c.ASTExpVariable
+ - passed value: y // o.a.f.c.ASTExpVariable
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n7 " // String
+ #function // o.a.f.c.ASTDirMacro
+ - assignment target: "foo" // String
+ - parameter name: "x" // String
+ - parameter default: null // Null
+ - parameter name: "y" // String
+ - parameter default: null // Null
+ - catch-all parameter name: null // Null
+ - AST-node subtype: "1" // Integer
+ #local // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 123 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "2" // Integer
+ - namespace: null // Null
+ #return // o.a.f.c.ASTDirReturn
+ - value: 1 // o.a.f.c.ASTExpNumberLiteral
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n8 " // String
+ #list // o.a.f.c.ASTDirList
+ - list source: xs // o.a.f.c.ASTExpVariable
+ - target loop variable: "x" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n9 " // String
+ #list-#else-container // o.a.f.c.ASTDirListElseContainer
+ #list // o.a.f.c.ASTDirList
+ - list source: xs // o.a.f.c.ASTExpVariable
+ #text // o.a.f.c.ASTStaticText
+ - content: "[" // String
+ #items // o.a.f.c.ASTDirItems
+ - target loop variable: "x" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: x // o.a.f.c.ASTExpVariable
+ #sep // o.a.f.c.ASTDirSep
+ #text // o.a.f.c.ASTStaticText
+ - content: ", " // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "]" // String
+ #else // o.a.f.c.ASTDirElseOfList
+ #text // o.a.f.c.ASTStaticText
+ - content: "None" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n10 " // String
+ #--...-- // o.a.f.c.ASTComment
+ - content: " A comment " // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n11 " // String
+ #outputformat // o.a.f.c.ASTDirOutputFormat
+ - value: "XML" // o.a.f.c.ASTExpStringLiteral
+ #noautoesc // o.a.f.c.ASTDirNoAutoEsc
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: a // o.a.f.c.ASTExpVariable
+ #autoesc // o.a.f.c.ASTDirAutoEsc
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: b // o.a.f.c.ASTExpVariable
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: c // o.a.f.c.ASTExpVariable
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ftl
new file mode 100644
index 0000000..8c8953a
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-1.ftl
@@ -0,0 +1,29 @@
+<#--
+ 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 <@foo x=1 y=2; b1, b2>x</...@foo>
+2 <@ns.bar 1 2; b1, b2>y</@>
+3 <#assign x = 123><#assign x = 123 in ns><#global x = 123>
+4 <#if x + 1 == 0>foo${y}bar<#else>${"static"}${'x${baaz * 10}y'}</#if>
+5 <#switch x><#case 1>one<#case 2>two<#default>more</#switch>
+6 <#macro foo x y=2 z=y+1 q...><#nested x y></#macro>
+7 <#function foo x y><#local x = 123><#return 1></#function>
+8 <#list xs as x></#list>
+9 <#list xs>[<#items as x>${x}<#sep>, </#items>]<#else>None</#list>
+10 <#-- A comment -->
+11 <#outputFormat "XML"><#noAutoEsc>${a}<#autoEsc>${b}</#autoEsc>${c}</#noAutoEsc></#outputFormat>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ast
new file mode 100644
index 0000000..4839892
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ast
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+#mixed_content // o.a.f.c.ASTImplicitParent
+ #text // o.a.f.c.ASTStaticText
+ - content: "1 " // String
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n2 " // String
+ #assign // o.a.f.c.ASTDirAssignmentsContainer
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "y" // String
+ - assignment operator: "=" // String
+ - assignment source: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n3 " // String
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: ns // o.a.f.c.ASTExpVariable
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n4 " // String
+ #assign // o.a.f.c.ASTDirAssignmentsContainer
+ - variable scope: "1" // Integer
+ - namespace: ns // o.a.f.c.ASTExpVariable
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: ns // o.a.f.c.ASTExpVariable
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "y" // String
+ - assignment operator: "=" // String
+ - assignment source: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: ns // o.a.f.c.ASTExpVariable
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n5 " // String
+ #global // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "3" // Integer
+ - namespace: null // Null
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n6 " // String
+ #global // o.a.f.c.ASTDirAssignmentsContainer
+ - variable scope: "3" // Integer
+ - namespace: null // Null
+ #global // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "3" // Integer
+ - namespace: null // Null
+ #global // o.a.f.c.ASTDirAssignment
+ - assignment target: "y" // String
+ - assignment operator: "=" // String
+ - assignment source: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "3" // Integer
+ - namespace: null // Null
+ #macro // o.a.f.c.ASTDirMacro
+ - assignment target: "m" // String
+ - catch-all parameter name: null // Null
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText
+ - content: " 7 " // String
+ #local // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "2" // Integer
+ - namespace: null // Null
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n 8 " // String
+ #local // o.a.f.c.ASTDirAssignmentsContainer
+ - variable scope: "2" // Integer
+ - namespace: null // Null
+ #local // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "2" // Integer
+ - namespace: null // Null
+ #local // o.a.f.c.ASTDirAssignment
+ - assignment target: "y" // String
+ - assignment operator: "=" // String
+ - assignment source: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "2" // Integer
+ - namespace: null // Null
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "9 " // String
+ #assign // o.a.f.c.ASTDirAssignmentsContainer
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "a" // String
+ - assignment operator: "+=" // String
+ - assignment source: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "b" // String
+ - assignment operator: "-=" // String
+ - assignment source: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "c" // String
+ - assignment operator: "*=" // String
+ - assignment source: 3 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "d" // String
+ - assignment operator: "/=" // String
+ - assignment source: 4 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "e" // String
+ - assignment operator: "%=" // String
+ - assignment source: 5 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "f" // String
+ - assignment operator: "++" // String
+ - assignment source: null // Null
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "g" // String
+ - assignment operator: "--" // String
+ - assignment source: null // Null
+ - variable scope: "1" // Integer
+ - namespace: null // Null
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ftl
new file mode 100644
index 0000000..c070635
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-assignments.ftl
@@ -0,0 +1,29 @@
+<#--
+ 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 <#assign x = 1>
+2 <#assign x = 1, y = 2>
+3 <#assign x = 1 in ns>
+4 <#assign x = 1, y = 2 in ns>
+5 <#global x = 1>
+6 <#global x = 1, y = 2>
+<#macro m>
+ 7 <#local x = 1>
+ 8 <#local x = 1, y = 2>
+</#macro>
+9 <#assign a += 1, b -= 2, c *= 3, d /= 4, e %= 5, f++, g-->
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.ast
new file mode 100644
index 0000000..b8b696f
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.ast
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+#mixed_content // o.a.f.c.ASTImplicitParent
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: ?trim // o.a.f.c.BuiltInsForStringsBasic$trimBI
+ - left-hand operand: x // o.a.f.c.ASTExpVariable
+ - right-hand operand: "trim" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: ...(...) // o.a.f.c.ASTExpMethodCall
+ - callee: ?left_pad // o.a.f.c.BuiltInsForStringsBasic$padBI
+ - left-hand operand: x // o.a.f.c.ASTExpVariable
+ - right-hand operand: "left_pad" // String
+ - argument value: 5 // o.a.f.c.ASTExpNumberLiteral
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: ...(...) // o.a.f.c.ASTExpMethodCall
+ - callee: ?left_pad // o.a.f.c.BuiltInsForStringsBasic$padBI
+ - left-hand operand: x // o.a.f.c.ASTExpVariable
+ - right-hand operand: "left_pad" // String
+ - argument value: 5 // o.a.f.c.ASTExpNumberLiteral
+ - argument value: "-" // o.a.f.c.ASTExpStringLiteral
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: ?then(...) // o.a.f.c.BuiltInsWithParseTimeParameters$then_BI
+ - left-hand operand: x // o.a.f.c.ASTExpVariable
+ - right-hand operand: "then" // String
+ - argument value: "y" // o.a.f.c.ASTExpStringLiteral
+ - argument value: "n" // o.a.f.c.ASTExpStringLiteral
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: ?switch(...) // o.a.f.c.BuiltInsWithParseTimeParameters$switch_BI
+ - left-hand operand: x // o.a.f.c.ASTExpVariable
+ - right-hand operand: "switch" // String
+ - argument value: 1 // o.a.f.c.ASTExpNumberLiteral
+ - argument value: 11 // o.a.f.c.ASTExpNumberLiteral
+ - argument value: 2 // o.a.f.c.ASTExpNumberLiteral
+ - argument value: 22 // o.a.f.c.ASTExpNumberLiteral
+ - argument value: 33 // o.a.f.c.ASTExpNumberLiteral
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.ftl
new file mode 100644
index 0000000..74aee52
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-builtins.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.
+-->
+${x?trim}
+${x?left_pad(5)}
+${x?left_pad(5, '-')}
+${x?then('y', 'n')}
+${x?switch(1, 11, 2, 22, 33)}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ast
new file mode 100644
index 0000000..7770d72
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ast
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+#mixed_content // o.a.f.c.ASTImplicitParent; Location 1:1-18:8
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 1:1-1:15
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 1:6-1:8
+ - AST-node subtype: "0" // Integer
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 2:1-2:16
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 2:6-2:8
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText; Location 2:10-2:10
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 2:17-2:17
+ - content: "\n" // String
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 3:1-3:20
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 3:6-3:8
+ - AST-node subtype: "0" // Integer
+ ${...} // o.a.f.c.ASTDollarInterpolation; Location 3:10-3:13
+ - content: 1 // o.a.f.c.ASTExpNumberLiteral; Location 3:12-3:12
+ #text // o.a.f.c.ASTStaticText; Location 3:14-3:14
+ - content: "2" // String
+ #text // o.a.f.c.ASTStaticText; Location 3:21-3:21
+ - content: "\n" // String
+ #if-#elseif-#else-container // o.a.f.c.ASTDirIfElseIfElseContainer; Location 4:1-4:22
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 4:1-4:9
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 4:6-4:8
+ - AST-node subtype: "0" // Integer
+ #else // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 4:10-4:16
+ - condition: null // Null
+ - AST-node subtype: "1" // Integer
+ #if-#elseif-#else-container // o.a.f.c.ASTDirIfElseIfElseContainer; Location 5:1-5:24
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 5:1-5:10
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 5:6-5:8
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText; Location 5:10-5:10
+ - content: "1" // String
+ #else // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 5:11-5:18
+ - condition: null // Null
+ - AST-node subtype: "1" // Integer
+ #text // o.a.f.c.ASTStaticText; Location 5:18-5:18
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 5:25-5:25
+ - content: "\n" // String
+ #if-#elseif-#else-container // o.a.f.c.ASTDirIfElseIfElseContainer; Location 6:1-6:32
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 6:1-6:14
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 6:6-6:8
+ - AST-node subtype: "0" // Integer
+ ${...} // o.a.f.c.ASTDollarInterpolation; Location 6:10-6:13
+ - content: 1 // o.a.f.c.ASTExpNumberLiteral; Location 6:12-6:12
+ #text // o.a.f.c.ASTStaticText; Location 6:14-6:14
+ - content: "2" // String
+ #else // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 6:15-6:26
+ - condition: null // Null
+ - AST-node subtype: "1" // Integer
+ ${...} // o.a.f.c.ASTDollarInterpolation; Location 6:22-6:25
+ - content: 1 // o.a.f.c.ASTExpNumberLiteral; Location 6:24-6:24
+ #text // o.a.f.c.ASTStaticText; Location 6:26-6:26
+ - content: "2" // String
+ #text // o.a.f.c.ASTStaticText; Location 6:33-6:33
+ - content: "\n" // String
+ #if-#elseif-#else-container // o.a.f.c.ASTDirIfElseIfElseContainer; Location 7:1-7:28
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 7:1-7:9
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 7:6-7:8
+ - AST-node subtype: "0" // Integer
+ #elseif // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 7:10-7:22
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 7:19-7:21
+ - AST-node subtype: "2" // Integer
+ #if-#elseif-#else-container // o.a.f.c.ASTDirIfElseIfElseContainer; Location 8:1-8:29
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 8:1-8:9
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 8:6-8:8
+ - AST-node subtype: "0" // Integer
+ #elseif // o.a.f.c.ASTDirIfOrElseOrElseIf; Location 8:10-8:23
+ - condition: exp // o.a.f.c.ASTExpVariable; Location 8:19-8:21
+ - AST-node subtype: "2" // Integer
+ #text // o.a.f.c.ASTStaticText; Location 8:23-8:23
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 8:30-8:30
+ - content: "\n" // String
+ #attempt // o.a.f.c.ASTDirAttemptRecoverContainer; Location 9:1-9:31
+ - error handler: #recover // o.a.f.c.ASTDirRecover; Location 9:11-9:20
+ #recover // o.a.f.c.ASTDirRecover; Location 9:11-9:20
+ #attempt // o.a.f.c.ASTDirAttemptRecoverContainer; Location 10:1-10:33
+ - error handler: #recover // o.a.f.c.ASTDirRecover; Location 10:12-10:22
+ #text // o.a.f.c.ASTStaticText; Location 10:22-10:22
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 10:11-10:11
+ - content: "1" // String
+ #recover // o.a.f.c.ASTDirRecover; Location 10:12-10:22
+ #text // o.a.f.c.ASTStaticText; Location 10:22-10:22
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 10:34-10:34
+ - content: "\n" // String
+ #list // o.a.f.c.ASTDirList; Location 11:1-11:22
+ - list source: s // o.a.f.c.ASTExpVariable; Location 11:8-11:8
+ - target loop variable: "i" // String
+ #list // o.a.f.c.ASTDirList; Location 12:1-12:23
+ - list source: s // o.a.f.c.ASTExpVariable; Location 12:8-12:8
+ - target loop variable: "i" // String
+ #text // o.a.f.c.ASTStaticText; Location 12:15-12:15
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 12:24-12:24
+ - content: "\n" // String
+ #list // o.a.f.c.ASTDirList; Location 13:1-13:28
+ - list source: s // o.a.f.c.ASTExpVariable; Location 13:8-13:8
+ - target loop variable: "i" // String
+ #sep // o.a.f.c.ASTDirSep; Location 13:15-13:20
+ #list // o.a.f.c.ASTDirList; Location 14:1-14:30
+ - list source: s // o.a.f.c.ASTExpVariable; Location 14:8-14:8
+ - target loop variable: "i" // String
+ #text // o.a.f.c.ASTStaticText; Location 14:15-14:15
+ - content: "1" // String
+ #sep // o.a.f.c.ASTDirSep; Location 14:16-14:22
+ #text // o.a.f.c.ASTStaticText; Location 14:22-14:22
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 14:31-14:31
+ - content: "\n" // String
+ #list // o.a.f.c.ASTDirList; Location 15:1-15:45
+ - list source: s // o.a.f.c.ASTExpVariable; Location 15:8-15:8
+ #items // o.a.f.c.ASTDirItems; Location 15:10-15:37
+ - target loop variable: "i" // String
+ #sep // o.a.f.c.ASTDirSep; Location 15:23-15:28
+ #list // o.a.f.c.ASTDirList; Location 16:1-16:49
+ - list source: s // o.a.f.c.ASTExpVariable; Location 16:8-16:8
+ #text // o.a.f.c.ASTStaticText; Location 16:10-16:10
+ - content: "1" // String
+ #items // o.a.f.c.ASTDirItems; Location 16:11-16:40
+ - target loop variable: "i" // String
+ #text // o.a.f.c.ASTStaticText; Location 16:24-16:24
+ - content: "1" // String
+ #sep // o.a.f.c.ASTDirSep; Location 16:25-16:31
+ #text // o.a.f.c.ASTStaticText; Location 16:31-16:31
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 16:41-16:41
+ - content: "1" // String
+ #text // o.a.f.c.ASTStaticText; Location 16:50-17:2
+ - content: "\n1\n" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation; Location 18:1-18:8
+ - content: + // o.a.f.c.ASTExpAddOrConcat; Location 18:3-18:7
+ - left-hand operand: x // o.a.f.c.ASTExpVariable; Location 18:3-18:3
+ - right-hand operand: y // o.a.f.c.ASTExpVariable; Location 18:7-18:7
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ftl
new file mode 100644
index 0000000..99fa244
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-locations.ftl
@@ -0,0 +1,36 @@
+<#--
+ 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.
+-->
+<#if exp></#if>
+<#if exp>1</#if>
+<#if exp>${1}2</#if>
+<#if exp><#else></#if>
+<#if exp>1<#else>1</#if>
+<#if exp>${1}2<#else>${1}2</#if>
+<#if exp><#elseif exp></#if>
+<#if exp><#elseif exp>1</#if>
+<#attempt><#recover></#attempt>
+<#attempt>1<#recover>1</#attempt>
+<#list s as i></#list>
+<#list s as i>1</#list>
+<#list s as i><#sep></#list>
+<#list s as i>1<#sep>1</#list>
+<#list s><#items as i><#sep></#items></#list>
+<#list s>1<#items as i>1<#sep>1</#items>1</#list>
+1
+${x + y}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ast
new file mode 100644
index 0000000..41fc90b
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ast
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+#if // o.a.f.c.ASTDirIfOrElseOrElseIf
+ - condition: true // o.a.f.c.ASTExpBooleanLiteral
+ - AST-node subtype: "0" // Integer
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf
+ - condition: true // o.a.f.c.ASTExpBooleanLiteral
+ - AST-node subtype: "0" // Integer
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf
+ - condition: true // o.a.f.c.ASTExpBooleanLiteral
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText
+ - content: " text\n" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: " " // String
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf
+ - condition: true // o.a.f.c.ASTExpBooleanLiteral
+ - AST-node subtype: "0" // Integer
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: x // o.a.f.c.ASTExpVariable
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n" // String
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ftl
new file mode 100644
index 0000000..53716e4
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-mixedcontentsimplifications.ftl
@@ -0,0 +1,26 @@
+<#--
+ 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.
+-->
+<#if true>
+ <#if true>
+ </#if>
+ <#if true>
+ text
+ </#if>
+ <#if true>${x}</#if>
+</#if>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ast
new file mode 100644
index 0000000..7675522
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ast
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+#mixed_content // o.a.f.c.ASTImplicitParent
+ #text // o.a.f.c.ASTStaticText
+ - content: "a\n" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "b\n" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "c\n" // String
+ #text // o.a.f.c.ASTStaticText
+ - content: "d\n" // String
+ #if // o.a.f.c.ASTDirIfOrElseOrElseIf
+ - condition: true // o.a.f.c.ASTExpBooleanLiteral
+ - AST-node subtype: "0" // Integer
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ftl
new file mode 100644
index 0000000..501802a
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-multipleignoredchildren.ftl
@@ -0,0 +1,33 @@
+<#--
+ 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.
+-->
+a
+<#compress></#compress>
+b
+<#compress></#compress>
+<#compress></#compress>
+c
+<#compress></#compress>
+<#compress></#compress>
+<#compress></#compress>
+d
+<#if true>
+ <#compress></#compress>
+ <#compress></#compress>
+ <#compress></#compress>
+</#if>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ast
new file mode 100644
index 0000000..eefa5b1
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ast
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+#outputformat // o.a.f.c.ASTDirOutputFormat
+ - value: "HTML" // o.a.f.c.ASTExpStringLiteral
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ftl
new file mode 100644
index 0000000..fbdb342
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-nestedignoredchildren.ftl
@@ -0,0 +1,19 @@
+<#--
+ 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.
+-->
+<#outputFormat 'HTML'><#outputFormat 'HTML'><#outputFormat 'HTML'></#outputFormat></#outputFormat></#outputFormat>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ast
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ast
new file mode 100644
index 0000000..831c7dc
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ast
@@ -0,0 +1,281 @@
+/*
+ * 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.
+ */
+#mixed_content // o.a.f.c.ASTImplicitParent
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: 0 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: null // Null
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: 0 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: ..< // o.a.f.c.ASTExpRange
+ - left-hand operand: 0 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: ..< // o.a.f.c.ASTExpRange
+ - left-hand operand: 0 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: ..< // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: ..< // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: * // o.a.f.c.ArithmeticExpression
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "1" // Integer
+ - right-hand operand: * // o.a.f.c.ArithmeticExpression
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "1" // Integer
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: ?abs // o.a.f.c.BuiltInsForNumbers$absBI
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: "abs" // String
+ - right-hand operand: ?abs // o.a.f.c.BuiltInsForNumbers$absBI
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: "abs" // String
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: ...(...) // o.a.f.c.ASTExpMethodCall
+ - callee: ?index_of // o.a.f.c.BuiltInsForStringsBasic$index_ofBI
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: "index_of" // String
+ - argument value: "x" // o.a.f.c.ASTExpStringLiteral
+ - right-hand operand: ...(...) // o.a.f.c.ASTExpMethodCall
+ - callee: ?index_of // o.a.f.c.BuiltInsForStringsBasic$index_ofBI
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: "index_of" // String
+ - argument value: "y" // o.a.f.c.ASTExpStringLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: == // o.a.f.c.ASTExpComparison
+ - left-hand operand: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: o // o.a.f.c.ASTExpVariable
+ - right-hand operand: p // o.a.f.c.ASTExpVariable
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: == // o.a.f.c.ASTExpComparison
+ - left-hand operand: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - right-hand operand: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: o // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: p // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: a // o.a.f.c.ASTExpVariable
+ - right-hand operand: +... // o.a.f.c.ASTExpNegateOrPlus
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "1" // Integer
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: a // o.a.f.c.ASTExpVariable
+ - AST-node subtype: "0" // Integer
+ - right-hand operand: -... // o.a.f.c.ASTExpNegateOrPlus
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: ..* // o.a.f.c.ASTExpRange
+ - left-hand operand: * // o.a.f.c.ArithmeticExpression
+ - left-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: a // o.a.f.c.ASTExpVariable
+ - AST-node subtype: "1" // Integer
+ - right-hand operand: 2 // o.a.f.c.ASTExpNumberLiteral
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: || // o.a.f.c.ASTExpOr
+ - left-hand operand: && // o.a.f.c.ASTExpAnd
+ - left-hand operand: a // o.a.f.c.ASTExpVariable
+ - right-hand operand: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: b // o.a.f.c.ASTExpVariable
+ - right-hand operand: c // o.a.f.c.ASTExpVariable
+ - right-hand operand: d // o.a.f.c.ASTExpVariable
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #assign // o.a.f.c.ASTDirAssignment
+ - assignment target: "x" // String
+ - assignment operator: "=" // String
+ - assignment source: || // o.a.f.c.ASTExpOr
+ - left-hand operand: && // o.a.f.c.ASTExpAnd
+ - left-hand operand: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: a // o.a.f.c.ASTExpVariable
+ - right-hand operand: null // Null
+ - right-hand operand: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: b // o.a.f.c.ASTExpVariable
+ - right-hand operand: null // Null
+ - right-hand operand: d // o.a.f.c.ASTExpVariable
+ - variable scope: "1" // Integer
+ - namespace: null // Null
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n" // String
+ ${...} // o.a.f.c.ASTDollarInterpolation
+ - content: ...(...) // o.a.f.c.ASTExpMethodCall
+ - callee: f // o.a.f.c.ASTExpVariable
+ - argument value: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: null // Null
+ - argument value: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - right-hand operand: null // Null
+ - argument value: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ #text // o.a.f.c.ASTStaticText
+ - content: "\n\n" // String
+ @ // o.a.f.c.ASTDirUserDefined
+ - callee: m // o.a.f.c.ASTExpVariable
+ - argument value: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: * // o.a.f.c.ArithmeticExpression
+ - left-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: m // o.a.f.c.ASTExpVariable
+ - AST-node subtype: "1" // Integer
+ - right-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - argument value: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: + // o.a.f.c.ASTExpAddOrConcat
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - right-hand operand: - // o.a.f.c.ArithmeticExpression
+ - left-hand operand: n // o.a.f.c.ASTExpVariable
+ - right-hand operand: 1 // o.a.f.c.ASTExpNumberLiteral
+ - AST-node subtype: "0" // Integer
+ - argument value: .. // o.a.f.c.ASTExpRange
+ - left-hand operand: m // o.a.f.c.ASTExpVariable
+ - right-hand operand: null // Null
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ftl
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ftl
new file mode 100644
index 0000000..cb55c8a
--- /dev/null
+++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-range.ftl
@@ -0,0 +1,47 @@
+<#--
+ 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.
+-->
+<#assign x = 0..>
+
+<#assign x = 0..1>
+<#assign x = 0..<1>
+<#assign x = 0..!1>
+
+<#assign x = n + 1 .. m + 2>
+<#assign x = n + 1 ..< m + 2>
+<#assign x = n + 1 ..! m + 2>
+
+<#assign x = n * 1 .. m * 2>
+
+<#assign x = n?abs .. m?abs>
+
+<#assign x = n?index_of('x') .. m?index_of('y')>
+
+<#assign x = n..m == o..p>
+
+<#assign x = n+1+2..m-1-2 == o+1+2..p-1-2>
+
+<#assign x = 1+a..+2>
+<#assign x = 1-a..-2>
+<#assign x = 1*a..*2>
+<#assign x = a && b..c || d>
+<#assign x = a.. && b.. || d>
+
+${f(m.., m-1.., m+1..n-1)}
+
+<@m 1 * m .. m - 1 m + 1 .. n - 1 m .. />