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);
             }
         }
 

Reply via email to