FREEMARKER-63: Lot of refinement in the API-s and implementation. #macro now creates a `TemplateDirectiveModel`, and #function now creates `TemplateFunctionModel` (though the function/method call syntax doesn't yet allow named parameters). Test suite passes.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/3cacd9ed Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/3cacd9ed Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/3cacd9ed Branch: refs/heads/3 Commit: 3cacd9ed04a231af67e3964525fd592b97da1665 Parents: da4c332 Author: ddekany <[email protected]> Authored: Thu Aug 3 23:11:57 2017 +0200 Committer: ddekany <[email protected]> Committed: Thu Aug 3 23:11:57 2017 +0200 ---------------------------------------------------------------------- FM3-CHANGE-LOG.txt | 48 ++- .../freemarker/core/CanonicalFormTest.java | 4 +- .../freemarker/core/DirectiveCallPlaceTest.java | 1 - .../EnvironmentGetTemplateVariantsTest.java | 1 - .../core/MistakenlyPublicMacroAPIsTest.java | 21 +- .../core/ParsingErrorMessagesTest.java | 65 +++- .../core/TemplateCallableModelTest.java | 140 +++++-- .../core/TheadInterruptingSupportTest.java | 1 - .../core/userpkg/AllFeaturesDirective.java | 9 +- .../core/userpkg/AllFeaturesFunction.java | 114 ++++++ .../core/userpkg/NamedVarargsOnlyDirective.java | 5 +- .../userpkg/PositionalVarargsOnlyDirective.java | 13 +- .../userpkg/PositionalVarargsOnlyFunction.java | 62 +++ .../core/userpkg/TestTemplateCallableModel.java | 88 +++++ .../userpkg/TestTemplateDirectiveModel.java | 88 ----- .../core/userpkg/TwoNamedParamsDirective.java | 5 +- .../TwoNestedContentParamsDirective.java | 5 +- .../userpkg/TwoPositionalParamsDirective.java | 5 +- .../userpkg/TwoPositionalParamsFunction.java | 63 +++ .../core/userpkg/UpperCaseDirective.java | 2 +- .../core/util/StringToIndexMapTest.java | 5 + .../core/valueformat/NumberFormatTest.java | 2 +- .../org/apache/freemarker/core/ast-1.ast | 24 +- .../apache/freemarker/core/ast-assignments.ast | 3 +- .../freemarker/core/cano-macro-and-function.ftl | 43 +++ .../core/cano-macro-and-function.ftl.out | 42 ++ .../org/apache/freemarker/core/cano-macros.ftl | 29 -- .../apache/freemarker/core/cano-macros.ftl.out | 28 -- .../core/templatesuite/expected/macros2.txt | 22 -- .../templatesuite/templates/api-builtins.ftl | 20 +- .../core/templatesuite/templates/boolean.ftl | 8 +- .../templatesuite/templates/comparisons.ftl | 216 +++++------ .../templates/date-type-builtins.ftl | 32 +- .../templatesuite/templates/dateparsing.ftl | 4 +- .../templates/existence-operators.ftl | 34 +- .../core/templatesuite/templates/hashconcat.ftl | 2 +- .../templates/identifier-non-ascii.ftl | 2 +- .../core/templatesuite/templates/list.ftl | 2 +- .../core/templatesuite/templates/list2.ftl | 2 +- .../core/templatesuite/templates/list3.ftl | 8 +- .../core/templatesuite/templates/listhash.ftl | 2 +- .../core/templatesuite/templates/macros.ftl | 17 +- .../core/templatesuite/templates/macros2.ftl | 35 -- .../templates/number-math-builtins.ftl | 68 ++-- .../core/templatesuite/templates/recover.ftl | 8 +- .../core/templatesuite/templates/root.ftl | 2 +- .../templates/sequence-builtins.ftl | 18 +- .../templates/string-builtin-coercion.ftl | 24 +- .../templates/string-builtins-regexps.ftl | 6 +- .../core/templatesuite/templates/var-layers.ftl | 2 +- .../freemarker/core/templatesuite/testcases.xml | 1 - .../org/apache/freemarker/core/ASTDirMacro.java | 325 ---------------- .../freemarker/core/ASTDirMacroOrFunction.java | 369 ++++++++++++++++++ .../apache/freemarker/core/ASTDirNested.java | 91 ++--- .../apache/freemarker/core/ASTDirReturn.java | 2 +- .../freemarker/core/ASTDynamicTopLevelCall.java | 164 ++++---- .../org/apache/freemarker/core/ASTElement.java | 4 +- .../freemarker/core/ASTExpBuiltInVariable.java | 4 +- .../freemarker/core/ASTExpListLiteral.java | 8 +- .../freemarker/core/ASTExpMethodCall.java | 117 +++++- .../apache/freemarker/core/ASTStaticText.java | 2 +- .../core/BuiltInsForMultipleTypes.java | 14 +- .../freemarker/core/BuiltInsForStringsMisc.java | 1 - .../org/apache/freemarker/core/CallPlace.java | 195 ++++++++++ ...lPlaceCustomDataInitializationException.java | 3 +- .../org/apache/freemarker/core/Environment.java | 379 +++++++++++-------- .../apache/freemarker/core/LocalContext.java | 2 +- .../org/apache/freemarker/core/MessageUtil.java | 2 +- .../freemarker/core/NonDirectiveException.java | 63 +++ .../freemarker/core/NonTemplateCallPlace.java | 166 ++++++++ .../NonUserDefinedDirectiveLikeException.java | 65 ---- .../apache/freemarker/core/ParameterRole.java | 6 +- .../org/apache/freemarker/core/Template.java | 2 +- .../core/TemplateCallableModelUtils.java | 46 --- ...nterruptionSupportTemplatePostProcessor.java | 1 - .../org/apache/freemarker/core/_CoreAPI.java | 10 +- .../core/_ErrorDescriptionBuilder.java | 5 +- .../core/_TemplateCallableModelUtils.java | 112 ++++++ .../core/model/ArgumentArrayLayout.java | 101 +++-- .../apache/freemarker/core/model/CallPlace.java | 179 --------- .../apache/freemarker/core/model/Constants.java | 2 + .../core/model/TemplateCallableModel.java | 6 +- .../core/model/TemplateDirectiveModel.java | 43 ++- .../core/model/TemplateFunctionModel.java | 41 +- .../core/util/DuplicateStringKeyException.java | 38 ++ .../apache/freemarker/core/util/FTLUtil.java | 40 +- .../freemarker/core/util/StringToIndexMap.java | 29 +- freemarker-core/src/main/javacc/FTL.jj | 328 ++++++++++------ .../examples/AutoEscapingExample-infoBox.ftlh | 2 +- .../apache/freemarker/servlet/IncludePage.java | 2 +- .../jsp/CustomTagAndELFunctionCombiner.java | 2 +- .../servlet/jsp/SimpleTagDirectiveModel.java | 2 +- .../servlet/jsp/TagDirectiveModel.java | 2 +- .../test/templateutil/AssertDirective.java | 16 +- .../templateutil/AssertEqualsDirective.java | 2 +- .../test/templateutil/AssertFailsDirective.java | 2 +- .../test/templateutil/NoOutputDirective.java | 2 +- 97 files changed, 2709 insertions(+), 1739 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/FM3-CHANGE-LOG.txt ---------------------------------------------------------------------- diff --git a/FM3-CHANGE-LOG.txt b/FM3-CHANGE-LOG.txt index 21ce533..aab66b7 100644 --- a/FM3-CHANGE-LOG.txt +++ b/FM3-CHANGE-LOG.txt @@ -48,7 +48,21 @@ Major changes / features Examples: `<@x x + 1 2 3 />` now must be written as `<@x x + 1, 2, 3 />` `<#nested x y>` now must be written as `<#nested x, y>` -- TemplateDirectiveModel was redesigned to be more universal. +- #macro-s and #function + - Both #macro-s and #function-s can now define parameters that are passed by position, and that are passed by name. + Function parameters are by default positional, which can be changed by adding `{named}` after the parameter name. + Macro parameters are by default named, which can be changed by adding `{positional}` after the parameter name. + Positional parameters always precede the named ones. There can be both a positional and a named varargs parameter; + the first is always a sequnce, the later is always a hash. + Examples: + - All named: `<#macro heading title icon>...</#macro>` `<@heading title="Test" icon="foo.jpg" />` + - Mixed: `<#macro heading title{positional} icon>...</#macro>` `<@heading "Test" icon="foo.jpg" />` + - All positional: `<#function f(x, y, r=0)>...</#function>` `${f(1, 2)} ${f(1, 2, 10)}` + - Mixed: `<#function f(x, y, r{named}=0)>...</#function>` `${f(1, 2)} ${f(1, 2, r=10)}` + - Positional varargs: `<#function sum(xs... abs{named}=false)>...</#function>` `${sum(1, 2, 3, abs=true)} + - Positional and named varargs: `<#function f(xs..., props{named}...)>...</#function>` `${f(1, 2, 3, x=1, y=2)}` + - In FM2, the same macro could be called with specifying all parameters by position, or by specifying all parameters + by name. In FM3 that won't work anymore, as now a parameter is either strictly positional or strictly named. Smaller changes --------------- @@ -104,13 +118,25 @@ Node: Changes already mentioned above aren't repeated here! - TemplateDirectiveModel was redesigend (see in the major changes section) - Removed `TemplateTransformModel`; `TemplateDirectiveModel` can do the same things, and more. - Renamed `DirectiveCallPlace` to `CallPlace` - - Removed Environment.getDirectiveCallPlace(), as TemplateDirectiveModel-s now get the CallPlace as the parameter - of the `execute` method. + - Removed Environment.getDirectiveCallPlace(), as TemplateDirectiveModel-s now get the CallPlace as the + parameter of the `execute` method. - ?isTransform was removed (as there are no transforms anymore). Converter note: The template converter tool replaces it with ?isDirective - The directive returned by `?interpret` doesn't allow nested content anymore. (It wasn't useful earlier either; the nested content was simply executed after the interpreted string.) - +- Changes in #macro/#functions + - See major changes first, in the earlier chapter + - It's not tolerated anymore if the caller of a macro has declared more nested content parameters than + what `#nested` passes to it (like in `<#macro m><#nested 1, 2></#macro> <@m ; i, j, k>...</@>`, where `k` has + no corresponding value in `#nested`). + - In `#macro` (and `function`) named parameters with default values need not be at the end of the parameter list + anymore. (Positional parameters with default values need to be at the end of the list of positional parameters + only.) + - When parameter default expressions are evaluated, only the parameters defined earlier are already set. + So `<#macro m a b=a>` works, but `<#macro m a=b b>` won't work anymore (unless there's `b` outside the + parameter list), as `b` is not yet set when the default of `a` is calculated. + + Java API changes ================ @@ -165,7 +191,18 @@ Major changes / features - Configuration is now immutable. You should use Configuration.Builder to set up the setting values, then create the Configuration with the builder's build() method. - Configuration defaults were changed to follow the current best practices (like default charset is UTF-8 everywhere) -- Removed freemarker.ext.log, our log abstraction layer from the old times when there was no clear winner on this field. +- Reworked callable `TemplateModel`-s (i.e., models that can be called like `foo(...)` or as `<@foo .../>`) + - Earlier there were several callable `TemplateModel` internfaces (`TemplateMethodModel`, `TemplateMethodModelEx`, + `TemplateDirectiveModel`, `TemplateTransformModel`). FM3 replaces them with only two new interfaces, + `TemplateDirectiveModel` (differs from the interface with identical name in FM2) and `TemplateFunctionModel`. + (These are both the subinterfaces of another new interface `TemplateCallableModel`.) + [TODO: TemplateMethodModel[Ex] wasn't yet replaced by TemplateFunctionModel.] + - All callable TempalteModel-s support passing parameters by position and by name, even in the same call + (e.g., `<@heading "Some title" icon="foo.jpg" />`, `sum(1, 2, 3, abs=true)`) + - `#macro` now produces a `TemplateDirectiveModel` and `#function` produces a `TemplateFunctionModel`. (Earlier, the + product was just a generic `TemplateModel` that could only be invoked using internal API-s, and had capabilities + that the callable TemplateModel-s coulnd't have.) +- Removed freemarker.ext.log, our log abstraction layer from the times when there was no clear winner on this field. 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.] @@ -426,6 +463,7 @@ Core / Miscellaneous "compress" - Removed `NestedContentNotSupportedException`, as `TemplateDirectiveModel.isNestedContentSupported()` now takes care of that problem. +- CallPlaceCustomDataInitializationException is not a checked exception anymore (now it extends RuntimeException) Build / development process changes http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/CanonicalFormTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CanonicalFormTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CanonicalFormTest.java index fd1a5a5..1bf4888 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CanonicalFormTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CanonicalFormTest.java @@ -33,8 +33,8 @@ public class CanonicalFormTest extends FileTestCase { super(name); } - public void testMacrosCanonicalForm() throws Exception { - assertCanonicalFormOf("cano-macros.ftl"); + public void testCallableDefinitionCanonicalForm() throws Exception { + assertCanonicalFormOf("cano-macro-and-function.ftl"); } public void testIdentifierEscapingCanonicalForm() throws Exception { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/DirectiveCallPlaceTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/DirectiveCallPlaceTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/DirectiveCallPlaceTest.java index f959b1d..7ee42c2 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/DirectiveCallPlaceTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/DirectiveCallPlaceTest.java @@ -27,7 +27,6 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateHashModelEx2; import org.apache.freemarker.core.model.TemplateModel; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java index 10205e9..a094ec6 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/EnvironmentGetTemplateVariantsTest.java @@ -26,7 +26,6 @@ import java.io.Writer; import java.util.Collections; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.impl.SimpleScalar; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicMacroAPIsTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicMacroAPIsTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicMacroAPIsTest.java index 9c87e61..ad27627 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicMacroAPIsTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/MistakenlyPublicMacroAPIsTest.java @@ -19,15 +19,12 @@ package org.apache.freemarker.core; -import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.io.IOException; import java.io.StringWriter; import java.util.Map; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.util._NullWriter; import org.apache.freemarker.test.TestConfigurationBuilder; import org.junit.Test; @@ -44,7 +41,7 @@ public class MistakenlyPublicMacroAPIsTest { @Test public void testMacroCopyingExploit() throws IOException, TemplateException { Template tMacros = new Template(null, "<#macro m1>1</#macro><#macro m2>2</#macro>", cfg); - Map<String, ASTDirMacro> macros = tMacros.getMacros(); + Map<String, ASTDirMacroOrFunction> macros = tMacros.getMacros(); Template t = new Template(null, "<@m1/><@m2/><@m3/>" @@ -60,25 +57,11 @@ public class MistakenlyPublicMacroAPIsTest { public void testMacroCopyingExploitAndNamespaces() throws IOException, TemplateException { Template tMacros = new Template(null, "<#assign x = 0><#macro m1>${x}</#macro>", cfg); Template t = new Template(null, "<#assign x = 1><@m1/>", cfg); - t.addMacro((ASTDirMacro) tMacros.getMacros().get("m1")); + t.addMacro((ASTDirMacroOrFunction) tMacros.getMacros().get("m1")); assertEquals("1", getTemplateOutput(t)); } - @Test - public void testMacroCopyingFromFTLVariable() throws IOException, TemplateException { - Template tMacros = new Template(null, "<#assign x = 0><#macro m1>${x}</#macro>", cfg); - Environment env = tMacros.createProcessingEnvironment(null, _NullWriter.INSTANCE); - env.process(); - TemplateModel m1 = env.getVariable("m1"); - assertThat(m1, instanceOf(ASTDirMacro.class)); - - Template t = new Template(null, "<#assign x = 1><@m1/>", cfg); - t.addMacro((ASTDirMacro) m1); - - assertEquals("1", getTemplateOutput(t)); - } - private String getTemplateOutput(Template t) throws TemplateException, IOException { StringWriter sw = new StringWriter(); t.process(null, sw); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/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 77dbe0a..3189615 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 @@ -62,7 +62,9 @@ public class ParsingErrorMessagesTest { @Test public void testUnclosedDirectives() { assertErrorContains("<#macro x>", "#macro", "unclosed"); + assertErrorContains("<#macro x></#function>", "macro end tag"); assertErrorContains("<#function x()>", "#macro", "unclosed"); + assertErrorContains("<#function x()></#macro>", "function end tag"); assertErrorContains("<#assign x>", "#assign", "unclosed"); assertErrorContains("<#macro m><#local x>", "#local", "unclosed"); assertErrorContains("<#global x>", "#global", "unclosed"); @@ -122,15 +124,62 @@ public class ParsingErrorMessagesTest { assertErrorContains("<#assign x = x}>", "\"}\"", "open"); // TODO assertErrorContains("<#assign x = '${x'>", "unclosed"); } - + + @Test + public void testUnknownHeaderParameter() { + assertErrorContains("<#ftl foo=1>", "Unknown", "foo"); + assertErrorContains("<#ftl attributes={}>", "Unknown", "attributes", "customSettings"); + } + + @Test + public void testDynamicTopCalls() throws IOException, TemplateException { + assertErrorContains("<@a, n1=1 />", "Remove comma", "between", "by position"); + assertErrorContains("<@a n1=1, n2=1 />", "Remove comma", "between", "by position"); + assertErrorContains("<@a n1=1, 2 />", "Remove comma", "between", "by position"); + assertErrorContains("<@a, 1 />", "Remove comma", "between", "by position"); + assertErrorContains("<@a 1, , 2 />", "Two commas"); + assertErrorContains("<@a 1 2 />", "Missing comma"); + assertErrorContains("<@a n1=1 2 />", "must be earlier than arguments passed by name"); + } + + @Test + public void testMacroAndFunctionDefinitions() { + assertErrorContains("<#macro m><#macro n></#macro></#macro>", "nested into each other"); + assertErrorContains("<#macro m(a)></#macro>", "can't use \"(\""); + assertErrorContains("<#function f a></#function>", "must use \"(\""); + assertErrorContains("<#macro m a{badOption})></#macro>", "\"badOption\"", + "\"" + ASTDirMacroOrFunction.POSITIONAL_PARAMETER_OPTION_NAME + "\"", + "\"" + ASTDirMacroOrFunction.NAMED_PARAMETER_OPTION_NAME + "\""); + assertErrorContains("<#function f(a{named}, b)></#function>", "Positional", "must precede named"); + assertErrorContains("<#function f(a..., b)></#function>", "another", "after", "positional varargs"); + assertErrorContains("<#function f(a..., b...)></#function>", "another", "after", "positional varargs"); + assertErrorContains("<#macro m a... b></#macro>", "another", "after", "named varargs"); + assertErrorContains("<#macro m a... b...></#macro>", "another", "after", "named varargs"); + assertErrorContains("<#function f(a b)></#function>", "Function", "must have comma"); + assertErrorContains("<#function f(a{named} b{named})></#function>", "Function", "must have comma"); + assertErrorContains("<#macro m a, b></#macro>", "Named param", "macro", "need no comma"); + assertErrorContains("<#macro m a{positional} b{positional}></#macro>", + "Positional param", "must have comma"); + assertErrorContains("<#macro m a...=[]></#macro>", "Varargs", "default"); + assertErrorContains("<#function f(a=0, b)></#function>", "with default", "without a default"); + assertErrorContains("<#function f(a,)></#function>", "Comma without"); + assertErrorContains("<#macro m a{positional}, b{positional},></#macro>", "Comma without"); + assertErrorContains(false, "<#function f(a, b></#function>"); + assertErrorContains(false, "<#function f(></#function>"); + assertErrorContains(false, "[#ftl][#function f(a, b][/#function]", "Missing closing \")\""); + assertErrorContains(false, "[#ftl][#function f(][/#function]", "Missing closing \")\""); + assertErrorContains("<#macro m a b)></#macro>", "\")\" without", "opening"); + assertErrorContains("<#macro m a b a></#macro>", "\"a\"", "multiple"); + } + private void assertErrorContains(String ftl, String... expectedSubstrings) { assertErrorContains(false, ftl, expectedSubstrings); assertErrorContains(true, ftl, expectedSubstrings); } - private void assertErrorContains(boolean squareTags, String ftl, String... expectedSubstrings) { + private void assertErrorContains(boolean convertToSquare, String ftl, String... expectedSubstrings) { try { - if (squareTags) { + if (convertToSquare) { ftl = ftl.replace('<', '[').replace('>', ']'); } new Template("adhoc", ftl, cfg); @@ -139,7 +188,7 @@ public class ParsingErrorMessagesTest { String msg = e.getMessage(); for (String needle: expectedSubstrings) { if (needle.startsWith("\\!")) { - String netNeedle = needle.substring(2); + String netNeedle = needle.substring(2); if (msg.contains(netNeedle)) { fail("The message shouldn't contain substring " + _StringUtil.jQuote(netNeedle) + ":\n" + msg); } @@ -153,15 +202,9 @@ public class ParsingErrorMessagesTest { throw new RuntimeException(e); } } - + private void showError(Throwable e) { //System.out.println(e); } - @Test - public void testUnknownHeaderParameter() { - assertErrorContains("<#ftl foo=1>", "Unknown", "foo"); - assertErrorContains("<#ftl attributes={}>", "Unknown", "attributes", "customSettings"); - } - } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java index b7d55f5..3459aea 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TemplateCallableModelTest.java @@ -22,11 +22,14 @@ package org.apache.freemarker.core; import java.io.IOException; import org.apache.freemarker.core.userpkg.AllFeaturesDirective; +import org.apache.freemarker.core.userpkg.AllFeaturesFunction; import org.apache.freemarker.core.userpkg.NamedVarargsOnlyDirective; import org.apache.freemarker.core.userpkg.PositionalVarargsOnlyDirective; +import org.apache.freemarker.core.userpkg.PositionalVarargsOnlyFunction; import org.apache.freemarker.core.userpkg.TwoNamedParamsDirective; import org.apache.freemarker.core.userpkg.TwoNestedContentParamsDirective; import org.apache.freemarker.core.userpkg.TwoPositionalParamsDirective; +import org.apache.freemarker.core.userpkg.TwoPositionalParamsFunction; import org.apache.freemarker.core.userpkg.UpperCaseDirective; import org.apache.freemarker.test.TemplateTest; import org.junit.Before; @@ -36,15 +39,20 @@ public class TemplateCallableModelTest extends TemplateTest { @Before public void addCommonData() { - addToDataModel("a", new AllFeaturesDirective()); + addToDataModel("a", AllFeaturesDirective.INSTANCE); addToDataModel("p", TwoPositionalParamsDirective.INSTANCE); addToDataModel("n", TwoNamedParamsDirective.INSTANCE); addToDataModel("pvo", PositionalVarargsOnlyDirective.INSTANCE); addToDataModel("nvo", NamedVarargsOnlyDirective.INSTANCE); + addToDataModel("uc", UpperCaseDirective.INSTANCE); + + addToDataModel("fa", AllFeaturesFunction.INSTANCE); + addToDataModel("fp", TwoPositionalParamsFunction.INSTANCE); + addToDataModel("fpvo", PositionalVarargsOnlyFunction.INSTANCE); } @Test - public void testArguments() throws IOException, TemplateException { + public void testDirectiveArguments() throws IOException, TemplateException { assertOutput("<@p />", "#p(p1=null, p2=null)"); assertOutput("<@p 1 />", @@ -103,6 +111,34 @@ public class TemplateCallableModelTest extends TemplateTest { } @Test + public void testFunctionArguments() throws IOException, TemplateException { + // TODO [FM3] Add more tests as named parameters become supported + + assertOutput("${fp()}", + "fp(p1=null, p2=null)"); + assertOutput("${fp(1)}", + "fp(p1=1, p2=null)"); + assertOutput("${fp(1, 2)}", + "fp(p1=1, p2=2)"); + + assertOutput("${fpvo()}", + "fpvo(pVarargs=[])"); + assertOutput("${fpvo(1)}", + "fpvo(pVarargs=[1])"); + assertOutput("${fpvo(1, 2)}", + "fpvo(pVarargs=[1, 2])"); + + assertOutput("${fa()}", + "fa(p1=null, p2=null, pVarargs=[], n1=null, n2=null, nVarargs={})"); + assertOutput("${fa(1, 2)}", + "fa(p1=1, p2=2, pVarargs=[], n1=null, n2=null, nVarargs={})"); + assertOutput("${fa(1, 2, 3)}", + "fa(p1=1, p2=2, pVarargs=[3], n1=null, n2=null, nVarargs={})"); + assertOutput("${fa(1, 2, 3, 4)}", + "fa(p1=1, p2=2, pVarargs=[3, 4], n1=null, n2=null, nVarargs={})"); + } + + @Test public void testNestedContent() throws IOException, TemplateException { assertOutput("<@a />", "#a(p1=null, p2=null, pVarargs=[], n1=null, n2=null, nVarargs={})"); @@ -140,18 +176,16 @@ public class TemplateCallableModelTest extends TemplateTest { assertOutput("<@a + 1 />", "#a(p1=1, p2=null, pVarargs=[], n1=null, n2=null, nVarargs={})"); - } - @Test - @SuppressWarnings("ThrowableNotThrown") - public void testParsingErrors() throws IOException, TemplateException { - assertErrorContains("<@a, n1=1 />", "Remove comma", "between", "by position"); - assertErrorContains("<@a n1=1, n2=1 />", "Remove comma", "between", "by position"); - assertErrorContains("<@a n1=1, 2 />", "Remove comma", "between", "by position"); - assertErrorContains("<@a, 1 />", "Remove comma", "between", "by position"); - assertErrorContains("<@a 1, , 2 />", "Two commas"); - assertErrorContains("<@a 1 2 />", "Missing comma"); - assertErrorContains("<@a n1=1 2 />", "must be earlier than arguments passed by name"); + assertOutput("<@nvo a=x! 1 b=2 />", + "#nvo(nVarargs={\"a\": 1, \"b\": 2})"); + assertOutput("<@nvo a=x! b=2 />", + "#nvo(nVarargs={\"a\": \"\", \"b\": 2})"); + assertOutput("<@nvo a=x!b=2 />", + "#nvo(nVarargs={\"a\": \"\", \"b\": 2})"); + + assertOutput("<@nvo a=(1)b=2 />", + "#nvo(nVarargs={\"a\": 1, \"b\": 2})"); } @Test @@ -160,7 +194,9 @@ public class TemplateCallableModelTest extends TemplateTest { assertErrorContains("<@p 9, 9, 9 />", "can only have 2", "3", "by position"); assertErrorContains("<@n 9 />", "can't have arguments passed by position"); assertErrorContains("<@n n3=9 />", "has no", "\"n3\"", "supported", "\"n1\", \"n2\""); - assertErrorContains("<@p n1=9 />", "doesn't have any by-name-passed"); + assertErrorContains("<@p n1=9 />", "directive", "can't have arguments that are passed by name", "\"n1\""); + assertErrorContains("<@uc n1=9 />", "directive", "doesn't support any parameters"); + assertErrorContains("<@uc 9 />", "directive", "doesn't support any parameters"); addToDataModel("tncp", TwoNestedContentParamsDirective.INSTANCE); assertErrorContains("<@tncp />", " no ", " 2 "); @@ -175,18 +211,76 @@ public class TemplateCallableModelTest extends TemplateTest { @Test public void testMacros() throws IOException, TemplateException { + assertOutput("<#macro m>text</#macro><@m /> <@m />", + "text text"); + assertOutput("<#macro m a>text ${a}</#macro><@m a=1 /> <@m a=2 />", + "text 1 text 2"); + assertOutput("<#macro m a b=2>text ${a} ${b}</#macro><@m a=1 /> <@m a=11 b=22 />", + "text 1 2 text 11 22"); + assertOutput("<#macro m a{positional}>text ${a}</#macro><@m 1 /> <@m 2 />", + "text 1 text 2"); + assertOutput("<#macro m a{positional}, b{positional}=2>text ${a} ${b}</#macro><@m 1 /> <@m 11, 22 />", + "text 1 2 text 11 22"); + assertOutput("<#macro m a{positional}, b{positional}=2 c d=4>text ${a} ${b} ${c} ${d}</#macro>" + + "<@m 1 c=3 /> <@m 11, 22 c=33 d=44 />", + "text 1 2 3 4 text 11 22 33 44"); + + assertOutput("<#macro m>[<#nested>]</#macro><@m>text</@m>", + "[text]"); + assertOutput("<#macro m>[<#nested 1>, <#nested 2>]</#macro><@m ; i>text ${i}</@m>", + "[text 1, text 2]"); + assertOutput("<#macro m>[<#nested 1, 2>]</#macro><@m ; i, j>${i} ${j}</@m>", + "[1 2]"); assertOutput("<#macro m a b=22><#list 1..2 as n>[<#nested a * n, b * n>]</#list></#macro>" - + "<@m 11; i, j>${i} ${j}</@m> <@m a=1 b=2; i, j>${i} ${j}</@m>", + + "<@m a=11; i, j>${i} ${j}</@m> <@m a=1 b=2; i, j>${i} ${j}</@m>", "[11 22][22 44] [1 2][2 4]"); - assertOutput("<#macro m a b others...>[a=${a}, b=${b}<#if others?hasContent>, </#if>" - + "<#if others?isSequence>" - + "<#list others as v>${v}<#sep>, </#list>" - + "<#else>" - + "<#list others as k, v>${k}=${v}<#sep>, </#list>" - + "</#if>]" + assertOutput("<#macro m1><#local x = 1>${x}{<@m2>${x}<<#list [3] as x>${x}</#list>>${x}</@m2>}${x}</#macro>" + + "<#macro m2><#local x = 2>${x}[<#nested>]${x}</#macro>" + + "<#assign x = 0>${x}(<@m1 />)${x}", + "0(1{2[1<3>1]2}1)0"); + assertOutput("<#macro m1>" + + "<#local x = 0>${x} <#list [1, 2] as x>${x}{<@m2>${x}</@m2>}${x}<#sep> </#list> ${x}" + "</#macro>" - + "<@m 1, 2 /> <@m 1, 2, 3, 4 /> <@m a=1 b=2 /> <@m a=1 b=2 c=3 d=4 />", - "[a=1, b=2] [a=1, b=2, 3, 4] [a=1, b=2] [a=1, b=2, c=3, d=4]"); + + "<#macro m2><#list [3, 4] as x>${x}[<#nested>]${x}<#sep> </#list></#macro>" + + "<@m1 />", + "0 1{3[1]3 4[1]4}1 2{3[2]3 4[2]4}2 0"); + + assertOutput("<#macro m a b=0 others...>[" + + "a=${a}, b=${b}" + + "<#list others>, <#items as k, v>${k}=${v}<#sep>, </#items></#list>" + + "]</#macro>" + + "<@m a=1 /> <@m a=1 b=2 /> <@m a=1 b=2 c=3 d=4 />", + "[a=1, b=0] [a=1, b=2] [a=1, b=2, c=3, d=4]"); + assertOutput("<#macro m a{positional}, b{positional}=0, others{positional}...>[" + + "a=${a}, b=${b}" + + "<#list others>, <#items as v>${v}<#sep>, </#items></#list>" + + "]</#macro>" + + "<@m 1 /> <@m 1, 2 /> <@m 1, 2, 3, 4 />", + "[a=1, b=0] [a=1, b=2] [a=1, b=2, 3, 4]"); + assertOutput("<#macro m pVarargs{positional}... nVarargs...>" + + "[<#list pVarargs as v>${v}<#sep>, </#list>]" + + "{<#list nVarargs as k, v>${k}=${v}<#sep>, </#list>}" + + "</#macro>" + + "<@m 1, 2 a=1 b=2 /> <@m 1, 2 /> <@m a=1 b=2 />", + "[1, 2]{a=1, b=2} [1, 2]{} []{a=1, b=2}"); + + assertOutput("<#macro m x{positional}, y{positional}><#local y++><#local z = x + y>${x} + ${y} = ${z}</#macro>" + + "<@m 1, 2 />", + "1 + 3 = 4"); + + // Default expression sees previous argument: + assertOutput("<#macro m a{positional} b=a>${a}${b}</#macro><@m 1/> <@m 2 b=3/>", "11 23"); + + addTemplate("lib.ftl", "" + + "<#assign defaultA=1>" + + "<#assign b=2>" + + "<#macro m a=defaultA>${a} ${b}[<#nested>]${b} ${a}</#macro>"); + assertOutput("<#import 'lib.ftl' as lib>" + + "<#assign a='a'>" + + "<#assign b='b'>" + + "<@lib.m>${a}${b}</@> " + + "<@lib.m a=3>${a}${b}</@>" + + "", "1 2[ab]2 1 3 2[ab]2 3"); } @Test http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java index a6b01ac..61c5823 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java @@ -26,7 +26,6 @@ import java.io.Writer; import org.apache.freemarker.core.ThreadInterruptionSupportTemplatePostProcessor.TemplateProcessingThreadInterruptedException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.util._NullWriter; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java index 24a3a4e..3509b78 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesDirective.java @@ -19,7 +19,7 @@ package org.apache.freemarker.core.userpkg; -import static org.apache.freemarker.core.TemplateCallableModelUtils.*; +import static org.apache.freemarker.core._TemplateCallableModelUtils.*; import java.io.IOException; import java.io.Writer; @@ -27,7 +27,8 @@ import java.io.Writer; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateHashModelEx2; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateNumberModel; @@ -35,7 +36,9 @@ import org.apache.freemarker.core.model.TemplateSequenceModel; import org.apache.freemarker.core.model.impl.SimpleNumber; import org.apache.freemarker.core.util.StringToIndexMap; -public class AllFeaturesDirective extends TestTemplateDirectiveModel { +public class AllFeaturesDirective extends TestTemplateCallableModel implements TemplateDirectiveModel { + + public static final AllFeaturesDirective INSTANCE = new AllFeaturesDirective(); private static final int P1_ARG_IDX = 0; private static final int P2_ARG_IDX = 1; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java new file mode 100644 index 0000000..7f1f6c1 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AllFeaturesFunction.java @@ -0,0 +1,114 @@ +/* + * 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.userpkg; + +import static org.apache.freemarker.core._TemplateCallableModelUtils.*; + +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.TemplateException; +import org.apache.freemarker.core.model.ArgumentArrayLayout; +import org.apache.freemarker.core.model.TemplateFunctionModel; +import org.apache.freemarker.core.model.TemplateHashModelEx2; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.TemplateNumberModel; +import org.apache.freemarker.core.model.TemplateSequenceModel; +import org.apache.freemarker.core.model.impl.SimpleScalar; +import org.apache.freemarker.core.util.StringToIndexMap; + +public class AllFeaturesFunction extends TestTemplateCallableModel implements TemplateFunctionModel { + + public static final AllFeaturesFunction INSTANCE = new AllFeaturesFunction(); + + private static final int P1_ARG_IDX = 0; + private static final int P2_ARG_IDX = 1; + private static final int N1_ARG_IDX = 2; + private static final int N2_ARG_IDX = 3; + + private static final String N1_ARG_NAME = "n1"; + private static final String N2_ARG_NAME = "n2"; + + private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create( + 2, + true, + StringToIndexMap.of( + N1_ARG_NAME, N1_ARG_IDX, + N2_ARG_NAME, N2_ARG_IDX), + true + ); + + private static final int P_VARARGS_ARG_IDX = ARGS_LAYOUT.getPositionalVarargsArgumentIndex(); + private static final int N_VARARGS_ARG_IDX = ARGS_LAYOUT.getNamedVarargsArgumentIndex(); + + private final boolean p1AllowNull; + private final boolean p2AllowNull; + private final boolean n1AllowNull; + private final boolean n2AllowNull; + + public AllFeaturesFunction() { + this(true, true, true, true); + } + + public AllFeaturesFunction(boolean p1AllowNull, boolean p2AllowNull, boolean n1AllowNull, boolean n2AllowNull) { + this.p1AllowNull = p1AllowNull; + this.p2AllowNull = p2AllowNull; + this.n1AllowNull = n1AllowNull; + this.n2AllowNull = n2AllowNull; + } + + @Override + public TemplateModel execute(TemplateModel[] args, CallPlace callPlace, Environment env) throws TemplateException { + return execute(castArgumentToNumber(args, P1_ARG_IDX, p1AllowNull, env), + castArgumentToNumber(args, P2_ARG_IDX, p2AllowNull, env), + (TemplateSequenceModel) args[P_VARARGS_ARG_IDX], + castArgumentToNumber(args[N1_ARG_IDX], N1_ARG_NAME, n1AllowNull, env), + castArgumentToNumber(args[N2_ARG_IDX], N2_ARG_NAME, n2AllowNull, env), + (TemplateHashModelEx2) args[N_VARARGS_ARG_IDX], + env); + } + + private TemplateModel execute(TemplateNumberModel p1, TemplateNumberModel p2, TemplateSequenceModel pOthers, + TemplateNumberModel n1, TemplateNumberModel n2, TemplateHashModelEx2 nOthers, + Environment env) throws TemplateException { + StringWriter out = new StringWriter(); + try { + out.write("fa("); + printParam("p1", p1, out, true); + printParam("p2", p2, out); + printParam("pVarargs", pOthers, out); + printParam(N1_ARG_NAME, n1, out); + printParam(N2_ARG_NAME, n2, out); + printParam("nVarargs", nOthers, out); + out.write(")"); + } catch (IOException e) { + throw new IllegalStateException(e); + } + return new SimpleScalar(out.toString()); + } + + @Override + public ArgumentArrayLayout getArgumentArrayLayout() { + return ARGS_LAYOUT; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NamedVarargsOnlyDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NamedVarargsOnlyDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NamedVarargsOnlyDirective.java index fed4bc7..a087188 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NamedVarargsOnlyDirective.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NamedVarargsOnlyDirective.java @@ -25,10 +25,11 @@ import java.io.Writer; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; -public class NamedVarargsOnlyDirective extends TestTemplateDirectiveModel { +public class NamedVarargsOnlyDirective extends TestTemplateCallableModel implements TemplateDirectiveModel { public static final NamedVarargsOnlyDirective INSTANCE = new NamedVarargsOnlyDirective(); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyDirective.java index 540a641..2f9532e 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyDirective.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyDirective.java @@ -25,17 +25,14 @@ import java.io.Writer; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; -public class PositionalVarargsOnlyDirective extends TestTemplateDirectiveModel { +public class PositionalVarargsOnlyDirective extends TestTemplateCallableModel implements TemplateDirectiveModel { public static final PositionalVarargsOnlyDirective INSTANCE = new PositionalVarargsOnlyDirective(); - private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create( - 0, true, - null, false); - private PositionalVarargsOnlyDirective() { // } @@ -44,13 +41,13 @@ public class PositionalVarargsOnlyDirective extends TestTemplateDirectiveModel { public void execute(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env) throws TemplateException, IOException { out.write("#pvo("); - printParam("pVarargs", args[ARGS_LAYOUT.getPositionalVarargsArgumentIndex()], out, true); + printParam("pVarargs", args[0], out, true); out.write(")"); } @Override public ArgumentArrayLayout getArgumentArrayLayout() { - return ARGS_LAYOUT; + return ArgumentArrayLayout.POSITIONAL_VARARGS_PARAMETER_ONLY; } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyFunction.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyFunction.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyFunction.java new file mode 100644 index 0000000..eb8a3eb --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PositionalVarargsOnlyFunction.java @@ -0,0 +1,62 @@ +/* + * 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.userpkg; + +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.TemplateException; +import org.apache.freemarker.core.model.ArgumentArrayLayout; +import org.apache.freemarker.core.model.TemplateFunctionModel; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.impl.SimpleScalar; + +public class PositionalVarargsOnlyFunction extends TestTemplateCallableModel implements TemplateFunctionModel { + + public static final PositionalVarargsOnlyFunction INSTANCE = new PositionalVarargsOnlyFunction(); + + private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create( + 0, true, + null, false); + + private PositionalVarargsOnlyFunction() { + // + } + + @Override + public TemplateModel execute(TemplateModel[] args, CallPlace callPlace, Environment env) throws TemplateException { + try { + StringWriter out = new StringWriter(); + out.write("fpvo("); + printParam("pVarargs", args[ARGS_LAYOUT.getPositionalVarargsArgumentIndex()], out, true); + out.write(")"); + return new SimpleScalar(out.toString()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public ArgumentArrayLayout getArgumentArrayLayout() { + return ARGS_LAYOUT; + } +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java new file mode 100644 index 0000000..9dd34ba --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateCallableModel.java @@ -0,0 +1,88 @@ +/* + * 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.userpkg; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.freemarker.core.model.TemplateCallableModel; +import org.apache.freemarker.core.model.TemplateHashModelEx2; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.TemplateNumberModel; +import org.apache.freemarker.core.model.TemplateScalarModel; +import org.apache.freemarker.core.model.TemplateSequenceModel; +import org.apache.freemarker.core.util.FTLUtil; + +public abstract class TestTemplateCallableModel implements TemplateCallableModel { + + protected void printParam(String name, TemplateModel value, Writer out) throws IOException, TemplateModelException { + printParam(name, value, out, false); + } + + protected void printParam(String name, TemplateModel value, Writer out, boolean first) + throws IOException, TemplateModelException { + if (!first) { + out.write(", "); + } + out.write(name); + out.write("="); + printValue(value, out); + } + + private void printValue(TemplateModel value, Writer out) throws IOException, TemplateModelException { + if (value == null) { + out.write("null"); + } else if (value instanceof TemplateNumberModel) { + out.write(((TemplateNumberModel) value).getAsNumber().toString()); + } else if (value instanceof TemplateScalarModel) { + out.write(FTLUtil.toStringLiteral(((TemplateScalarModel) value).getAsString())); + } else if (value instanceof TemplateSequenceModel) { + int len = ((TemplateSequenceModel) value).size(); + out.write('['); + for (int i = 0; i < len; i++) { + if (i != 0) { + out.write(", "); + } + printValue(((TemplateSequenceModel) value).get(i), out); + } + out.write(']'); + } else if (value instanceof TemplateHashModelEx2) { + TemplateHashModelEx2.KeyValuePairIterator it = ((TemplateHashModelEx2) value).keyValuePairIterator(); + out.write('{'); + while (it.hasNext()) { + TemplateHashModelEx2.KeyValuePair kvp = it.next(); + + printValue(kvp.getKey(), out); + out.write(": "); + printValue(kvp.getValue(), out); + + if (it.hasNext()) { + out.write(", "); + } + } + out.write('}'); + } else { + throw new IllegalArgumentException("Unsupported value class: " + value.getClass().getName()); + } + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateDirectiveModel.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateDirectiveModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateDirectiveModel.java deleted file mode 100644 index 49bb049..0000000 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TestTemplateDirectiveModel.java +++ /dev/null @@ -1,88 +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.userpkg; - -import java.io.IOException; -import java.io.Writer; - -import org.apache.freemarker.core.model.TemplateDirectiveModel; -import org.apache.freemarker.core.model.TemplateHashModelEx2; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.TemplateNumberModel; -import org.apache.freemarker.core.model.TemplateScalarModel; -import org.apache.freemarker.core.model.TemplateSequenceModel; -import org.apache.freemarker.core.util.FTLUtil; - -public abstract class TestTemplateDirectiveModel implements TemplateDirectiveModel { - - protected void printParam(String name, TemplateModel value, Writer out) throws IOException, TemplateModelException { - printParam(name, value, out, false); - } - - protected void printParam(String name, TemplateModel value, Writer out, boolean first) - throws IOException, TemplateModelException { - if (!first) { - out.write(", "); - } - out.write(name); - out.write("="); - printValue(value, out); - } - - private void printValue(TemplateModel value, Writer out) throws IOException, TemplateModelException { - if (value == null) { - out.write("null"); - } else if (value instanceof TemplateNumberModel) { - out.write(((TemplateNumberModel) value).getAsNumber().toString()); - } else if (value instanceof TemplateScalarModel) { - out.write(FTLUtil.toStringLiteral(((TemplateScalarModel) value).getAsString())); - } else if (value instanceof TemplateSequenceModel) { - int len = ((TemplateSequenceModel) value).size(); - out.write('['); - for (int i = 0; i < len; i++) { - if (i != 0) { - out.write(", "); - } - printValue(((TemplateSequenceModel) value).get(i), out); - } - out.write(']'); - } else if (value instanceof TemplateHashModelEx2) { - TemplateHashModelEx2.KeyValuePairIterator it = ((TemplateHashModelEx2) value).keyValuePairIterator(); - out.write('{'); - while (it.hasNext()) { - TemplateHashModelEx2.KeyValuePair kvp = it.next(); - - printValue(kvp.getKey(), out); - out.write(": "); - printValue(kvp.getValue(), out); - - if (it.hasNext()) { - out.write(", "); - } - } - out.write('}'); - } else { - throw new IllegalArgumentException("Unsupported value class: " + value.getClass().getName()); - } - } - - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNamedParamsDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNamedParamsDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNamedParamsDirective.java index b4b85d3..83b5435 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNamedParamsDirective.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNamedParamsDirective.java @@ -25,11 +25,12 @@ import java.io.Writer; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.util.StringToIndexMap; -public class TwoNamedParamsDirective extends TestTemplateDirectiveModel { +public class TwoNamedParamsDirective extends TestTemplateCallableModel implements TemplateDirectiveModel { public static final TwoNamedParamsDirective INSTANCE = new TwoNamedParamsDirective(); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNestedContentParamsDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNestedContentParamsDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNestedContentParamsDirective.java index ff47315..6f768f4 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNestedContentParamsDirective.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoNestedContentParamsDirective.java @@ -25,12 +25,13 @@ import java.io.Writer; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; import org.apache.freemarker.core.model.Constants; +import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.impl.SimpleNumber; -public class TwoNestedContentParamsDirective extends TestTemplateDirectiveModel { +public class TwoNestedContentParamsDirective extends TestTemplateCallableModel implements TemplateDirectiveModel { public static final TwoNestedContentParamsDirective INSTANCE = new TwoNestedContentParamsDirective(); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsDirective.java index 4bd671e..008d8c8 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsDirective.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsDirective.java @@ -25,10 +25,11 @@ import java.io.Writer; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; -public class TwoPositionalParamsDirective extends TestTemplateDirectiveModel { +public class TwoPositionalParamsDirective extends TestTemplateCallableModel implements TemplateDirectiveModel { public static final TwoPositionalParamsDirective INSTANCE = new TwoPositionalParamsDirective(); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsFunction.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsFunction.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsFunction.java new file mode 100644 index 0000000..58e292b --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TwoPositionalParamsFunction.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.freemarker.core.userpkg; + +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.TemplateException; +import org.apache.freemarker.core.model.ArgumentArrayLayout; +import org.apache.freemarker.core.model.TemplateFunctionModel; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.impl.SimpleScalar; + +public class TwoPositionalParamsFunction extends TestTemplateCallableModel implements TemplateFunctionModel { + + public static TwoPositionalParamsFunction INSTANCE = new TwoPositionalParamsFunction(); + + private TwoPositionalParamsFunction() { + // + } + + private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create( + 2, false, + null, false); + + @Override + public TemplateModel execute(TemplateModel[] args, CallPlace callPlace, Environment env) throws TemplateException { + try { + StringWriter out = new StringWriter(); + out.write("fp("); + printParam("p1", args[0], out, true); + printParam("p2", args[1], out); + out.write(")"); + return new SimpleScalar(out.toString()); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + @Override + public ArgumentArrayLayout getArgumentArrayLayout() { + return ARGS_LAYOUT; + } +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/UpperCaseDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/UpperCaseDirective.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/UpperCaseDirective.java index 220aeef..05e5d6d 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/UpperCaseDirective.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/UpperCaseDirective.java @@ -26,7 +26,7 @@ import java.io.Writer; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/StringToIndexMapTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/StringToIndexMapTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/StringToIndexMapTest.java index 769325f..3be5783 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/StringToIndexMapTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/StringToIndexMapTest.java @@ -47,6 +47,8 @@ public class StringToIndexMapTest { assertEquals(-1, m.get("a")); assertEquals(0, m.get("i")); assertEquals(ImmutableList.of("i"), m.getKeys()); + assertEquals("i", m.getKeyOfValue(0)); + assertNull(m.getKeyOfValue(1)); } @Test @@ -57,6 +59,9 @@ public class StringToIndexMapTest { assertEquals(0, m.get("i")); assertEquals(1, m.get("j")); assertEquals(ImmutableList.of("i", "j"), m.getKeys()); + assertEquals("i", m.getKeyOfValue(0)); + assertEquals("j", m.getKeyOfValue(1)); + assertNull(m.getKeyOfValue(2)); } @Test http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java index 318e7ae..9bdea77 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/valueformat/NumberFormatTest.java @@ -35,7 +35,7 @@ import org.apache.freemarker.core.Template; import org.apache.freemarker.core.TemplateConfiguration; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.model.ArgumentArrayLayout; -import org.apache.freemarker.core.model.CallPlace; +import org.apache.freemarker.core.CallPlace; import org.apache.freemarker.core.model.TemplateDirectiveModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/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 index 18e46e9..81f83dc 100644 --- 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 @@ -112,30 +112,22 @@ - content: "more" // String #text // o.a.f.c.ASTStaticText - content: "\n6 " // String - #macro // o.a.f.c.ASTDirMacro + #macro // o.a.f.c.ASTDirMacroOrFunction - 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 + - parameter definition: "ParameterDefinition(name=\"x\")" // o.a.f.c.ASTDirMacroOrFunction$ParameterDefinition + - parameter definition: "ParameterDefinition(name=\"y\", default=2)" // o.a.f.c.ASTDirMacroOrFunction$ParameterDefinition + - parameter definition: "ParameterDefinition(name=\"z\", default=y + 1)" // o.a.f.c.ASTDirMacroOrFunction$ParameterDefinition + - parameter definition: "ParameterDefinition(name=\"q\")" // o.a.f.c.ASTDirMacroOrFunction$ParameterDefinition - 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 + #function // o.a.f.c.ASTDirMacroOrFunction - 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 + - parameter definition: "ParameterDefinition(name=\"x\")" // o.a.f.c.ASTDirMacroOrFunction$ParameterDefinition + - parameter definition: "ParameterDefinition(name=\"y\")" // o.a.f.c.ASTDirMacroOrFunction$ParameterDefinition - AST-node subtype: "1" // Integer #local // o.a.f.c.ASTDirAssignment - assignment target: "x" // String http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/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 index 479f868..847caab 100644 --- 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 @@ -92,9 +92,8 @@ - assignment source: 2 // o.a.f.c.ASTExpNumberLiteral - variable scope: "3" // Integer - namespace: null // Null - #macro // o.a.f.c.ASTDirMacro + #macro // o.a.f.c.ASTDirMacroOrFunction - assignment target: "m" // String - - catch-all parameter name: null // Null - AST-node subtype: "0" // Integer #text // o.a.f.c.ASTStaticText - content: " 7 " // String http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl new file mode 100644 index 0000000..56e816f --- /dev/null +++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl @@ -0,0 +1,43 @@ +<#ftl stripWhitespace=false> +<#-- + 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. +--> +<#macro m></#macro> +<#macro m a></#macro> +<#macro m a b></#macro> +<#macro m a b c...></#macro> +<#macro m a...></#macro> +<#macro m p1{positional}, p2{positional}, pva{positional}... n1 n2 nva...></#macro> +<#macro m p1{positional}, p2{positional}=2, pva{positional}... n1=3 n2 nva...></#macro> +<#macro m a{positional}></#macro> +<#macro m a{positional}=1></#macro> +<#macro m a{positional}...></#macro> +<#macro m nva{positional}... pva...></#macro> +<#function f()></#function> +<#function f(a)></#function> +<#function f(a, b)></#function> +<#function f(a, b, c...)></#function> +<#function f(a...)></#function> +<#function f(p1, p2, pva..., n1{named}, n2{named}, nva{named}...)></#function> +<#function f(p1, p2=2, pva..., n1{named}, n2{named}=3, nva{named}...)></#function> +<#function f(a{named})></#function> +<#function f(a{named}=1)></#function> +<#function f(a{named}...)></#function> +<#function f(nva..., pva{named}...)></#function> + +<#macro m p1 { positional } , p2 { positional } = 2 , pva { positional } ... n1 = 3 n2 nva ... ></#macro > http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl.out ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl.out b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl.out new file mode 100644 index 0000000..c15b35d --- /dev/null +++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macro-and-function.ftl.out @@ -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. + */ +<#macro m></#macro> +<#macro m a></#macro> +<#macro m a b></#macro> +<#macro m a b c...></#macro> +<#macro m a...></#macro> +<#macro m p1{positional}, p2{positional}, pva{positional}... n1 n2 nva...></#macro> +<#macro m p1{positional}, p2{positional}=2, pva{positional}... n1=3 n2 nva...></#macro> +<#macro m a{positional}></#macro> +<#macro m a{positional}=1></#macro> +<#macro m a{positional}...></#macro> +<#macro m nva{positional}... pva...></#macro> +<#function f()></#function> +<#function f(a)></#function> +<#function f(a, b)></#function> +<#function f(a, b, c...)></#function> +<#function f(a...)></#function> +<#function f(p1, p2, pva..., n1{named}, n2{named}, nva{named}...)></#function> +<#function f(p1, p2=2, pva..., n1{named}, n2{named}=3, nva{named}...)></#function> +<#function f(a{named})></#function> +<#function f(a{named}=1)></#function> +<#function f(a{named}...)></#function> +<#function f(nva..., pva{named}...)></#function> + +<#macro m p1{positional}, p2{positional}=2, pva{positional}... n1=3 n2 nva...></#macro> http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl deleted file mode 100644 index 9288e63..0000000 --- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl +++ /dev/null @@ -1,29 +0,0 @@ -<#ftl stripWhitespace=false> -<#-- - 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. ---> -<#macro m></#macro> -<#macro m a></#macro> -<#macro m a b></#macro> -<#macro m a b c...></#macro> -<#macro m a...></#macro> -<#function f()></#function> -<#function f(a)></#function> -<#function f(a, b)></#function> -<#function f(a, b, c...)></#function> -<#function f(a...)></#function> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl.out ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl.out b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl.out deleted file mode 100644 index ad49cae..0000000 --- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/cano-macros.ftl.out +++ /dev/null @@ -1,28 +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. - */ -<#macro m></#macro> -<#macro m a></#macro> -<#macro m a b></#macro> -<#macro m a b c...></#macro> -<#macro m a...></#macro> -<#function f()></#function> -<#function f(a)></#function> -<#function f(a, b)></#function> -<#function f(a, b, c...)></#function> -<#function f(a...)></#function> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/macros2.txt ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/macros2.txt b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/macros2.txt deleted file mode 100644 index 1b4e007..0000000 --- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/expected/macros2.txt +++ /dev/null @@ -1,22 +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. - */ -1 1 -2 2 -4 -m3 with d="4" Failed! http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/api-builtins.ftl ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/api-builtins.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/api-builtins.ftl index c7d1915..5377f38 100644 --- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/api-builtins.ftl +++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/api-builtins.ftl @@ -18,8 +18,8 @@ --> <@assertEquals expected="b" actual=map?api.get(2?int) /> <@assertEquals expected=2 actual=list?api.indexOf(3?int) /> -<@assert test=set?api.contains("b") /> -<@assert test=!set?api.contains("d") /> +<@assert set?api.contains("b") /> +<@assert !set?api.contains("d") /> <#assign dump = ""> <#list map?api.entrySet() as entry> @@ -30,11 +30,11 @@ </#list> <@assertEquals expected="1: a, 2: b, 3: c" actual=dump /> -<@assert test=map?hasApi /> -<@assert test=list?hasApi /> -<@assert test=set?hasApi /> -<@assert test=!s?hasApi /> -<@assert test=!1?hasApi /> -<@assert test=!""?hasApi /> -<@assert test=!{}?hasApi /> -<@assert test=!true?hasApi /> +<@assert map?hasApi /> +<@assert list?hasApi /> +<@assert set?hasApi /> +<@assert !s?hasApi /> +<@assert !1?hasApi /> +<@assert !""?hasApi /> +<@assert !{}?hasApi /> +<@assert !true?hasApi /> http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3cacd9ed/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/boolean.ftl ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/boolean.ftl b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/boolean.ftl index 49816ee..3d70cc5 100644 --- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/boolean.ftl +++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/templatesuite/templates/boolean.ftl @@ -71,10 +71,10 @@ <#else> boolean4 && boolean5 failed.<br /> </#if></p> -<@assert test=true && true /> -<@assert test=!(false && true) /> -<@assert test=true \and true /> -<@assert test=!(false \and true) /> +<@assert true && true /> +<@assert !(false && true) /> +<@assert true \and true /> +<@assert !(false \and true) /> <p>Now test list models:</p>
