freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [4/4] freemarker git commit: Continued work on TemplateLanguage configuration and new file extensions:
Date Wed, 11 Apr 2018 18:40:48 GMT
Continued work on TemplateLanguage configuration and new file extensions:

- FM2 file extension not recognized anymore.
- templateLanguage setting value is the file extension for the standard language
- The tagSyntax and interpolationSyntax settings were moved inside the templateLanguage setting, as they are only
  applicable if the templateLanguage is a DefaultTemplateLanguage instance.
- Adjusted many tests, so they pass


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

Branch: refs/heads/3
Commit: e9ca9d4c87f70fd167cb4dd118a82831dc5181a3
Parents: 220b11e
Author: ddekany <ddekany@apache.org>
Authored: Tue Apr 10 08:03:30 2018 +0200
Committer: ddekany <ddekany@apache.org>
Committed: Wed Apr 11 20:40:15 2018 +0200

----------------------------------------------------------------------
 FM3-CHANGE-LOG.txt                              |  20 ++-
 .../freemarker/core/ActualTagSyntaxTest.java    |  56 -------
 .../freemarker/core/ConfigurationTest.java      |  18 --
 .../core/InterpolationSyntaxTest.java           |  39 +++--
 .../core/InterpretSettingInheritanceTest.java   |   8 +-
 ...leParsingAndProcessingConfigurationTest.java |  18 +-
 .../freemarker/core/OutputFormatTest.java       |  92 +++++------
 .../core/ParsingErrorMessagesTest.java          |  71 ++++++--
 .../core/TagSyntaxVariationsTest.java           |  13 +-
 .../core/TemplateConfigurationTest.java         |  31 ++--
 .../freemarker/core/ASTExpStringLiteral.java    |   3 +-
 .../freemarker/core/ASTInterpolation.java       |   9 +-
 .../apache/freemarker/core/Configuration.java   |  99 ++---------
 .../core/DefaultTemplateLanguage.java           |  54 ++++--
 .../org/apache/freemarker/core/Environment.java |   2 +-
 .../freemarker/core/InterpolationSyntax.java    |   2 +-
 ...utableParsingAndProcessingConfiguration.java | 132 ++-------------
 .../core/MutableProcessingConfiguration.java    |  20 +--
 .../freemarker/core/ParsingConfiguration.java   | 164 ++++++++++++-------
 .../core/ParsingConfigurationWithFallback.java  |  20 ---
 ...nfigurationWithTemplateLanguageOverride.java |  23 ---
 .../org/apache/freemarker/core/TagSyntax.java   |   2 +-
 .../org/apache/freemarker/core/Template.java    |  24 ---
 .../freemarker/core/TemplateConfiguration.java  |  46 ------
 .../freemarker/core/TemplateLanguage.java       |  18 +-
 .../core/_ErrorDescriptionBuilder.java          |   5 +-
 freemarker-core/src/main/javacc/FTL.jj          |  25 +--
 .../examples/AbsoluteTemplateNameBIExample.java |   2 +-
 .../manual/examples/AutoEscapingExample.java    |  16 +-
 .../manual/examples/CustomFormatsExample.java   |   6 +-
 .../manual/examples/GettingStartedExample.java  |   2 +-
 .../AbsoluteTemplateNameBIExample-foo.f3ah      |  19 +++
 .../AbsoluteTemplateNameBIExample-foo.ftl       |  19 ---
 .../AbsoluteTemplateNameBIExample-lib.f3ah      |  38 +++++
 .../AbsoluteTemplateNameBIExample-lib.ftl       |  38 -----
 .../examples/AutoEscapingExample-capture.f3ah   |  21 +++
 .../AutoEscapingExample-capture.f3ah.out        |  20 +++
 .../examples/AutoEscapingExample-capture.ftlh   |  21 ---
 .../AutoEscapingExample-capture.ftlh.out        |  20 ---
 .../examples/AutoEscapingExample-convert.f3ah   |  27 +++
 .../AutoEscapingExample-convert.f3ah.out        |  25 +++
 .../examples/AutoEscapingExample-convert.ftlh   |  27 ---
 .../AutoEscapingExample-convert.ftlh.out        |  25 ---
 .../examples/AutoEscapingExample-convert2.f3au  |  25 +++
 .../AutoEscapingExample-convert2.f3au.out       |  21 +++
 .../examples/AutoEscapingExample-convert2.ftl   |  25 ---
 .../AutoEscapingExample-convert2.ftl.out        |  21 ---
 .../examples/AutoEscapingExample-infoBox.f3ah   |  26 +++
 .../AutoEscapingExample-infoBox.f3ah.out        |  25 +++
 .../examples/AutoEscapingExample-infoBox.ftlh   |  26 ---
 .../AutoEscapingExample-infoBox.ftlh.out        |  25 ---
 .../examples/AutoEscapingExample-markup.f3ah    |  28 ++++
 .../AutoEscapingExample-markup.f3ah.out         |  26 +++
 .../examples/AutoEscapingExample-markup.ftlh    |  28 ----
 .../AutoEscapingExample-markup.ftlh.out         |  26 ---
 .../AutoEscapingExample-stringConcat.f3ah       |  19 +++
 .../AutoEscapingExample-stringConcat.f3ah.out   |  19 +++
 .../AutoEscapingExample-stringConcat.ftlh       |  19 ---
 .../AutoEscapingExample-stringConcat.ftlh.out   |  19 ---
 .../AutoEscapingExample-stringLiteral.f3ah      |  21 +++
 .../AutoEscapingExample-stringLiteral.f3ah.out  |  20 +++
 .../AutoEscapingExample-stringLiteral.ftlh      |  21 ---
 .../AutoEscapingExample-stringLiteral.ftlh.out  |  20 ---
 .../AutoEscapingExample-stringLiteral2.f3ah     |  25 +++
 .../AutoEscapingExample-stringLiteral2.f3ah.out |  21 +++
 .../AutoEscapingExample-stringLiteral2.ftlh     |  25 ---
 .../AutoEscapingExample-stringLiteral2.ftlh.out |  21 ---
 .../examples/CustomFormatsExample-alias1.f3ah   |  22 +++
 .../CustomFormatsExample-alias1.f3ah.out        |  22 +++
 .../examples/CustomFormatsExample-alias1.ftlh   |  22 ---
 .../CustomFormatsExample-alias1.ftlh.out        |  22 ---
 .../examples/CustomFormatsExample-alias2.f3ah   |  19 +++
 .../CustomFormatsExample-alias2.f3ah.out        |  19 +++
 .../examples/CustomFormatsExample-alias2.ftlh   |  19 ---
 .../CustomFormatsExample-alias2.ftlh.out        |  19 ---
 .../CustomFormatsExample-modelAware.f3ah        |  20 +++
 .../CustomFormatsExample-modelAware.f3ah.out    |  20 +++
 .../CustomFormatsExample-modelAware.ftlh        |  20 ---
 .../CustomFormatsExample-modelAware.ftlh.out    |  20 ---
 .../dir/AbsoluteTemplateNameBIExample-foo.f3ah  |  19 +++
 .../dir/AbsoluteTemplateNameBIExample-foo.ftl   |  19 ---
 .../dir/AbsoluteTemplateNameBIExample-main.f3ah |  24 +++
 .../AbsoluteTemplateNameBIExample-main.f3ah.out |  26 +++
 .../dir/AbsoluteTemplateNameBIExample-main.ftl  |  24 ---
 .../AbsoluteTemplateNameBIExample-main.ftl.out  |  26 ---
 .../apache/freemarker/manual/examples/test.f3ah |  28 ++++
 .../apache/freemarker/manual/examples/test.ftlh |  28 ----
 .../spring/ConfigurationFactoryBeanTest.java    |   7 +-
 .../views/example/users/useredit.f3ah           |  87 ++++++++++
 .../views/example/users/useredit.ftlh           |  87 ----------
 .../views/example/users/userlist.f3ah           |  45 +++++
 .../views/example/users/userlist.ftlh           |  45 -----
 .../test/model/bind-directive-basic-usages.f3ah |  54 ++++++
 .../test/model/bind-directive-basic-usages.ftlh |  54 ------
 .../binderrors-directive-basic-usages.f3ah      |  69 ++++++++
 .../binderrors-directive-basic-usages.ftlh      |  69 --------
 .../test/model/eval-function-basic-usages.f3ah  |  40 +++++
 .../test/model/eval-function-basic-usages.ftlh  |  40 -----
 .../model/form/button-directive-usages.f3ah     |  39 +++++
 .../model/form/button-directive-usages.ftlh     |  39 -----
 .../model/form/errors-directive-usages.f3ah     |  72 ++++++++
 .../model/form/errors-directive-usages.ftlh     |  72 --------
 .../test/model/form/form-directive-usages.f3ah  |  78 +++++++++
 .../test/model/form/form-directive-usages.ftlh  |  78 ---------
 .../form/hidden-input-directive-usages.f3ah     |  63 +++++++
 .../form/hidden-input-directive-usages.ftlh     |  63 -------
 .../test/model/form/input-directive-usages.f3ah |  92 +++++++++++
 .../test/model/form/input-directive-usages.ftlh |  92 -----------
 .../test/model/form/label-directive-usages.f3ah |  53 ++++++
 .../test/model/form/label-directive-usages.ftlh |  53 ------
 .../form/password-input-directive-usages.f3ah   |  64 ++++++++
 .../form/password-input-directive-usages.ftlh   |  64 --------
 .../model/form/select-directive-usages.f3ah     |  37 +++++
 .../model/form/select-directive-usages.ftlh     |  37 -----
 .../model/form/textarea-directive-usages.f3ah   |  36 ++++
 .../model/form/textarea-directive-usages.ftlh   |  36 ----
 .../model/message-function-basic-usages.f3ah    |  31 ++++
 .../model/message-function-basic-usages.ftlh    |  31 ----
 .../nestedpath-directive-basic-usages.f3ah      |  54 ++++++
 .../nestedpath-directive-basic-usages.ftlh      |  54 ------
 .../test/model/theme-function-basic-usages.f3ah |  30 ++++
 .../test/model/theme-function-basic-usages.ftlh |  30 ----
 .../model/transform-function-basic-usages.f3ah  |  27 +++
 .../model/transform-function-basic-usages.ftlh  |  27 ---
 .../test/model/url-function-basic-usages.f3ah   |  83 ++++++++++
 .../test/model/url-function-basic-usages.ftlh   |  83 ----------
 .../example/mvc/users/users-mvc-context.xml     |   2 +-
 127 files changed, 2102 insertions(+), 2345 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/FM3-CHANGE-LOG.txt b/FM3-CHANGE-LOG.txt
