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 2017/07/03 00:07:44 UTC
incubator-freemarker git commit: Continued work on the FM2 to FM3
converter
Repository: incubator-freemarker
Updated Branches:
refs/heads/3 1f086e3f2 -> 70e47bef7
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/70e47bef
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/70e47bef
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/70e47bef
Branch: refs/heads/3
Commit: 70e47bef7b4ae7128ee725acf98e1df87fa3d019
Parents: 1f086e3
Author: ddekany <dd...@apache.org>
Authored: Mon Jul 3 02:07:25 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Mon Jul 3 02:07:25 2017 +0200
----------------------------------------------------------------------
.../core/FM2ASTToFM3SourceConverter.java | 151 ++++++++++++++++---
.../freemarker/converter/FM2ToFM3Converter.java | 13 +-
.../converter/FM2ToFM3ConverterTest.java | 7 +
3 files changed, 143 insertions(+), 28 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/70e47bef/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 b1f221c..8322f95 100644
--- a/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java
+++ b/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java
@@ -28,10 +28,7 @@ import java.util.Set;
import org.apache.freemarker.converter.ConverterException;
import org.apache.freemarker.converter.ConverterUtils;
import org.apache.freemarker.core.NamingConvention;
-import org.apache.freemarker.core.util.FTLUtil;
-import org.apache.freemarker.core.util._ClassUtil;
-import org.apache.freemarker.core.util._NullArgumentException;
-import org.apache.freemarker.core.util._StringUtil;
+import org.apache.freemarker.core.util.*;
import freemarker.template.Configuration;
import freemarker.template.Template;
@@ -67,6 +64,7 @@ import freemarker.template.utility.StringUtil;
@SuppressWarnings("deprecation")
public class FM2ASTToFM3SourceConverter {
+ private final Template template;
private final String src;
private final StringBuilder out;
private List<Integer> rowStartPositions;
@@ -78,17 +76,34 @@ public class FM2ASTToFM3SourceConverter {
.build();
private final Set<String> fm3BuiltInNames = fm3Config.getSupportedBuiltInNames();
+ private boolean printNextCustomDirAsFtlDir;
+
/**
- * @param template Must have been parsed with {@link Configuration#getWhitespaceStripping()} {@code false}.
+ * @param fm2Cfg The {@link Configuration} used for parsing; {@link Configuration#getWhitespaceStripping()} must
+ * return {@code false}.
*/
- public static String convert(Template template, String src) throws ConverterException {
- FM2ASTToFM3SourceConverter instance = new FM2ASTToFM3SourceConverter(template, src);
- instance.printNode(template.getRootTreeNode());
- return instance.getOutput();
+ public static Result convert(String templateName, String src, Configuration fm2Cfg) throws ConverterException {
+ return new FM2ASTToFM3SourceConverter(templateName, src, fm2Cfg).convert();
}
- private FM2ASTToFM3SourceConverter(Template template, String src) {
- _NullArgumentException.check("template", template);
+ private Result convert() throws ConverterException {
+ printDirFtl();
+ printNode(template.getRootTreeNode());
+
+ String outAsString = out.toString();
+ try {
+ //!!T new org.apache.freemarker.core.Template(null, s, fm3Config);
+ } catch (Exception e) {
+ throw new ConverterException(
+ "The result of the conversion wasn't valid FreeMarker 3 template; see cause exception", e);
+ }
+
+ return new Result(template, outAsString);
+ }
+
+ private FM2ASTToFM3SourceConverter(String templateName, String src, Configuration fm2Cfg)
+ throws ConverterException {
+ template = createTemplate(templateName, src, fm2Cfg);
if (template.getParserConfiguration().getWhitespaceStripping()) {
throw new IllegalArgumentException("The Template must have been parsed with whitespaceStripping false.");
}
@@ -106,15 +121,80 @@ public class FM2ASTToFM3SourceConverter {
}
}
- private String getOutput() throws ConverterException {
- String s = out.toString();
+ /**
+ * Converts a {@link String} to a {@link Template}.
+ */
+ private static Template createTemplate(String templateName, String src, Configuration fm2Cfg) throws
+ ConverterException {
+ if (fm2Cfg.getWhitespaceStripping()) {
+ throw new IllegalArgumentException("Configuration.whitespaceStripping must be false");
+ }
try {
- //!!T new org.apache.freemarker.core.Template(null, s, fm3Config);
+ return new Template(templateName, src, fm2Cfg);
} catch (Exception e) {
- throw new ConverterException(
- "The result of the conversion wasn't valid FreeMarker 3 template; see cause exception", e);
+ throw new ConverterException("Failed to load FreeMarker 2.3.x template", e);
}
- return s;
+ }
+
+ // The FTL tag is not part of the AST tree, so we have to treat it differently
+ private void printDirFtl() throws ConverterException {
+ int pos = getPositionAfterWSAndExpComments(0);
+ if (src.length() > pos + 1 && src.charAt(pos) == tagBeginChar && src.startsWith("#ftl", pos + 1)) {
+ printWithConvertedExpComments(src.substring(0, pos));
+
+ pos += 5; // "<#ftl".length()
+
+ int tagEnd;
+ String postFtlTagSkippedWS;
+ {
+ int firstNodePos;
+
+ TemplateElement rootNode = template.getRootTreeNode();
+ if (rootNode.getBeginLine() != 0) {
+ firstNodePos = getStartPosition(rootNode);
+ assertNodeContent(firstNodePos > pos, rootNode,
+ "Root node position should be after #ftl header");
+ } else {
+ // Extreme case where the template only contains the #ftl header.
+ assertNodeContent(rootNode.getEndLine() == 0, rootNode,
+ "Expected 0 end line for root node");
+ firstNodePos = src.length();
+ }
+
+ tagEnd = firstNodePos - 1;
+ while (tagEnd >= 0 && src.charAt(tagEnd) != tagEndChar) {
+ if (!Character.isWhitespace(src.charAt(tagEnd))) {
+ throw new ConverterException("Non-WS character while backtracking to #ftl tag end character.");
+ }
+ tagEnd--;
+ }
+ if (tagEnd < 0) {
+ throw new ConverterException("Couldn't backtrack to #ftl tag end character.");
+ }
+
+ postFtlTagSkippedWS = src.substring(tagEnd + 1, firstNodePos);
+ }
+
+ boolean hasSlash = src.charAt(tagEnd - 1) == '/';
+
+ // We need the Expression-s parsed, but they aren't part of the AST. So, we parse a template that contains
+ // a similar custom "ftl" directive, and the converter to print it as an #ftl directive.
+ FM2ASTToFM3SourceConverter customFtlDirSrcConverter = new FM2ASTToFM3SourceConverter(
+ template.getName(),
+ tagBeginChar + "@ftl" + src.substring(pos, tagEnd) + (hasSlash ? "" : "/") + tagEndChar,
+ template.getConfiguration());
+ customFtlDirSrcConverter.printNextCustomDirAsFtlDir = true;
+ String fm3Content = customFtlDirSrcConverter.convert().fm3Content;
+ print(hasSlash
+ ? fm3Content
+ : fm3Content.substring(0, fm3Content.length() - 2) + tagEndChar);
+
+ print(postFtlTagSkippedWS);
+ }
+ }
+
+ private String convertFtlHeaderParamName(String name) throws ConverterException {
+ return name.indexOf('_') == -1 ? name : ConverterUtils.snakeCaseToCamelCase(name);
}
private void printNode(TemplateObject node) throws ConverterException {
@@ -222,6 +302,8 @@ public class FM2ASTToFM3SourceConverter {
printDirAssignmentMultiple((AssignmentInstruction) node);
} else if (node instanceof AttemptBlock) {
printDirAttemptRecover((AttemptBlock) node);
+ } else if (node instanceof AttemptBlock) {
+ printDirAttemptRecover((AttemptBlock) node);
} else {
throw new ConverterException("Unhandled AST TemplateElement class: " + node.getClass().getName());
}
@@ -443,8 +525,11 @@ public class FM2ASTToFM3SourceConverter {
}
private void printDirCustom(UnifiedCall node) throws ConverterException {
+ boolean ftlDirMode = printNextCustomDirAsFtlDir;
+ printNextCustomDirAsFtlDir = false;
+
print(tagBeginChar);
- print('@');
+ print(ftlDirMode ? '#' : '@');
Expression callee = getParam(node, 0, ParameterRole.CALLEE, Expression.class);
printExp(callee);
@@ -467,9 +552,19 @@ public class FM2ASTToFM3SourceConverter {
// Print named arguments:
while (paramIdx < paramCount
&& node.getParameterRole(paramIdx) == ParameterRole.ARGUMENT_NAME) {
+ String paramName = getParam(node, paramIdx, ParameterRole.ARGUMENT_NAME, String.class);
Expression argValue = getParam(node, paramIdx + 1, ParameterRole.ARGUMENT_VALUE, Expression.class);
- printParameterSeparatorSource(lastPrintedExp, argValue); // Prints something like " someArgName="
+ int pos = getEndPositionExclusive(lastPrintedExp);
+ pos = printWSAndExpComments(pos, ",", true);
+ int paramNameStartPos = pos;
+ pos = getPositionAfterIdentifier(pos);
+ assertNodeContent(pos > paramNameStartPos, node, "Parameter name in src was empty");
+ if (ftlDirMode) {
+ paramName = convertFtlHeaderParamName(paramName);
+ }
+ print(FTLUtil.escapeIdentifier(paramName));
+ printWSAndExpComments(pos, "=", false);
printExp(argValue);
lastPrintedExp = argValue;
@@ -1385,4 +1480,22 @@ public class FM2ASTToFM3SourceConverter {
}
+ public static class Result {
+ private final Template fm2Template;
+ private final String fm3Content;
+
+ public Result(Template fm2Template, String fm3Content) {
+ this.fm2Template = fm2Template;
+ this.fm3Content = fm3Content;
+ }
+
+ public Template getFM2Template() {
+ return fm2Template;
+ }
+
+ public String getFM3Content() {
+ return fm3Content;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/70e47bef/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 e4c3fa5..a70c08e 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
@@ -93,16 +93,11 @@ public class FM2ToFM3Converter extends Converter {
@Override
protected void convertFile(FileConversionContext fileTransCtx) throws ConverterException, IOException {
String src = IOUtils.toString(fileTransCtx.getSourceStream(), StandardCharsets.UTF_8);
- Template template;
- try {
- template = new Template(fileTransCtx.getSourceFile().getName(), src, fm2Cfg);
- } catch (Exception e) {
- throw new ConverterException("Failed to load FreeMarker 2.3.x template", e);
- }
-
- fileTransCtx.setDestinationFileName(getDestinationFileName(template));
+ FM2ASTToFM3SourceConverter.Result result = FM2ASTToFM3SourceConverter.convert(fileTransCtx.getSourceFile()
+ .getName(), src, fm2Cfg);
+ fileTransCtx.setDestinationFileName(getDestinationFileName(result.getFM2Template()));
fileTransCtx.getDestinationStream().write(
- FM2ASTToFM3SourceConverter.convert(template, src).getBytes(getTemplateEncoding(template)));
+ result.getFM3Content().getBytes(getTemplateEncoding(result.getFM2Template())));
}
private String getTemplateEncoding(Template template) {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/70e47bef/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 0f74125..675a3c6 100644
--- a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java
+++ b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java
@@ -203,6 +203,13 @@ public class FM2ToFM3ConverterTest extends ConverterTest {
assertConvertedSame("<#attempt >a<#recover >r</#attempt >");
assertConverted("<#attempt>a<#recover>r</#attempt>", "<#attempt>a<#recover>r</#recover>");
assertConverted("<#attempt >a<#recover >r</#attempt >", "<#attempt >a<#recover >r</#recover >");
+
+ assertConvertedSame("<#ftl>");
+ assertConvertedSame("<#ftl>x");
+ assertConvertedSame("<#ftl>x${x}");
+ assertConvertedSame("<#ftl>\nx${x}");
+ assertConvertedSame("\n\n <#ftl>\n\nx");
+ assertConverted("<#ftl outputFormat='HTML'>x", "<#ftl output_format='HTML'>x");
}
@Test