You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2015/09/18 22:21:55 UTC
incubator-freemarker git commit: @@ can't be used to escape @ at the
beginning of format strings anymore, because it was confusing on Android,
where DecimalFormat supports patterns like "@@@@@@". If a pattern has to
output a literal @ as the first charac
Repository: incubator-freemarker
Updated Branches:
refs/heads/2.3-gae d5bfedbad -> 8e7c80a43
@@ can't be used to escape @ at the beginning of format strings anymore, because it was confusing on Android, where DecimalFormat supports patterns like "@@@@@@". If a pattern has to output a literal @ as the first character, you can simply use quoting as defined by DecimalFormat and SimpleDateFormat (for example, "'@'0.##").
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/8e7c80a4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/8e7c80a4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/8e7c80a4
Branch: refs/heads/2.3-gae
Commit: 8e7c80a439273ea81a660611b4fa4a807b6c4e6f
Parents: d5bfedb
Author: ddekany <dd...@apache.org>
Authored: Fri Sep 18 22:20:21 2015 +0200
Committer: ddekany <dd...@apache.org>
Committed: Fri Sep 18 22:21:31 2015 +0200
----------------------------------------------------------------------
src/main/java/freemarker/core/Configurable.java | 14 +++++++---
src/main/java/freemarker/core/Environment.java | 28 ++++---------------
src/manual/book.xml | 29 ++++++++++++++------
.../java/freemarker/core/DateFormatTest.java | 18 ++++++++----
.../java/freemarker/core/NumberFormatTest.java | 18 ++++++++----
5 files changed, 60 insertions(+), 47 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8e7c80a4/src/main/java/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index bdc76ae..4ad0a2e 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -778,7 +778,8 @@ public class Configurable {
* meaning).
*
* @param customNumberFormats
- * Can't be {@code null}.
+ * Can't be {@code null}. The name must start with an UNICODE letter, and can only contain UNICODE
+ * letters and digits.
*
* @since 2.3.24
*/
@@ -793,12 +794,16 @@ public class Configurable {
if (name.length() == 0) {
throw new IllegalArgumentException("Format names can't be 0 length");
}
- if (name.charAt(0) == '@') {
+ char firstChar = name.charAt(0);
+ if (firstChar == '@') {
throw new IllegalArgumentException(
"Format names can't start with '@'. '@' is only used when referring to them from format "
+ "strings. In: " + name);
}
- for (int i = 0; i < name.length(); i++) {
+ if (!Character.isLetter(firstChar)) {
+ throw new IllegalArgumentException("Format name must start with letter: " + name);
+ }
+ for (int i = 1; i < name.length(); i++) {
// Note that we deliberately don't allow "_" here.
if (!Character.isLetterOrDigit(name.charAt(i))) {
throw new IllegalArgumentException("Format name can only contain letters and digits: " + name);
@@ -1149,7 +1154,8 @@ public class Configurable {
* meaning).
*
* @param customDateFormats
- * Can't be {@code null}.
+ * Can't be {@code null}. The name must start with an UNICODE letter, and can only contain UNICODE
+ * letters and digits.
*
* @since 2.3.24
*/
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8e7c80a4/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 96e31fd..1e6aa73 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -1235,8 +1235,8 @@ public final class Environment extends Configurable {
int formatStringLen = formatString.length();
if (formatStringLen > 1
&& formatString.charAt(0) == '@'
- && formatString.charAt(1) != '@'
- && (isIcI2324OrLater() || hasCustomFormats())) {
+ && (isIcI2324OrLater() || hasCustomFormats())
+ && Character.isLetter(formatString.charAt(1))) {
final String name;
final String params;
{
@@ -1259,13 +1259,6 @@ public final class Environment extends Configurable {
return formatFactory.get(params, locale, this);
} else {
- if (formatStringLen > 1
- && formatString.charAt(0) == '@'
- && formatString.charAt(1) == '@'
- && (isIcI2324OrLater() || hasCustomFormats())) {
- // Unescape @ escaped as @@
- formatString = formatString.substring(1);
- }
return JavaTemplateNumberFormatFactory.INSTANCE.get(formatString, locale, this);
}
}
@@ -1742,8 +1735,8 @@ public final class Environment extends Configurable {
formatParams = formatString; // for speed, we don't remove the prefix
} else if (firstChar == '@'
&& formatStringLen > 1
- && formatString.charAt(1) != '@'
- && (isIcI2324OrLater() || hasCustomFormats())) {
+ && (isIcI2324OrLater() || hasCustomFormats())
+ && Character.isLetter(formatString.charAt(1))) {
final String name;
{
int endIdx;
@@ -1763,19 +1756,8 @@ public final class Environment extends Configurable {
"No custom date format was defined with name " + StringUtil.jQuote(name));
}
} else {
- String unescapedFormatString;
- if (firstChar == '@'
- && formatStringLen > 1
- && formatString.charAt(1) == '@'
- && (isIcI2324OrLater() || hasCustomFormats())) {
- // Unescape @ escaped as @@
- unescapedFormatString = formatString.substring(1);
- } else {
- unescapedFormatString = formatString;
- }
-
+ formatParams = formatString;
formatFactory = JavaTemplateDateFormatFactory.INSTANCE;
- formatParams = unescapedFormatString;
}
return formatFactory.get(formatParams, dateType, locale, timeZone,
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8e7c80a4/src/manual/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/book.xml b/src/manual/book.xml
index af492e4..0506f18 100644
--- a/src/manual/book.xml
+++ b/src/manual/book.xml
@@ -25756,10 +25756,10 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
or <literal>${n?string.@foo}</literal>,
<literal>${n?string.@foo_params}</literal>. For backward
compatibility, the initial <literal>@</literal> only has this
- special meaning if you have any custom formats or <link
+ special meaning if either you have any custom formats or <link
linkend="pgui_config_incompatible_improvements">the
<literal>incompatible_improvements</literal> setting</link> is
- 2.3.24 or higher.</para>
+ at lest 2.3.24.</para>
</listitem>
<listitem>
@@ -25915,12 +25915,12 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
Like, you can do <literal>cfg.setNumberFormat("@foo
params")</literal>, or <literal><#setting
number_format='@foo params'></literal>, or
- <literal>${n?string.@foo_params}</literal>. Note that an
- <replaceable>initial</replaceable> <literal>@</literal> in
- format strings is reserved for this purpose with
- <literal>incompatible_improvements</literal> to 2.3.24, and
- need to be escaped as <literal>@@</literal> if it has to be
- there literally. Note that the
+ <literal>${n?string.@foo_params}</literal>. For backward
+ compatibility, the initial <literal>@</literal> only has
+ this special meaning if either you have any custom formats
+ or <link linkend="pgui_config_incompatible_improvements">the
+ <literal>incompatible_improvements</literal> setting</link>
+ is at least 2.3.24. Note that the
<literal>custom_number_formats</literal> and
<literal>custom_date_formats</literal> settings can be set
per-template (via the new
@@ -26160,6 +26160,19 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
</listitem>
<listitem>
+ <para><literal>@@</literal> can't be used to escape
+ <literal>@</literal> at the beginning of format strings anymore,
+ because it was confusing on Android, where
+ <literal>DecimalFormat</literal> supports patterns like
+ <literal>"@@@@@@"</literal>. If a pattern has to output a
+ literal <literal>@</literal> as the first character, you can
+ simply use quoting as defined by
+ <literal>DecimalFormat</literal> and
+ <literal>SimpleDateFormat</literal> (for example,
+ <literal>"'@'0.##"</literal>).</para>
+ </listitem>
+
+ <listitem>
<para><literal>?date</literal>, <literal>?time</literal> and
<literal>?datetime</literal> now can be called as 0 argument
method, like <literal>?date()</literal>, etc., which returns the
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8e7c80a4/src/test/java/freemarker/core/DateFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/DateFormatTest.java b/src/test/java/freemarker/core/DateFormatTest.java
index 741e68b..c21b83a 100644
--- a/src/test/java/freemarker/core/DateFormatTest.java
+++ b/src/test/java/freemarker/core/DateFormatTest.java
@@ -205,23 +205,29 @@ public class DateFormatTest extends TemplateTest {
cfg.setCustomDateFormats(Collections.<String, TemplateDateFormatFactory>emptyMap());
- cfg.setDateTimeFormat("@@yyyy");
- assertOutput("${d}", "@@1970");
cfg.setDateTimeFormat("@epoch");
assertErrorContains("${d}", "\"@epoch\"");
+ cfg.setDateTimeFormat("'@'yyyy");
+ assertOutput("${d}", "@1970");
+ cfg.setDateTimeFormat("@@yyyy");
+ assertOutput("${d}", "@@1970");
cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_24);
- cfg.setDateTimeFormat("@@yyyy");
- assertOutput("${d}", "@1970");
cfg.setDateTimeFormat("@epoch");
assertErrorContains("${d}", "custom", "\"epoch\"");
+ cfg.setDateTimeFormat("'@'yyyy");
+ assertOutput("${d}", "@1970");
+ cfg.setDateTimeFormat("@@yyyy");
+ assertOutput("${d}", "@@1970");
}
protected void testIcIAndEscapingWhenCustFormsAreAccepted(Configuration cfg) throws IOException, TemplateException {
- cfg.setDateTimeFormat("@@yyyy");
- assertOutput("${d}", "@1970");
cfg.setDateTimeFormat("@epoch");
assertOutput("${d}", "12345678");
+ cfg.setDateTimeFormat("'@'yyyy");
+ assertOutput("${d}", "@1970");
+ cfg.setDateTimeFormat("@@yyyy");
+ assertOutput("${d}", "@@1970");
}
@Test
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8e7c80a4/src/test/java/freemarker/core/NumberFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/NumberFormatTest.java b/src/test/java/freemarker/core/NumberFormatTest.java
index 78b420f..b30b72a 100644
--- a/src/test/java/freemarker/core/NumberFormatTest.java
+++ b/src/test/java/freemarker/core/NumberFormatTest.java
@@ -215,23 +215,29 @@ public class NumberFormatTest extends TemplateTest {
testIcIAndEscapingWhenCustFormsAccepted(cfg);
cfg.setCustomNumberFormats(Collections.<String, TemplateNumberFormatFactory>emptyMap());
- cfg.setNumberFormat("@@0");
- assertOutput("${10}", "@@10");
cfg.setNumberFormat("@hex");
assertOutput("${10}", "@hex10");
+ cfg.setNumberFormat("'@'0");
+ assertOutput("${10}", "@10");
+ cfg.setNumberFormat("@@0");
+ assertOutput("${10}", "@@10");
cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_24);
- cfg.setNumberFormat("@@0");
- assertOutput("${10}", "@10");
cfg.setNumberFormat("@hex");
assertErrorContains("${10}", "custom", "\"hex\"");
+ cfg.setNumberFormat("'@'0");
+ assertOutput("${10}", "@10");
+ cfg.setNumberFormat("@@0");
+ assertOutput("${10}", "@@10");
}
protected void testIcIAndEscapingWhenCustFormsAccepted(Configuration cfg) throws IOException, TemplateException {
- cfg.setNumberFormat("@@0");
- assertOutput("${10}", "@10");
cfg.setNumberFormat("@hex");
assertOutput("${10}", "a");
+ cfg.setNumberFormat("'@'0");
+ assertOutput("${10}", "@10");
+ cfg.setNumberFormat("@@0");
+ assertOutput("${10}", "@@10");
}
@Test