Repository: incubator-freemarker Updated Branches: refs/heads/3 70e47bef7 -> 19071828a
FTLUtil.toStringLiteral choses literal format more intelligently. FTLUtil.escapeIdentifier now quotes unescapeable identifiers. Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/eca6684e Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/eca6684e Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/eca6684e Branch: refs/heads/3 Commit: eca6684e5d316c07d5cb8ca40fa35ea0e2b0ec8d Parents: 70e47be Author: ddekany <ddek...@apache.org> Authored: Tue Jul 4 00:47:09 2017 +0200 Committer: ddekany <ddek...@apache.org> Committed: Tue Jul 4 00:47:09 2017 +0200 ---------------------------------------------------------------------- .../freemarker/core/util/FTLUtilTest.java | 10 ++++++ .../freemarker/core/ast-strlitinterpolation.ast | 2 +- .../apache/freemarker/core/util/FTLUtil.java | 38 +++++++++++++++++--- 3 files changed, 45 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/eca6684e/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java index 14e5a07..aab0dbe 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java @@ -115,4 +115,14 @@ public class FTLUtilTest { assertFalse(FTLUtil.isNonEscapedIdentifierStart('\\')); } + @Test + public void testToStringLiteral() { + assertNull(FTLUtil.toStringLiteral(null)); + assertEquals("\"\"", FTLUtil.toStringLiteral("")); + assertEquals("'foo\"bar\"baaz\\''", FTLUtil.toStringLiteral("foo\"bar\"baaz'")); + assertEquals("\"foo'bar'baaz\\\"\"", FTLUtil.toStringLiteral("foo'bar'baaz\"")); + assertEquals("r\"\\d\"", FTLUtil.toStringLiteral("\\d")); + assertEquals("r'\\d\"'", FTLUtil.toStringLiteral("\\d\"")); + } + } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/eca6684e/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-strlitinterpolation.ast ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-strlitinterpolation.ast b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-strlitinterpolation.ast index 90317bd..97aca52 100644 --- a/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-strlitinterpolation.ast +++ b/freemarker-core-test/src/test/resources/org/apache/freemarker/core/ast-strlitinterpolation.ast @@ -26,7 +26,7 @@ - value part: ${...} // o.a.f.c.ASTDollarInterpolation - content: e1 // o.a.f.c.ASTExpVariable - argument name: "y" // String - - argument value: "$\\{e2}" // o.a.f.c.ASTExpStringLiteral + - argument value: r"$\{e2}" // o.a.f.c.ASTExpStringLiteral #text // o.a.f.c.ASTStaticText - content: "\n2. " // String ${...} // o.a.f.c.ASTDollarInterpolation http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/eca6684e/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java ---------------------------------------------------------------------- diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java b/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java index 8baa927..29ff468 100644 --- a/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java +++ b/freemarker-core/src/main/java/org/apache/freemarker/core/util/FTLUtil.java @@ -288,15 +288,41 @@ public final class FTLUtil { /** * Creates a <em>quoted</em> FTL string literal from a string, using escaping where necessary. The result either - * uses regular quotation marks (UCS 0x22) or apostrophe-quotes (UCS 0x27), depending on the string content. - * (Currently, apostrophe-quotes will be chosen exactly when the string contains regular quotation character and - * doesn't contain apostrophe-quote character.) + * uses regular quotation marks (UCS 0x22) or apostrophe-quotes (UCS 0x27), or it will be a raw string literal + * (like {@code r"can contain backslash anywhere"}). + * This is decided based on the number of regular quotation marks, apostrophe-quotes, and backslashes. * * @param s The value that should be converted to an FTL string literal whose evaluated value equals to {@code s} */ public static String toStringLiteral(String s) { + if (s == null) { + return null; + } + + int aposCnt = 0; + int quotCnt = 0; + int backslashCnt = 0; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '\'') { + aposCnt++; + } else if (c == '"') { + quotCnt++; + } else if (c == '\\') { + backslashCnt++; + } + } + + if (backslashCnt != 0) { + if (quotCnt == 0) { + return "r\"" + s + "\""; + } else if (aposCnt == 0) { + return "r\'" + s + "\'"; + } + } + char quotation; - if (s.indexOf('"') != -1 && s.indexOf('\'') == -1) { + if (aposCnt < quotCnt ) { quotation = '\''; } else { quotation = '\"'; @@ -615,6 +641,10 @@ public final class FTLUtil { } lastEscIdx = i; plusOutLn++; + } else if (i == 0 && !isNonEscapedIdentifierStart(c) + || i > 0 && !isNonEscapedIdentifierPart(c)) { + // TODO [FM3] But quoting is only allowed for target variables... that's a strange syntax anyway. + return toStringLiteral(s); } }