Repository: incubator-freemarker Updated Branches: refs/heads/3 ce72f4ba2 -> f3b89b5c6
Continued work on the FM2 to FM3 converter Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/f3b89b5c Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/f3b89b5c Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/f3b89b5c Branch: refs/heads/3 Commit: f3b89b5c680b5739d19a0ef699a35d5c3ce8aed1 Parents: ce72f4b Author: ddekany <[email protected]> Authored: Tue Jun 27 00:48:27 2017 +0200 Committer: ddekany <[email protected]> Committed: Tue Jun 27 00:48:27 2017 +0200 ---------------------------------------------------------------------- .../core/FM2ASTToFM3SourceConverter.java | 86 ++++++++++++++++++-- .../freemarker/converter/FM2ToFM3Converter.java | 2 - .../converter/FM2ToFM3ConverterTest.java | 25 +++++- 3 files changed, 103 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f3b89b5c/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java b/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java index 20fa2b8..7f8a2da 100644 --- a/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java +++ b/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java @@ -131,9 +131,9 @@ public class FM2ASTToFM3SourceConverter { } else if (node instanceof TextBlock) { print(getOnlyParam(node, ParameterRole.CONTENT, String.class)); } else if (node instanceof DollarVariable) { - printWithParamsLeadingSkippedTokens("${", node); - printNode(getOnlyParam(node, ParameterRole.CONTENT, Expression.class)); - printWithParamsTrailingSkippedTokens("}", node, 0); + printDollarInterpolation((DollarVariable) node); + } else if (node instanceof NumericalOutput) { + printNumericalInterpolation((NumericalOutput) node); } else if (node instanceof Comment) { print(tagBeginChar); print("#--"); @@ -145,6 +145,62 @@ public class FM2ASTToFM3SourceConverter { } } + private void printNumericalInterpolation(NumericalOutput node) throws ConverterException { + printWithParamsLeadingSkippedTokens("${", node); + Expression content = getParam(node, 0, ParameterRole.CONTENT, Expression.class); + + int pos = getPositionAfterWSAndExpComments(getEndPositionExclusive(content)); + assertNodeContent(pos < src.length(), node, "Unexpected EOF", null); + char c = src.charAt(pos); + assertNodeContent(c == ';' || c == '}', node, "Expected ';' or '}', found '{}'", c); + if (c == ';') { // #{exp; m1M2} -> ${exp?string('0.0#')} + int minDecimals = getParam(node, 1, ParameterRole.MINIMUM_DECIMALS, Integer.class); + int maxDecimals = getParam(node, 2, ParameterRole.MAXIMUM_DECIMALS, Integer.class); + + boolean needsParen = !needsNoParenthesisAsBuiltInLHO(content); + if (needsParen) { + print('('); + } + printNode(content); + if (needsParen) { + print(')'); + } + print("?string('0."); + for (int i = 0; i < minDecimals; i++) { + print('0'); + } + for (int i = minDecimals; i < maxDecimals; i++) { + print('#'); + } + print("')}"); + } else { // #{exp} -> ${exp} + printNode(content); + printWithParamsTrailingSkippedTokens("}", node, 0); + } + } + + private boolean needsNoParenthesisAsBuiltInLHO(Expression exp) { + return + exp instanceof Identifier + || exp instanceof NumberLiteral + || exp instanceof BooleanLiteral + || exp instanceof StringLiteral + || exp instanceof ListLiteral + || exp instanceof HashLiteral + || exp instanceof ParentheticalExpression + || exp instanceof MethodCall + || exp instanceof DynamicKeyName + || exp instanceof BuiltIn + || exp instanceof BuiltinVariable + || exp instanceof Dot; + } + + private void printDollarInterpolation(DollarVariable node) throws ConverterException { + printWithParamsLeadingSkippedTokens("${", node); + printNode(getOnlyParam(node, ParameterRole.CONTENT, Expression.class)); + printWithParamsTrailingSkippedTokens("}", node, 0); + } + /** * Prints a directive */ @@ -322,6 +378,8 @@ public class FM2ASTToFM3SourceConverter { printExpDynamicKeyName((DynamicKeyName) node); } else if (node instanceof BuiltIn) { printExpBuiltIn((BuiltIn) node); + } else if (node instanceof BuiltinVariable) { + printExpBuiltinVariable((BuiltinVariable) node); } else if (node instanceof Dot) { printExpDot((Dot) node); } else { @@ -329,6 +387,22 @@ public class FM2ASTToFM3SourceConverter { } } + private void printExpBuiltinVariable(BuiltinVariable node) throws ConverterException { + int startPos = getStartPosition(node); + String sep = readExpWSAndSeparator(startPos, '.', false); + printWithConvertedExpComments(sep); + String name = src.substring(startPos + sep.length(), getEndPositionExclusive(node)); + print(convertBuiltInVariableName(name)); + } + + private String convertBuiltInVariableName(String name) throws ConverterException { + String converted = name.indexOf('_') == -1 ? name : ConverterUtils.snakeCaseToCamelCase(name); + + // Will replace removed names here + + return converted; + } + private void printExpDot(Dot node) throws ConverterException { assertParamCount(node, 2); Expression lho = getParam(node, 0, ParameterRole.LEFT_HAND_OPERAND, Expression.class); @@ -342,11 +416,11 @@ public class FM2ASTToFM3SourceConverter { private void printExpDynamicKeyName(DynamicKeyName node) throws ConverterException { assertParamCount(node, 2); - Expression hashExp = getParam(node, 0, ParameterRole.LEFT_HAND_OPERAND, Expression.class); - printExp(hashExp); + Expression collExp = getParam(node, 0, ParameterRole.LEFT_HAND_OPERAND, Expression.class); + printExp(collExp); Expression keyExp = getParam(node, 1, ParameterRole.ENCLOSED_OPERAND, Expression.class); - printParameterSeparatorSource(hashExp, keyExp); + printParameterSeparatorSource(collExp, keyExp); printExp(keyExp); printWithParamsTrailingSkippedTokens("]", node, 1); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f3b89b5c/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3Converter.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3Converter.java b/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3Converter.java index 4668440..e4c3fa5 100644 --- a/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3Converter.java +++ b/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3Converter.java @@ -103,8 +103,6 @@ public class FM2ToFM3Converter extends Converter { fileTransCtx.setDestinationFileName(getDestinationFileName(template)); fileTransCtx.getDestinationStream().write( FM2ASTToFM3SourceConverter.convert(template, src).getBytes(getTemplateEncoding(template))); - - } private String getTemplateEncoding(Template template) { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f3b89b5c/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java index a00e54d..936c516 100644 --- a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java +++ b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java @@ -98,15 +98,36 @@ public class FM2ToFM3ConverterTest extends ConverterTest { assertConvertedSame("${m[key]}"); assertConvertedSame("${m['key']}"); assertConvertedSame("${m <#-- C1 --> [ <#-- C2 --> key <#-- C3 --> ]}"); + assertConvertedSame("${seq\\-foo[1]}"); assertConvertedSame("${m.key}"); assertConvertedSame("${m <#-- C1 --> . <#-- C3 --> key}"); + + assertConvertedSame("${.outputFormat}"); + assertConvertedSame("${. <#-- C --> outputFormat}"); + assertConverted("${.outputFormat}","${.output_format}"); } @Test public void testInterpolations() throws IOException, ConverterException { - assertConvertedSame("${var}"); - assertConvertedSame("${ var\n}"); + assertConvertedSame("${n}"); + assertConvertedSame("${ n\n}"); + + assertConverted("${n}", "#{n}"); + assertConverted("${n?string('0.00')}", "#{n; m2}"); + assertConverted("${n?string('0.###')}", "#{n; M3}"); + assertConverted("${n?string('0.00###')}", "#{n; m2M5}"); + assertConverted("${n + 1}", "#{n + 1}"); + assertConverted("${(n + 1)?string('0.00')}", "#{n + 1; m2}"); + assertConverted("${(n * m)?string('0.00')}", "#{n * m; m2}"); + assertConverted("${(-n)?string('0.00')}", "#{-n; m2}"); + assertConverted("${a.b?string('0.00')}", "#{a.b; m2}"); + assertConverted("${f()?string('0.00')}", "#{f(); m2}"); + assertConverted("${m[k]?string('0.00')}", "#{m[k]; m2}"); + assertConverted("${n?abs?string('0.00')}", "#{n?abs; m2}"); + + assertConverted("${ n }", "#{ n }"); + assertConverted("${ n?string('0.00')}", "#{ n ; m2}"); } @Test