index f9c6da8..b849d9a 100644
--- a/FM3-CHANGE-LOG.txt
+++ b/FM3-CHANGE-LOG.txt
@@ -240,7 +240,21 @@ Major changes / features
   Added org.slf4j:slf4j-api as required dependency instead.
 - Added Spring support to the FreeMarker project (freemarker-spring module), instead of relying Spring developers
   [Note: This is in very early stage, as of 2017-07-06.]
-
+- Added `Configuration.templateLangauge` and the `TemplateLanguage` class, which encapsulate the syntax and some of the
+  semantics, most importantly the `outputFormat`.
+- Each `TemplateLanguage` has an associated file extension, which should be sufficient for editors (IDE-s) to chose the
+  proper syntax highlighting. Syntax auto-detection was removed, as editors couldn't cope with it. Thus, the new file
+  extensions are somewhat complex, but serve tooling well. They are put together from 3 parts:
+  1. "f3" for FreeMarker 3. (Extensions starting with "f" are reserved for the FreeMarker project.)
+  2. Syntax: "a" for `ANGLE_BRACKET` `tagSyntax` and `DOLLAR` `interpolatonSyntax`, or "s" for `SQUARE_BRACKET`
+    `tagSyntax` and `SQUARE_BRACKET` `interpolationSyntax`. (Other permutations are possible, but has no standard
+     file extension reserved for them.)
+  3. Output format: Currently "h" for HTML, "x" for XML, "u" for undefined, "c" for configured (i.e., coming from
+     the `Configuration` or other kind of `ParsingConfiguration`). This is important for syntax highlighting of the
+     static parts, hence it's encoded into the file extension too. It's also important for security reasons, 
+  So a common file extensions will be "f3ah".
+  The FM2 file extensions, "ftl", "ftlh", and "ftlx" are banned to prevent confusion [TODO: not yet...].
+  
 
 Smaller Java API changes (categorized)
 --------------------------------------
@@ -343,9 +357,13 @@ Core / Configuration
     `TemplateConfiguration(sourceEncoding = "UTF-8")`, but `TemplateConfiguration(sourceEncoding = Charset("UTF-8"))`.
 - Configuration-related int constants were replaced with enums:
   - FM2 Configuration.${c}_TAG_SYNTAX with TagSyntax.${c}
+  - FM2 Configuration.${c}_INTERPOLATION_SYNTAX with InterpolationSyntax.${c}
   - FM2 Configuration.${c}_AUTO_ESCAPING_POLICY with AutoEscapingPolicy.${c}
 - Removed hasCustomFormats() from configuration related API-s (we don't need it anymore)
+- The tagSyntax and interpolationSyntax settings were moved inside the templateLanguage setting, as they are only
+  applicable if the templateLanguage is a DefaultTemplateLanguage instance.
 
+  
 Core / Models and Object wrapping
 .................................
 

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/ActualTagSyntaxTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ActualTagSyntaxTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ActualTagSyntaxTest.java
deleted file mode 100644
index 84813df..0000000
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ActualTagSyntaxTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 static org.apache.freemarker.core.TagSyntax.*;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-
-import org.apache.freemarker.test.TestConfigurationBuilder;
-import org.junit.Test;
-
-public class ActualTagSyntaxTest {
-
-    @Test
-    public void testWithFtlHeader() throws IOException {
-        testWithFtlHeader(ANGLE_BRACKET);
-        testWithFtlHeader(SQUARE_BRACKET);
-    }
-    
-    private void testWithFtlHeader(TagSyntax cfgTagSyntax) throws IOException {
-        assertEquals(getActualTagSyntax("[#ftl]foo", cfgTagSyntax), SQUARE_BRACKET);
-        assertEquals(getActualTagSyntax("<#ftl>foo", cfgTagSyntax), ANGLE_BRACKET);
-    }
-    
-    @Test
-    public void testUndecidable() throws IOException {
-        assertEquals(getActualTagSyntax("foo", ANGLE_BRACKET), ANGLE_BRACKET);
-        assertEquals(getActualTagSyntax("foo", SQUARE_BRACKET), SQUARE_BRACKET);
-    }
-
-    private TagSyntax getActualTagSyntax(String ftl, TagSyntax cfgTagSyntax) throws IOException {
-        return new Template(
-                null, ftl,
-                new TestConfigurationBuilder().tagSyntax(cfgTagSyntax).build())
-                .getActualTagSyntax();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
index 993b810..e5bb433 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
@@ -434,24 +434,6 @@ public class ConfigurationTest {
     }
 
     @Test
-    public void testInterpolationSyntaxSetting() throws TemplateException {
-        Builder cfgB = new Builder(VERSION_3_0_0);
-
-        // Default is "dollar":
-        assertEquals(InterpolationSyntax.DOLLAR, cfgB.getInterpolationSyntax());
-        
-        cfgB.setSetting("interpolationSyntax", "squareBracket");
-        assertEquals(InterpolationSyntax.SQUARE_BRACKET, cfgB.getInterpolationSyntax());
-        
-        try {
-            cfgB.setSetting("interpolationSyntax", "noSuchSyntax");
-            fail();
-        } catch (ConfigurationException e) {
-            assertThat(e.getMessage(), containsString("noSuchSyntax"));
-        }
-    }
-    
-    @Test
     public void testObjectWrapperSetSetting() throws Exception {
         Builder cfgB = new Builder(VERSION_3_0_0);
         {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
index 7dc0dd0..2bf4200 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpolationSyntaxTest.java
@@ -24,12 +24,24 @@ import static org.junit.Assert.*;
 import java.io.IOException;
 import java.io.StringWriter;
 
+import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
 import org.apache.freemarker.test.TemplateTest;
 import org.apache.freemarker.test.TestConfigurationBuilder;
 import org.junit.Test;
 
 public class InterpolationSyntaxTest extends TemplateTest {
 
+    /** Non-standard template language */
+    private final TemplateLanguage F3ASU = new DefaultTemplateLanguage("dummy",
+            UndefinedOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT,
+            TagSyntax.ANGLE_BRACKET, InterpolationSyntax.SQUARE_BRACKET); 
+
+    /** Non-standard template language */
+    private final TemplateLanguage F3SDU = new DefaultTemplateLanguage("dummy",
+            UndefinedOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT,
+            TagSyntax.SQUARE_BRACKET, InterpolationSyntax.DOLLAR); 
+    
+    
     @Test
     public void fm2HashInterpolationNotRecognized() throws IOException, TemplateException {
         // Find related: [interpolation prefixes]
@@ -51,13 +63,17 @@ public class InterpolationSyntaxTest extends TemplateTest {
         assertOutput("${'\"${1} #{1} [=1]\"'?eval}", "1 #{1} [=1]");
         
         assertOutput("<#setting booleanFormat='y,n'>${2>1}", "y"); // Not an error since 2.3.28
-        assertOutput("[#ftl][#setting booleanFormat='y,n']${2>1}", "y"); // Not an error since 2.3.28
+        setConfiguration(new TestConfigurationBuilder()
+                .templateLanguage(F3SDU)
+                .build());
+        assertOutput("[#setting booleanFormat='y,n']${2>1}", "y"); // Not an error since 2.3.28
     }
 
     @Test
     public void squareBracketInterpolationSyntaxTest() throws Exception {
+        
         setConfiguration(new TestConfigurationBuilder()
-                .interpolationSyntax(InterpolationSyntax.SQUARE_BRACKET)
+                .templateLanguage(F3ASU)
                 .build());
         
         assertOutput("${1} #{1} [=1]", "${1} #{1} 1");
@@ -72,14 +88,12 @@ public class InterpolationSyntaxTest extends TemplateTest {
         assertErrorContains("<#if [true][0]]></#if>", "\"]\"", "nothing open");
 
         setConfiguration(new TestConfigurationBuilder()
-                .tagSyntax(TagSyntax.SQUARE_BRACKET)
-                .interpolationSyntax(InterpolationSyntax.SQUARE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3SU)
                 .build());
         assertOutput("[#if [true][0]]>[/#if]", ">");
         assertOutput("[=1][=2]${3}", "12${3}");
         setConfiguration(new TestConfigurationBuilder()
-                .tagSyntax(TagSyntax.ANGLE_BRACKET)
-                .interpolationSyntax(InterpolationSyntax.SQUARE_BRACKET)
+                .templateLanguage(F3ASU)
                 .build());
         assertOutput("[#ftl][#if [true][0]]>[/#if]", ">");
         assertOutput("[#ftl][=1][=2]${3}", "12${3}");
@@ -109,11 +123,9 @@ public class InterpolationSyntaxTest extends TemplateTest {
 
     @Test
     public void squareBracketTagSyntaxStillWorks() throws Exception {
-        for (InterpolationSyntax intepolationSyntax : new InterpolationSyntax[] {
-                InterpolationSyntax.DOLLAR, InterpolationSyntax.SQUARE_BRACKET }) {
+        for (TemplateLanguage tempLang : new TemplateLanguage[] { F3SDU, DefaultTemplateLanguage.F3SU }) {
             setConfiguration(new TestConfigurationBuilder()
-                    .tagSyntax(TagSyntax.SQUARE_BRACKET)
-                    .interpolationSyntax(intepolationSyntax)
+                    .templateLanguage(tempLang)
                     .build());
             
             assertOutput("[#if [true][0]]t[#else]f[/#if]", "t");
@@ -129,16 +141,15 @@ public class InterpolationSyntaxTest extends TemplateTest {
         String badFtl4 = " <#t/]OK\n";
         
         setConfiguration(new TestConfigurationBuilder()
-                .interpolationSyntax(InterpolationSyntax.DOLLAR)
+                .templateLanguage(DefaultTemplateLanguage.F3AU)
                 .build());
         assertErrorContains(badFtl1, "\"]\"");
         assertErrorContains(badFtl2, "\"]\"");
         assertErrorContains(badFtl3, "\"]\"");
         assertErrorContains(badFtl4, "\"]\"");
         
-        // Glitch is not emulated with this:
         setConfiguration(new TestConfigurationBuilder()
-                .interpolationSyntax(InterpolationSyntax.SQUARE_BRACKET)
+                .templateLanguage(F3ASU)
                 .build());
         assertErrorContains(badFtl1, "\"]\"");
         assertErrorContains(badFtl2, "\"]\"");
@@ -157,7 +168,7 @@ public class InterpolationSyntaxTest extends TemplateTest {
         assertErrorContains("${1", "unclosed \"{\"");
         
         setConfiguration(new TestConfigurationBuilder()
-                .interpolationSyntax(InterpolationSyntax.SQUARE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3SU)
                 .build());
         assertErrorContains("[=1", "unclosed \"[\"");
     }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java
index 9132d11..3e17c2f 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/InterpretSettingInheritanceTest.java
@@ -42,7 +42,7 @@ public class InterpretSettingInheritanceTest  extends TemplateTest {
     @Test
     public void tagSyntaxTest() throws IOException, TemplateException {
         setConfiguration(new TestConfigurationBuilder()
-                .tagSyntax(TagSyntax.ANGLE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3AU)
                 .build());
         assertOutput(FTL_S_A_S, OUT_A_S_WHEN_SYNTAX_IS_A);
         assertOutput(FTL_S_S_A, OUT_S_A_WHEN_SYNTAX_IS_A);
@@ -50,7 +50,7 @@ public class InterpretSettingInheritanceTest  extends TemplateTest {
         assertOutput(FTL_A_S_A, OUT_S_A_WHEN_SYNTAX_IS_A);
 
         setConfiguration(new TestConfigurationBuilder()
-                .tagSyntax(TagSyntax.SQUARE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3SU)
                 .build());
         assertOutput(FTL_S_A_S, OUT_A_S_WHEN_SYNTAX_IS_S);
         assertOutput(FTL_S_S_A, OUT_S_A_WHEN_SYNTAX_IS_S);
@@ -80,13 +80,13 @@ public class InterpretSettingInheritanceTest  extends TemplateTest {
     @Test
     public void evalTest() throws IOException, TemplateException {
         setConfiguration(new TestConfigurationBuilder()
-                .tagSyntax(TagSyntax.ANGLE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3AU)
                 .build());
         assertOutput("<@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval />", OUT_S_A_WHEN_SYNTAX_IS_A);
         assertOutput("[#ftl][@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval /]", OUT_S_A_WHEN_SYNTAX_IS_A);
 
         setConfiguration(new TestConfigurationBuilder()
-                .tagSyntax(TagSyntax.SQUARE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3SU)
                 .build());
         assertOutput("[@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval /]", OUT_S_A_WHEN_SYNTAX_IS_S);
         assertOutput("<#ftl><@'\"[#if true]s[/#if]<#if true>a</#if>\"?interpret'?eval />", OUT_S_A_WHEN_SYNTAX_IS_S);

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java
index 51a331f..56f8581 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MutableParsingAndProcessingConfigurationTest.java
@@ -273,7 +273,7 @@ public class MutableParsingAndProcessingConfigurationTest {
         assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
         assertFalse(cfgB.isTimeZoneSet());
 
-        cfgB.setSetting(Configuration.ExtendableBuilder.TIME_ZONE_KEY, "JVM default");
+        cfgB.setSetting(Configuration.Builder.TIME_ZONE_KEY, "JVM default");
         assertEquals(TimeZone.getDefault(), cfgB.getTimeZone());
         assertTrue(cfgB.isTimeZoneSet());
     }
@@ -311,6 +311,22 @@ public class MutableParsingAndProcessingConfigurationTest {
                 MutableParsingAndProcessingConfiguration.getSettingNames(),
                 MutableParsingAndProcessingConfiguration.class);
     }
+    
+    @Test
+    public void testTemplateLanguage() throws Exception {
+        Configuration.Builder cfgB = new Configuration.Builder(Configuration.VERSION_3_0_0);
+        cfgB.setSetting(Configuration.Builder.TEMPLATE_LANGUAGE_KEY, "f3ax");
+        assertEquals(DefaultTemplateLanguage.F3AX, cfgB.getTemplateLanguage());
+        cfgB.setSetting(Configuration.Builder.TEMPLATE_LANGUAGE_KEY, "f3SH");
+        assertEquals(DefaultTemplateLanguage.F3SH, cfgB.getTemplateLanguage());
+        try {
+            cfgB.setSetting(Configuration.Builder.TEMPLATE_LANGUAGE_KEY, "qqqq");
+            fail();
+        } catch (InvalidSettingValueException e) {
+            assertThat(e.getMessage(), allOf(containsString("qqqq"), containsString("language")));
+        }
+    }
+    
 
     @SuppressWarnings("boxing")
     private void assertStartsWith(List<String> list, List<String> headList) {

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
index 279516f..9f1c7d3 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/OutputFormatTest.java
@@ -90,14 +90,14 @@ public class OutputFormatTest extends TemplateTest {
     public void testStandardFileExtensions() throws Exception {
         String commonContent = "${.outputFormat}";
         addTemplate("t", commonContent);
-        addTemplate("t.ftl", commonContent);
-        addTemplate("t.ftlh", commonContent);
-        addTemplate("t.FTLH", commonContent);
-        addTemplate("t.fTlH", commonContent);
-        addTemplate("t.ftlx", commonContent);
-        addTemplate("t.FTLX", commonContent);
-        addTemplate("t.fTlX", commonContent);
-        addTemplate("tWithHeader.ftlx", "<#ftl outputFormat='HTML'>" + commonContent);
+        addTemplate("t.f3ac", commonContent);
+        addTemplate("t.f3ah", commonContent);
+        addTemplate("t.F3AH", commonContent);
+        addTemplate("t.f3aH", commonContent);
+        addTemplate("t.f3ax", commonContent);
+        addTemplate("t.F3AX", commonContent);
+        addTemplate("t.f3aX", commonContent);
+        addTemplate("tWithHeader.f3ax", "<#ftl outputFormat='HTML'>" + commonContent);
         
         for (int setupNumber = 1; setupNumber <= 3; setupNumber++) {
             TestConfigurationBuilder cfgB = createDefaultConfigurationBuilder();
@@ -124,9 +124,9 @@ public class OutputFormatTest extends TemplateTest {
                 cfgB.setTemplateConfigurations(
                         new ConditionalTemplateConfigurationFactory(
                                 new OrMatcher(
-                                        new FileNameGlobMatcher("*.ftlh"),
-                                        new FileNameGlobMatcher("*.FTLH"),
-                                        new FileNameGlobMatcher("*.fTlH")),
+                                        new FileNameGlobMatcher("*.f3ah"),
+                                        new FileNameGlobMatcher("*.F3AH"),
+                                        new FileNameGlobMatcher("*.f3aH")),
                                 tcbXML.build()));
                 ftlhOutputFormat = HTMLOutputFormat.INSTANCE; // can't be overidden
                 ftlxOutputFormat = XMLOutputFormat.INSTANCE;
@@ -145,25 +145,25 @@ public class OutputFormatTest extends TemplateTest {
             }
             
             {
-                Template t = getConfiguration().getTemplate("t.ftl");
+                Template t = getConfiguration().getTemplate("t.f3ac");
                 assertEquals(cfgOutputFormat, t.getOutputFormat());
                 assertOutput(t, t.getOutputFormat().getName());
             }
             
-            for (String name : new String[] { "t.ftlh", "t.FTLH", "t.fTlH" }) {
+            for (String name : new String[] { "t.f3ah", "t.F3AH", "t.f3aH" }) {
                 Template t = getConfiguration().getTemplate(name);
                 assertEquals(ftlhOutputFormat, t.getOutputFormat());
                 assertOutput(t, t.getOutputFormat().getName());
             }
             
-            for (String name : new String[] { "t.ftlx", "t.FTLX", "t.fTlX" }) {
+            for (String name : new String[] { "t.f3ax", "t.F3AX", "t.f3aX" }) {
                 Template t = getConfiguration().getTemplate(name);
                 assertEquals(ftlxOutputFormat, t.getOutputFormat());
                 assertOutput(t, t.getOutputFormat().getName());
             }
 
             {
-                Template t = getConfiguration().getTemplate("tWithHeader.ftlx");
+                Template t = getConfiguration().getTemplate("tWithHeader.f3ax");
                 assertEquals(HTMLOutputFormat.INSTANCE, t.getOutputFormat());
                 assertOutput(t, t.getOutputFormat().getName());
             }
@@ -174,7 +174,7 @@ public class OutputFormatTest extends TemplateTest {
     
     @Test
     public void testStandardFileExtensionsSettingOverriding() throws Exception {
-        addTemplate("t.ftlx",
+        addTemplate("t.f3ax",
                 "${\"'\"} ${\"'\"?esc} ${\"'\"?noEsc}");
         addTemplate("t.ftl",
                 "${'{}'} ${'{}'?esc} ${'{}'?noEsc}");
@@ -193,37 +193,37 @@ public class OutputFormatTest extends TemplateTest {
 
         {
             setConfiguration(createDefaultConfigurationBuilder().outputFormat(HTMLOutputFormat.INSTANCE).build());
-            assertOutputForNamed("t.ftlx", "&apos; &apos; '");  // Can't override it
+            assertOutputForNamed("t.f3ax", "&apos; &apos; '");  // Can't override it
             setConfiguration(createDefaultConfigurationBuilder().templateConfigurations(tcfHTML).build());
-            assertOutputForNamed("t.ftlx", "&apos; &apos; '");  // Can't override it
+            assertOutputForNamed("t.f3ax", "&apos; &apos; '");  // Can't override it
             setConfiguration(createDefaultConfigurationBuilder().templateConfigurations(tcfNoAutoEsc).build());
-            assertOutputForNamed("t.ftlx", "&apos; &apos; '");  // Can't override it
+            assertOutputForNamed("t.f3ax", "&apos; &apos; '");  // Can't override it
         }
 
         {
             setConfiguration(createDefaultConfigurationBuilder().recognizeStandardFileExtensions(false).build());
-            assertErrorContainsForNamed("t.ftlx", UndefinedOutputFormat.INSTANCE.getName());
+            assertErrorContainsForNamed("t.f3ax", UndefinedOutputFormat.INSTANCE.getName());
 
             setConfiguration(createDefaultConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
                     .outputFormat(HTMLOutputFormat.INSTANCE).build());
-            assertOutputForNamed("t.ftlx", "&#39; &#39; '");
+            assertOutputForNamed("t.f3ax", "&#39; &#39; '");
 
             setConfiguration(createDefaultConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
                     .outputFormat(XMLOutputFormat.INSTANCE).build());
-            assertOutputForNamed("t.ftlx", "&apos; &apos; '");
+            assertOutputForNamed("t.f3ax", "&apos; &apos; '");
 
             setConfiguration(createDefaultConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
                     .templateConfigurations(tcfHTML).build());
-            assertOutputForNamed("t.ftlx", "&#39; &#39; '");
+            assertOutputForNamed("t.f3ax", "&#39; &#39; '");
 
             setConfiguration(createDefaultConfigurationBuilder()
                     .recognizeStandardFileExtensions(false)
                     .templateConfigurations(tcfNoAutoEsc)
                     .outputFormat(XMLOutputFormat.INSTANCE).build());
-            assertOutputForNamed("t.ftlx", "' &apos; '");
+            assertOutputForNamed("t.f3ax", "' &apos; '");
         }
     }
 
@@ -239,14 +239,14 @@ public class OutputFormatTest extends TemplateTest {
             assertEquals("'", out.toString());
         }
         {
-            Template t = new Template("foo.ftlx", commonFTL, cfg);
+            Template t = new Template("foo.f3ax", commonFTL, cfg);
             assertSame(XMLOutputFormat.INSTANCE, t.getOutputFormat());
             StringWriter out = new StringWriter();
             t.process(null, out);
             assertEquals("&apos;", out.toString());
         }
         {
-            Template t = new Template("foo.ftlh", commonFTL, cfg);
+            Template t = new Template("foo.f3ah", commonFTL, cfg);
             assertSame(HTMLOutputFormat.INSTANCE, t.getOutputFormat());
             StringWriter out = new StringWriter();
             t.process(null, out);
@@ -256,19 +256,19 @@ public class OutputFormatTest extends TemplateTest {
     
     @Test
     public void testStandardFileExtensionsFormatterImplOverriding() throws Exception {
-        addTemplate("t.ftlh", "${'a&x'}");
+        addTemplate("t.f3ah", "${'a&x'}");
 
-        assertOutputForNamed("t.ftlh", "a&amp;x");
+        assertOutputForNamed("t.f3ah", "a&amp;x");
 
         setConfiguration(new TestConfigurationBuilder()
                 .registeredCustomOutputFormats(Collections.<OutputFormat>singleton(CustomHTMLOutputFormat.INSTANCE))
                 .build());
-        assertOutputForNamed("t.ftlh", "a&amp;X");
+        assertOutputForNamed("t.f3ah", "a&amp;X");
 
         setConfiguration(new TestConfigurationBuilder()
                 .registeredCustomOutputFormats(Collections.<OutputFormat>emptyList())
                 .build());
-        assertOutputForNamed("t.ftlh", "a&amp;x");
+        assertOutputForNamed("t.f3ah", "a&amp;x");
     }
     
     @Test
@@ -527,18 +527,18 @@ public class OutputFormatTest extends TemplateTest {
     public void testSpecialVariables() throws Exception {
         String commonFTL = "${.outputFormat} ${.autoEsc?c}";
         
-        addTemplate("t.ftlx", commonFTL);
-        assertOutputForNamed("t.ftlx", "XML true");
+        addTemplate("t.f3ax", commonFTL);
+        assertOutputForNamed("t.f3ax", "XML true");
         
-        addTemplate("t.ftlh", commonFTL);
-        assertOutputForNamed("t.ftlh", "HTML true");
+        addTemplate("t.f3ah", commonFTL);
+        assertOutputForNamed("t.f3ah", "HTML true");
 
         addTemplate("t.ftl", commonFTL);
         assertOutputForNamed("t.ftl", "undefined false");
         
         addTemplate("tX.ftl", "<#ftl outputFormat='XML'>" + commonFTL);
-        addTemplate("tX.ftlx", commonFTL);
-        assertOutputForNamed("t.ftlx", "XML true");
+        addTemplate("tX.f3ax", commonFTL);
+        assertOutputForNamed("t.f3ax", "XML true");
         
         addTemplate("tN.ftl", "<#ftl outputFormat='RTF' autoEsc=false>" + commonFTL);
         assertOutputForNamed("tN.ftl", "RTF false");
@@ -549,11 +549,11 @@ public class OutputFormatTest extends TemplateTest {
     @Test
     public void testEscAndNoEscBIBasics() throws IOException, TemplateException {
         String commonFTL = "${'<x>'} ${'<x>'?esc} ${'<x>'?noEsc}";
-        addTemplate("t.ftlh", commonFTL);
-        addTemplate("t-noAuto.ftlh", "<#ftl autoEsc=false>" + commonFTL);
+        addTemplate("t.f3ah", commonFTL);
+        addTemplate("t-noAuto.f3ah", "<#ftl autoEsc=false>" + commonFTL);
         addTemplate("t.ftl", commonFTL);
-        assertOutputForNamed("t.ftlh", "&lt;x&gt; &lt;x&gt; <x>");
-        assertOutputForNamed("t-noAuto.ftlh", "<x> &lt;x&gt; <x>");
+        assertOutputForNamed("t.f3ah", "&lt;x&gt; &lt;x&gt; <x>");
+        assertOutputForNamed("t-noAuto.f3ah", "<x> &lt;x&gt; <x>");
         assertErrorContainsForNamed("t.ftl", "output format", "undefined");
     }
 
@@ -821,14 +821,14 @@ public class OutputFormatTest extends TemplateTest {
         String commonFTL
                 = "Eval: ${'.outputFormat'?eval}; "
                   + "Interpret: <#assign ipd = r\"${.outputFormat} ${'{&}'}\"?interpret><@ipd/>";
-        addTemplate("t.ftlh", commonFTL);
-        addTemplate("t2.ftlh", "<#outputFormat 'RTF'>" + commonFTL + "</#outputFormat>");
+        addTemplate("t.f3ah", commonFTL);
+        addTemplate("t2.f3ah", "<#outputFormat 'RTF'>" + commonFTL + "</#outputFormat>");
         
         assertOutputForNamed(
-                "t.ftlh",
+                "t.f3ah",
                 "Eval: HTML; Interpret: HTML {&amp;}");
         assertOutputForNamed(
-                "t2.ftlh",
+                "t2.f3ah",
                 "Eval: RTF; Interpret: RTF \\{&\\}");
         assertOutput(
                 commonFTL,
@@ -937,9 +937,9 @@ public class OutputFormatTest extends TemplateTest {
         assertOutput(
                 "<#ftl outputFormat='XML'>" + commonFtl,
                 commonOutput);
-        addTemplate("t.ftlx", commonFtl);
+        addTemplate("t.f3ax", commonFtl);
         assertOutputForNamed(
-                "t.ftlx",
+                "t.f3ax",
                 commonOutput);
         
         assertErrorContains(

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java
index a3dcd6c..7bcdfd0 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ParsingErrorMessagesTest.java
@@ -20,6 +20,7 @@
 package org.apache.freemarker.core;
 
 import java.io.IOException;
+import java.util.LinkedList;
 
 import org.apache.freemarker.test.TemplateTest;
 import org.apache.freemarker.test.TestConfigurationBuilder;
@@ -34,9 +35,9 @@ public class ParsingErrorMessagesTest extends TemplateTest {
         assertErrorContainsAS("<@foo ${x == 3} />", "instead of ${");
         
         setConfiguration(new TestConfigurationBuilder()
-                .interpolationSyntax(InterpolationSyntax.SQUARE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3SU)
                 .build());
-        assertErrorContains("<@foo [= x == 3] />", "instead of [=");
+        assertErrorContains("[@foo [= x == 3] /]", "instead of [=");
     }
 
     @Test
@@ -124,9 +125,8 @@ public class ParsingErrorMessagesTest extends TemplateTest {
     public void testInterpolatingClosingsErrors() throws Exception {
         assertErrorContainsAS("<#ftl>${x", "unclosed");        
         assertErrorContainsAS("<#assign x = x}>", "\"}\"", "open");
-        assertErrorContainsAS("<#ftl>${'x']", "\"]\"", "open");
-        assertErrorContains("<#ftl>${'x'>", "end of file");
-        assertErrorContains("[#ftl]${'x'>", "end of file");
+        assertErrorContains("${'x']", "\"]\"", "open");
+        assertErrorContains("${'x'>", "end of file");
         
         assertOutput("<#assign x = '${x'>", ""); // TODO [FM3] Legacy glitch... should fail in theory.
     }
@@ -186,25 +186,74 @@ public class ParsingErrorMessagesTest extends TemplateTest {
         return assertErrorContainsAS(angleBracketsFtl, expectedSubstrings, expectedSubstrings);
     }
     
-    protected Throwable assertErrorContainsAS(String angleBracketsFtl,
+    protected Throwable assertErrorContainsAS(String f3aSrc,
             String[] expectedSubstringsA, String[] expectedSubstringsS) {
         pushNamelessTemplateConfiguraitonSettings(new TemplateConfiguration.Builder()
-                    .tagSyntax(TagSyntax.ANGLE_BRACKET)
-                    .build());
+                .templateLanguage(DefaultTemplateLanguage.F3AU)
+                .build());
         try {
-            assertErrorContains(angleBracketsFtl, expectedSubstringsA);
+            assertErrorContains(f3aSrc, expectedSubstringsA);
         } finally {
             popNamelessTemplateConfiguraitonSettings();
         }
         
         pushNamelessTemplateConfiguraitonSettings(new TemplateConfiguration.Builder()
-                .tagSyntax(TagSyntax.SQUARE_BRACKET)
+                .templateLanguage(DefaultTemplateLanguage.F3SU)
                 .build());
         try {
-            return assertErrorContains(angleBracketsFtl.replace('<', '[').replace('>', ']'), expectedSubstringsS);
+            return assertErrorContains(f3aToF3s(f3aSrc));
         } finally {
             popNamelessTemplateConfiguraitonSettings();
         }
     }
 
+    /**
+     * Very naive F3A to F3S conversion (incorrect, but good enough for this test).
+     */
+    private String f3aToF3s(String f3aSrc) {
+        StringBuilder sb = new StringBuilder();
+        LinkedList<Character> openingStack = new LinkedList<>();
+        for (int i = 0; i < f3aSrc.length(); i++) {
+            char c = f3aSrc.charAt(i);
+            if (c == '<') {
+                char cNext = i + 1 < f3aSrc.length() ? f3aSrc.charAt(i + 1) : 0; 
+                if (cNext == '/' || cNext == '#' || cNext == '@') {
+                    sb.append("[");
+                    openingStack.push('A');
+                } else {
+                    sb.append(c);
+                    openingStack.push(c);
+                }
+            } else if (c == '{') {
+                if (i > 0 && f3aSrc.charAt(i - 1) == '$') {
+                    sb.deleteCharAt(i - 1);
+                    sb.append("[=");
+                    openingStack.push('D');
+                } else {
+                    sb.append(c);
+                    openingStack.push(c);
+                }
+            } else if (c == '>') {
+                Character top = openingStack.peek();
+                if (top != null && top == '<' || top == 'A') {
+                    openingStack.pop();
+                    sb.append(top == 'A' ? ']' : c);
+                } else {
+                    sb.append(c);
+                }
+            } else if (c == '}') {
+                Character top = openingStack.peek();
+                if (top != null && top == '{' || top == 'D') {
+                    openingStack.pop();
+                    sb.append(top == 'D' ? ']' : c);
+                } else {
+                    sb.append(c);
+                }
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/TagSyntaxVariationsTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TagSyntaxVariationsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TagSyntaxVariationsTest.java
index 320f2b7..ca24bfd 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TagSyntaxVariationsTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TagSyntaxVariationsTest.java
@@ -37,8 +37,6 @@ import junit.framework.TestCase;
  */
 public class TagSyntaxVariationsTest extends TestCase {
     
-    private static final String HDR_ANG = "<#ftl>";
-    private static final String HDR_SQU = squarify(HDR_ANG);
     private static final String IF_ANG = "<#if true>i</#if>";
     private static final String IF_SQU = squarify(IF_ANG);
     private static final String IF_OUT = "i";
@@ -75,15 +73,14 @@ public class TagSyntaxVariationsTest extends TestCase {
             // Permutations 
             for (int angOrSqu = 0; angOrSqu < 2; angOrSqu++) {
                 Configuration cfg = new TestConfigurationBuilder()
-                        .tagSyntax(angOrSqu == 0
-                                ? TagSyntax.ANGLE_BRACKET
-                                : TagSyntax.SQUARE_BRACKET)
+                        .templateLanguage(angOrSqu == 0
+                                ? DefaultTemplateLanguage.F3AU
+                                : DefaultTemplateLanguage.F3SU)
                         .sharedVariables(sharedVariables)
                         .build();
 
                 String dir_xxx = angOrSqu == 0 ? dir_ang : dir_squ;
                 String cust_xxx = angOrSqu == 0 ? CUST_ANG : CUST_SQU;
-                String hdr_xxx = angOrSqu == 0 ? HDR_ANG : HDR_SQU;
                 String wrong_xxx = angOrSqu == 0 ? WRONG_ANG : WRONG_SQU;
                 String wrongc_xxx = angOrSqu == 0 ? WRONGC_ANG : WRONGC_SQU;
 
@@ -104,10 +101,6 @@ public class TagSyntaxVariationsTest extends TestCase {
                             null);
 
                     test(cfg,
-                            hdr_xxx + wrongx_xxx,
-                            null);
-
-                    test(cfg,
                             cust_xxx + wrongx_xxx + dir_xxx,
                             null);
                 } // for wrongc

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
index 269cb41..4204d3e 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateConfigurationTest.java
@@ -545,22 +545,6 @@ public class TemplateConfigurationTest {
         
         {
             TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
-            tcb.setTagSyntax(TagSyntax.SQUARE_BRACKET);
-            TemplateConfiguration tc = tcb.build();
-            assertOutputWithoutAndWithTC(tc, "[#if true]y[/#if]", "[#if true]y[/#if]", "y");
-            testedProps.add(Configuration.ExtendableBuilder.TAG_SYNTAX_KEY);
-        }
-
-        {
-            TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
-            tcb.setInterpolationSyntax(InterpolationSyntax.SQUARE_BRACKET);
-            TemplateConfiguration tc = tcb.build();
-            assertOutputWithoutAndWithTC(tc, "${1}[=2]", "1[=2]", "${1}2");
-            testedProps.add(Configuration.ExtendableBuilder.INTERPOLATION_SYNTAX_KEY);
-        }
-        
-        {
-            TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
             tcb.setWhitespaceStripping(false);
             TemplateConfiguration tc = tcb.build();
             assertOutputWithoutAndWithTC(tc, "<#if true>\nx\n</#if>\n", "x\n", "\nx\n\n");
@@ -608,7 +592,7 @@ public class TemplateConfigurationTest {
             TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
             tcb.setRecognizeStandardFileExtensions(false);
             TemplateConfiguration tc = tcb.build();
-            assertOutputWithoutAndWithTC(tc, "adhoc.ftlh", "${.outputFormat}",
+            assertOutputWithoutAndWithTC(tc, "adhoc.f3ah", "${.outputFormat}",
                     HTMLOutputFormat.INSTANCE.getName(), UndefinedOutputFormat.INSTANCE.getName());
             testedProps.add(Configuration.ExtendableBuilder.RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY);
         }
@@ -626,7 +610,14 @@ public class TemplateConfigurationTest {
         }
 
         {
-            // As the TemplateLanguage-based parser selection happens in the TemplateResolver, we can't use
+            TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
+            tcb.setTemplateLanguage(DefaultTemplateLanguage.F3SH);
+            TemplateConfiguration tc = tcb.build();
+            assertOutputWithoutAndWithTC(tc, "[#if true]y[/#if]${1}[=2]", "[#if true]y[/#if]1[=2]", "y${1}2");
+            testedProps.add(Configuration.ExtendableBuilder.TEMPLATE_LANGUAGE_KEY);
+        }
+        {
+            // TemplateResolver-based TemplateLanguage selection, we can't use
             // assertOutput here, as that hard-coded to create an FTL Template.
 
             TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
@@ -658,7 +649,7 @@ public class TemplateConfigurationTest {
         }
 
         {
-            // As the TemplateLanguage-based parser selection happens in the TemplateResolver, we can't use
+            // As the charset-selection happens in the TemplateResolver, we can't use
             // assertOutput here, as that hard-coded to create an FTL Template.
 
             TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder();
@@ -797,7 +788,7 @@ public class TemplateConfigurationTest {
             TemplateConfiguration tc, String templateName, String ftl, String expectedDefaultOutput,
             String expectedConfiguredOutput) throws TemplateException, IOException {
         if (templateName == null) {
-            templateName = "adhoc.ftl";
+            templateName = "adhoc";
         }
         assertOutput(null, templateName, ftl, expectedDefaultOutput);
         assertOutput(tc, templateName, ftl, expectedConfiguredOutput);

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
index ebd8ff6..3e1745f 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpStringLiteral.java
@@ -54,7 +54,8 @@ final class ASTExpStringLiteral extends ASTExpression implements TemplateStringM
         // but we can't fix this backward compatibly.
         Template parentTemplate = getTemplate();
         ParsingConfiguration pCfg = parentTemplate.getParsingConfiguration();
-        InterpolationSyntax intSyn = pCfg.getInterpolationSyntax();
+        // TODO [FM3] This shouldn't assume DefaultTemplateLanguage.
+        InterpolationSyntax intSyn = ((DefaultTemplateLanguage) pCfg.getTemplateLanguage()).getInterpolationSyntax();
         if (value.length() > 3 && (
                 // Find related: [interpolation prefixes]
                 intSyn == InterpolationSyntax.DOLLAR && value.indexOf("${") != -1

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core/src/main/java/org/apache/freemarker/core/ASTInterpolation.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTInterpolation.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTInterpolation.java
index 66c2563..6ce0b7e 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTInterpolation.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTInterpolation.java
@@ -25,6 +25,7 @@ import java.io.Writer;
 import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
 import org.apache.freemarker.core.outputformat.OutputFormat;
+import org.apache.freemarker.core.util.BugException;
 import org.apache.freemarker.core.util.TemplateLanguageUtils;
 
 /**
@@ -112,8 +113,14 @@ final class ASTInterpolation extends ASTElement {
     }
 
     private String dump(boolean canonical, boolean inStringLiteral) {
+        TemplateLanguage tempLang = getTemplate().getParsingConfiguration().getTemplateLanguage();
+        if (!(tempLang instanceof DefaultTemplateLanguage)) {
+            // TODO [FM3]
+            throw new BugException("Dumping custom template langauges not yet supported");
+        }
+        InterpolationSyntax syntax = ((DefaultTemplateLanguage) tempLang).getInterpolationSyntax();
+
         StringBuilder sb = new StringBuilder();
-        InterpolationSyntax syntax = getTemplate().getInterpolationSyntax();
         sb.append(syntax != InterpolationSyntax.SQUARE_BRACKET ? "${" : "[=");
         final String exprCF = expression.getCanonicalForm();
         sb.append(inStringLiteral ? TemplateLanguageUtils.escapeStringLiteralPart(exprCF, '"') : exprCF);

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
index 7701d2d..3005979 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
@@ -47,7 +47,6 @@ import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
 import org.apache.freemarker.core.arithmetic.impl.BigDecimalArithmeticEngine;
 import org.apache.freemarker.core.model.ObjectWrapper;
 import org.apache.freemarker.core.model.ObjectWrappingException;
-import org.apache.freemarker.core.model.TemplateMarkupOutputModel;
 import org.apache.freemarker.core.model.TemplateModel;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper;
@@ -183,8 +182,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
     // ParsingConfiguration settings:
 
     private final TemplateLanguage templateLanguage;
-    private final TagSyntax tagSyntax;
-    private final InterpolationSyntax interpolationSyntax;
     private final boolean whitespaceStripping;
     private final AutoEscapingPolicy autoEscapingPolicy;
     private final OutputFormat outputFormat;
@@ -349,8 +346,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         // ParsingConfiguration settings:
 
         templateLanguage = builder.getTemplateLanguage();
-        tagSyntax = builder.getTagSyntax();
-        interpolationSyntax = builder.getInterpolationSyntax();
         whitespaceStripping = builder.getWhitespaceStripping();
         autoEscapingPolicy = builder.getAutoEscapingPolicy();
         outputFormat = builder.getOutputFormat();
@@ -617,46 +612,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         return true;
     }
 
-    /**
-     * When auto-escaping should be enabled depending on the current {@linkplain OutputFormat output format};
-     * default is {@link AutoEscapingPolicy#ENABLE_IF_DEFAULT}. Note that the default output
-     * format, {@link UndefinedOutputFormat}, is a non-escaping format, so there auto-escaping will be off.
-     * Note that the templates can turn auto-escaping on/off locally with directives like {@code <#ftl auto_esc=...>},
-     * which will ignore the policy.
-     *
-     * <p><b>About auto-escaping</b></p>
-     *
-     * <p>
-     * Auto-escaping has significance when a value is printed with <code>${...}</code>. If
-     * auto-escaping is on, FreeMarker will assume that the value is plain text (as opposed to markup or some kind of
-     * rich text), so it will escape it according the current output format (see {@link #getOutputFormat()}
-     * and {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat)}). If auto-escaping is off, FreeMarker
-     * will assume that the string value is already in the output format, so it prints it as is to the output.
-     *
-     * <p>Further notes on auto-escaping:
-     * <ul>
-     *   <li>When printing numbers, dates, and other kind of non-string values with <code>${...}</code>, they will be
-     *       first converted to string (according the formatting settings and locale), then they are escaped just like
-     *       string values.
-     *   <li>When printing {@link TemplateMarkupOutputModel}-s, they aren't escaped again (they are already escaped).
-     *   <li>Auto-escaping doesn't do anything if the current output format isn't an {@link MarkupOutputFormat}.
-     *       That's the case for the default output format, {@link UndefinedOutputFormat}, and also for
-     *       {@link PlainTextOutputFormat}.
-     *   <li>The output format inside a string literal expression is always {@link PlainTextOutputFormat}
-     *       (regardless of the output format of the containing template), which is a non-escaping format. Thus for
-     *       example, with <code>&lt;#assign s = "foo${bar}"&gt;</code>, {@code bar} will always get into {@code s}
-     *       without escaping, but with <code>&lt;#assign s&gt;foo${bar}&lt;#assign&gt;</code> it may will be escaped.
-     * </ul>
-     *
-     * <p>Note that what you set here is just a default, which can be overridden for individual templates with the
-     * {@linkplain #getTemplateConfigurations() template configurations setting}. This setting is also overridden by
-     * the standard file extensions; see them at {@link #getRecognizeStandardFileExtensions()}.
-     *
-     * @see Configuration.Builder#setAutoEscapingPolicy(AutoEscapingPolicy)
-     * @see TemplateConfiguration.Builder#setAutoEscapingPolicy(AutoEscapingPolicy)
-     * @see Configuration.Builder#setOutputFormat(OutputFormat)
-     * @see TemplateConfiguration.Builder#setOutputFormat(OutputFormat)
-     */
     @Override
     public AutoEscapingPolicy getAutoEscapingPolicy() {
         return autoEscapingPolicy;
@@ -805,7 +760,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         return true;
     }
     
-    private static final Map<String, TemplateLanguage> PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION;
+    static final Map<String, TemplateLanguage> PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION;
     static {
         PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION = new HashMap<String, TemplateLanguage>(
                 (DefaultTemplateLanguage.STANDARD_INSTANCES.length + 1) * 2, 0.5f);
@@ -838,48 +793,32 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         if (dotIdx == -1) {
             return null;
         }
-        return PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION.get(templateName.substring(dotIdx + 1).toLowerCase());
-    }
-
-    @Override
-    public TemplateLanguage getTemplateLanguage() {
-        return templateLanguage;
+        
+        return getTemplateLanguageForFileExtension(templateName.substring(dotIdx + 1));
     }
 
     /**
-     * Always {@code true} in {@link Configuration}-s; even if this setting wasn't set in the builder, it gets a default
-     * value in the {@link Configuration}.
+     * Returns the {@link TemplateLanguage} associated to given file extension, or {@code null} if none is associated
+     * with it. The lookup is case insensitive.
+     * 
+     * @param fileExtension Case insensitive, not {@code null}.
      */
-    @Override
-    public boolean isTemplateLanguageSet() {
-        return true;
+    public TemplateLanguage getTemplateLanguageForFileExtension(String fileExtension) {
+        _NullArgumentException.check(fileExtension, "extension");
+        return PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION.get(fileExtension.toLowerCase());
     }
 
     @Override
-    public TagSyntax getTagSyntax() {
-        return tagSyntax;
-    }
-
-    /**
-     * Always {@code true} in {@link Configuration}-s; even if this setting wasn't set in the builder, it gets a default
-     * value in the {@link Configuration}.
-     */
-    @Override
-    public boolean isTagSyntaxSet() {
-        return true;
+    public TemplateLanguage getTemplateLanguage() {
+        return templateLanguage;
     }
 
-    @Override
-    public InterpolationSyntax getInterpolationSyntax() {
-        return interpolationSyntax;
-    }
-    
     /**
      * Always {@code true} in {@link Configuration}-s; even if this setting wasn't set in the builder, it gets a default
      * value in the {@link Configuration}.
      */
     @Override
-    public boolean isInterpolationSyntaxSet() {
+    public boolean isTemplateLanguageSet() {
         return true;
     }
 
@@ -2383,20 +2322,10 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
         public void unsetSharedVariables() {
             this.sharedVariables = null;
         }
-
-        @Override
-        protected TagSyntax getDefaultTagSyntax() {
-            return TagSyntax.ANGLE_BRACKET;
-        }
-
-        @Override
-        protected InterpolationSyntax getDefaultInterpolationSyntax() {
-            return InterpolationSyntax.DOLLAR;
-        }
         
         @Override
         protected TemplateLanguage getDefaultTemplateLanguage() {
-            return DefaultTemplateLanguage.F3CC;
+            return DefaultTemplateLanguage.F3AC;
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java b/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
index 23ce488..999789d 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/DefaultTemplateLanguage.java
@@ -27,6 +27,7 @@ import org.apache.freemarker.core.outputformat.OutputFormat;
 import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
 import org.apache.freemarker.core.outputformat.impl.XMLOutputFormat;
+import org.apache.freemarker.core.util._NullArgumentException;
 
 // FIXME [FM3] If we leave this here, FTL will be a required dependency of core (which is not nice if
 // template languages will be pluggable).
@@ -39,19 +40,13 @@ public final class DefaultTemplateLanguage extends TemplateLanguage {
      * For the case when the file extension doesn't specify the exact syntax and the output format, instead both comes
      * from the {@link Configuration} (or {@link TemplateConfiguration}). Avoid it, as it's problematic for tooling.
      */
-    public static final DefaultTemplateLanguage F3CC = new DefaultTemplateLanguage("f3cc", true,
-            null, null, null, null);
+    public static final DefaultTemplateLanguage F3AC = new DefaultTemplateLanguage("f3ac", true,
+            null, null,
+            TagSyntax.ANGLE_BRACKET, InterpolationSyntax.DOLLAR);
+    public static final DefaultTemplateLanguage F3SC = new DefaultTemplateLanguage("f3sc", true,
+            null, null,
+            TagSyntax.SQUARE_BRACKET, InterpolationSyntax.SQUARE_BRACKET);
 
-    // TODO [FM3][CF] Emulates FM2 behavior temporarily, to make the test suite pass 
-    public static final DefaultTemplateLanguage F3CH = new DefaultTemplateLanguage("ftlh", true,
-            HTMLOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT,
-            null, null);
-    
-    // TODO [FM3][CF] Emulates FM2 behavior temporarily, to make the test suite pass 
-    public static final DefaultTemplateLanguage F3CX = new DefaultTemplateLanguage("ftlx", true,
-            XMLOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT,
-            null, null);
-    
     public static final DefaultTemplateLanguage F3AH = new DefaultTemplateLanguage("f3ah", true,
             HTMLOutputFormat.INSTANCE, AutoEscapingPolicy.ENABLE_IF_DEFAULT,
             TagSyntax.ANGLE_BRACKET, InterpolationSyntax.DOLLAR);
@@ -76,7 +71,7 @@ public final class DefaultTemplateLanguage extends TemplateLanguage {
      * List all instances for which there's a constant in this class ({@link #F3AH} and such).
      */
     public static final DefaultTemplateLanguage[] STANDARD_INSTANCES = new DefaultTemplateLanguage[] {
-            F3CC, F3CH, F3CX,
+            F3AC, F3SC,
             F3AH, F3AX, F3AU, 
             F3SH, F3SX, F3SU 
     };
@@ -92,12 +87,9 @@ public final class DefaultTemplateLanguage extends TemplateLanguage {
      * @param autoEscapingPolicy
      *            See in {@link TemplateLanguage#TemplateLanguage(String, OutputFormat, AutoEscapingPolicy)}
      * @param tagSyntax
-     *            The tag syntax used, or {@code null} it it should come from the {@link ParsingConfiguration}. Using
-     *            {@code null} is generally a bad idea, as it makes tooling harder, and can be confusing for users.
+     *            The tag syntax used; not {@code null}.
      * @param interpolationSyntax
-     *            The interpolation syntax used, or {@code null} it it should come from the
-     *            {@link ParsingConfiguration}. Using {@code null} is generally a bad idea, as it makes tooling harder,
-     *            and can be confusing for users.
+     *            The interpolation syntax used; not {@code null}.
      */
     public DefaultTemplateLanguage(
             String fileExtension,
@@ -115,6 +107,8 @@ public final class DefaultTemplateLanguage extends TemplateLanguage {
             OutputFormat outputFormat, AutoEscapingPolicy autoEscapingPolicy,
             TagSyntax tagSyntax, InterpolationSyntax interpolationSyntax) {
         super(fileExtension, allowExtensionStartingWithF, outputFormat, autoEscapingPolicy);
+        _NullArgumentException.check("tagSyntax", tagSyntax);
+        _NullArgumentException.check("interpolationSyntax", interpolationSyntax);
         this.tagSyntax = tagSyntax;
         this.interpolationSyntax = interpolationSyntax;
     }
@@ -145,10 +139,34 @@ public final class DefaultTemplateLanguage extends TemplateLanguage {
         return root;
     }
 
+    /**
+     * Determines the tag syntax (like {@code <#if x>} VS {@code [#if x]}) of the template files. Don't confuse this
+     * with the interpolation syntax ({@link #getInterpolationSyntax()}); they are independent.
+     * 
+     * <p>The value is one of:
+     * <ul>
+     *   <li>{@link TagSyntax#ANGLE_BRACKET}:
+     *     Use the angle bracket tag syntax (the normal syntax), like {@code <#include ...>}. This is the default.
+     *   <li>{@link TagSyntax#SQUARE_BRACKET}:
+     *     Use the square bracket tag syntax, like {@code [#include ...]}. Note that this does <em>not</em> change
+     *     <code>${x}</code> to {@code [=...]}; that's <em>interpolation</em> syntax, so there the relevant one is
+     *     {@link #getInterpolationSyntax()}.
+     * </ul>
+     * 
+     * @return Not {@code null}
+     */
     public TagSyntax getTagSyntax() {
         return tagSyntax;
     }
 
+    /**
+     * Determines the interpolation syntax (<code>${x}</code> VS <code>[=x]</code>) of the template files.
+     * Don't confuse this with the tag syntax ({@link #getTagSyntax()}); they are independent.
+     * Note that {@link InterpolationSyntax#SQUARE_BRACKET} does <em>not</em> change {@code <#if x>} to
+     * {@code [#if x]}; that's <em>tag</em> syntax, so there the relevant one is {@link #getTagSyntax()}.
+     *
+     * @return Not {@code null}
+     */
     public InterpolationSyntax getInterpolationSyntax() {
         return interpolationSyntax;
     }

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/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 4800a5b..3e55501 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
@@ -2551,7 +2551,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
      *            paths.)
      */
     public Template getTemplateForImporting(String name) throws IOException {
-        return getTemplateForInclusion(name, true);
+        return getTemplateForInclusion(name, false);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core/src/main/java/org/apache/freemarker/core/InterpolationSyntax.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/InterpolationSyntax.java b/freemarker-core/src/main/java/org/apache/freemarker/core/InterpolationSyntax.java
index 7ea5fbe..2012130 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/InterpolationSyntax.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/InterpolationSyntax.java
@@ -20,7 +20,7 @@
 package org.apache.freemarker.core;
 
 /**
- * Used as the value of the {@link ParsingConfiguration#getInterpolationSyntax()}  interpolationSyntax} setting.
+ * Used as the value of the {@link DefaultTemplateLanguage#getInterpolationSyntax()}  interpolationSyntax} setting.
  */
 public enum InterpolationSyntax {
     

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
index 6f6703f..5bcb652 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java
@@ -42,8 +42,6 @@ public abstract class MutableParsingAndProcessingConfiguration<
     public static final String AUTO_ESCAPING_POLICY_KEY = "autoEscapingPolicy";
     public static final String RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY = "recognizeStandardFileExtensions";
     public static final String TEMPLATE_LANGUAGE_KEY = "templateLanguage";
-    public static final String TAG_SYNTAX_KEY = "tagSyntax";
-    public static final String INTERPOLATION_SYNTAX_KEY = "interpolationSyntax";
     public static final String TAB_SIZE_KEY = "tabSize";
     public static final String INCOMPATIBLE_IMPROVEMENTS_KEY = "incompatibleImprovements";
 
@@ -53,19 +51,15 @@ public abstract class MutableParsingAndProcessingConfiguration<
                 // Must be sorted alphabetically!
                 AUTO_ESCAPING_POLICY_KEY,
                 INCOMPATIBLE_IMPROVEMENTS_KEY,
-                INTERPOLATION_SYNTAX_KEY,
                 OUTPUT_FORMAT_KEY,
                 RECOGNIZE_STANDARD_FILE_EXTENSIONS_KEY,
                 SOURCE_ENCODING_KEY,
                 TAB_SIZE_KEY,
-                TAG_SYNTAX_KEY,
                 TEMPLATE_LANGUAGE_KEY,
                 WHITESPACE_STRIPPING_KEY
             ));
 
     private TemplateLanguage templateLanguage;
-    private TagSyntax tagSyntax;
-    private InterpolationSyntax interpolationSyntax;
     private Boolean whitespaceStripping;
     private AutoEscapingPolicy autoEscapingPolicy;
     private Boolean recognizeStandardFileExtensions;
@@ -119,37 +113,17 @@ public abstract class MutableParsingAndProcessingConfiguration<
                     setRecognizeStandardFileExtensions(_StringUtils.getYesNo(value));
                 }
             } else if (TEMPLATE_LANGUAGE_KEY.equals(name)) {
-                if ("FTL".equals(value)) {
-                    setTemplateLanguage(DefaultTemplateLanguage.F3CC);
-                } else if ("staticText".equals(value)) {
-                    setTemplateLanguage(UnparsedTemplateLanguage.INSTANCE);
-                } else {
-                    throw new InvalidSettingValueException(name, value, "Unsupported template language name");
-                }
-            } else if (TAG_SYNTAX_KEY.equals(name)) {
-                if ("angleBracket".equals(value)) {
-                    setTagSyntax(TagSyntax.ANGLE_BRACKET);
-                } else if ("squareBracket".equals(value)) {
-                    setTagSyntax(TagSyntax.SQUARE_BRACKET);
-                } else {
-                    throw new InvalidSettingValueException(name, value,
-                            "angle_bracket".equals(value) ? "The correct value is: angleBracket" :
-                            "square_bracket".equals(value) ? "The correct value is: squareBracket" :
-                            "autoDetect".equals(value) || "auto_detect".equals(value)
-                                    ? "The autoDetect tag syntax is not supported since 3.0.0." :
-                            "No such predefined tag syntax name");
-                }
-            } else if (INTERPOLATION_SYNTAX_KEY.equals(name)) {
-                if ("dollar".equals(value)) {
-                    setInterpolationSyntax(InterpolationSyntax.DOLLAR);
-                } else if ("squareBracket".equals(value)) {
-                    setInterpolationSyntax(InterpolationSyntax.SQUARE_BRACKET);
-                } else {
-                    throw new InvalidSettingValueException(name, value,
-                            "legacy".equals(value) ? "The supported alternative is: dollar" :
-                            "square_bracket".equals(value) ? "The correct value is: squareBracket" :
-                            "No such predefined interpolation syntax name");
+                TemplateLanguage templateLanguage = Configuration.PREDEFINED_TEMPLATE_LANGUAGES_BY_EXTENSION.get(
+                        value.toLowerCase());
+                if (templateLanguage == null) {
+                    if ("staticText".equals(value)) {
+                        templateLanguage = UnparsedTemplateLanguage.INSTANCE;
+                    } else {
+                        // TODO [FM3] Allow setting a custom template language by class name.
+                        throw new InvalidSettingValueException(name, value, "Unsupported template language name");
+                    }
                 }
+                setTemplateLanguage(templateLanguage);
             } else if (TAB_SIZE_KEY.equals(name)) {
                 setTabSize(Integer.parseInt(value));
             } else {
@@ -177,92 +151,6 @@ public abstract class MutableParsingAndProcessingConfiguration<
         return SETTING_NAMES;
     }
 
-    /**
-     * Setter pair of {@link #getTagSyntax()}.
-     *
-     * @param tagSyntax
-     *         Can't be {@code null}
-     */
-    public void setTagSyntax(TagSyntax tagSyntax) {
-        _NullArgumentException.check("tagSyntax", tagSyntax);
-        this.tagSyntax = tagSyntax;
-    }
-
-    /**
-     * Fluent API equivalent of {@link #tagSyntax(TagSyntax)}
-     */
-    public SelfT tagSyntax(TagSyntax tagSyntax) {
-        setTagSyntax(tagSyntax);
-        return self();
-    }
-
-    /**
-     * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another
-     * {@link ParsingConfiguration}).
-     */
-    public void unsetTagSyntax() {
-        this.tagSyntax = null;
-    }
-
-    @Override
-    public TagSyntax getTagSyntax() {
-        return isTagSyntaxSet() ? tagSyntax : getDefaultTagSyntax();
-    }
-    
-    /**
-     * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value
-     * from another {@link ParsingConfiguration}, or throws {@link CoreSettingValueNotSetException}.
-     */
-    protected abstract TagSyntax getDefaultTagSyntax();
-
-    @Override
-    public boolean isTagSyntaxSet() {
-        return tagSyntax != null;
-    }
-    
-    /**
-     * Setter pair of {@link #getInterpolationSyntax()}.
-     *
-     * @param interpolationSyntax
-     *         Can't be {@code null}
-     */
-    public void setInterpolationSyntax(InterpolationSyntax interpolationSyntax) {
-        _NullArgumentException.check("interpolationSyntax", interpolationSyntax);
-        this.interpolationSyntax = interpolationSyntax;
-    }
-
-    /**
-     * Fluent API equivalent of {@link #interpolationSyntax(InterpolationSyntax)}
-     */
-    public SelfT interpolationSyntax(InterpolationSyntax interpolationSyntax) {
-        setInterpolationSyntax(interpolationSyntax);
-        return self();
-    }
-
-    /**
-     * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another
-     * {@link ParsingConfiguration}).
-     */
-    public void unsetInterpolationSyntax() {
-        this.interpolationSyntax = null;
-    }
-
-    @Override
-    public InterpolationSyntax getInterpolationSyntax() {
-        return isInterpolationSyntaxSet() ? interpolationSyntax : getDefaultInterpolationSyntax();
-    }
-    
-    /**
-     * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value
-     * from another {@link ParsingConfiguration}, or throws {@link CoreSettingValueNotSetException}.
-     */
-    protected abstract InterpolationSyntax getDefaultInterpolationSyntax();
-
-    @Override
-    public boolean isInterpolationSyntaxSet() {
-        return interpolationSyntax != null;
-    }
-
     @Override
     public TemplateLanguage getTemplateLanguage() {
          return isTemplateLanguageSet() ? templateLanguage : getDefaultTemplateLanguage();

http://git-wip-us.apache.org/repos/asf/freemarker/blob/e9ca9d4c/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
index 9373a07..3d315fc 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
@@ -1515,22 +1515,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
      *       Supported units are: "s" (seconds), "ms" (milliseconds), "m" (minutes), "h" (hours). The whitespace between
      *       the unit and the number is optional. Units are only supported since 2.3.23.
      *       
-     *   <li><p>{@code "tagSyntax"}:
-     *       See {@link ParsingConfiguration#getTagSyntax()}.
-     *       <br>String value: Must be one of
-     *       {@code "autoDetect"}, {@code "squareBracket"}, and {@code "squareBracket"} (like {@code [#if x]}).
-     *       <br>Note that setting the {@code "tagSyntax"} to {@code "squareBracket"} does <em>not</em> change
-     *       <code>${x}</code> to {@code [=...]}; that's <em>interpolation</em> syntax, so use the
-     *       {@code "interpolationSyntax"} setting for that, not this setting..       
-     *
-     *   <li><p>{@code "interpolationSyntax"}:
-     *       See {@link ParsingConfiguration#getInterpolationSyntax()}.
-     *       <br>String value: Must be one of
-     *       {@code "legacy"}, {@code "dollar"}, and {@code "square_bracket"} (like {@code [=x]}). 
-     *       <br>Note that setting the {@code "interpolationSyntax"} to {@code "squareBracket"} does <em>not</em> change
-     *       {@code <#if x>} to {@code [#if x]}; that's <em>tag</em> syntax, so use the
-     *       {@code "tagSyntax"} setting for that, not this setting.       
-     *       
      *   <li><p>{@code "incompatibleImprovements"}:
      *       See {@link Configuration#getIncompatibleImprovements()}.
      *       <br>String value: version number like {@code 2.3.20}.
@@ -1885,7 +1869,9 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
      * it was removed, otherwise returns {@code null}.
      */
     protected Version getRemovalVersionForUnknownSetting(String name) {
-        if (name.equals("classic_compatible") || name.equals("classicCompatible")) {
+        if (name.equals("classic_compatible") || name.equals("classicCompatible")
+                || name.equals("tag_syntax") || name.equals("tagSyntax")
+                || name.equals("interpolation_syntax") || name.equals("interpolationSyntax")) {
             return Configuration.VERSION_3_0_0;
         }
         return null;


Mime
View raw message