Repository: incubator-freemarker Updated Branches: refs/heads/3 17279ba64 -> ea7a08903
Continued working on 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/ea7a0890 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/ea7a0890 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/ea7a0890 Branch: refs/heads/3 Commit: ea7a08903c20730f4020624cbce756bd31c25f30 Parents: 17279ba Author: ddekany <[email protected]> Authored: Wed Jul 12 02:16:30 2017 +0200 Committer: ddekany <[email protected]> Committed: Wed Jul 12 02:16:30 2017 +0200 ---------------------------------------------------------------------- .../core/FM2ASTToFM3SourceConverter.java | 184 +++++++++++-------- .../apache/freemarker/converter/Converter.java | 5 +- .../converter/FM2ToFM3ConverterCLI.java | 20 +- .../converter/FM2ToFM3ConverterCLITest.java | 3 +- .../converter/FM2ToFM3ConverterTest.java | 40 ++++ 5 files changed, 175 insertions(+), 77 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ea7a0890/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 4f7ffef..09fa90b 100644 --- a/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java +++ b/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java @@ -21,7 +21,6 @@ package freemarker.core; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -30,7 +29,6 @@ import java.util.Map; import java.util.Set; import org.apache.freemarker.converter.ConversionMarkers; -import org.apache.freemarker.converter.ConversionMarkers.Type; import org.apache.freemarker.converter.ConverterException; import org.apache.freemarker.converter.ConverterUtils; import org.apache.freemarker.converter.UnconvertableLegacyFeatureException; @@ -40,7 +38,8 @@ import org.apache.freemarker.core.util._ClassUtil; import org.apache.freemarker.core.util._NullArgumentException; import org.apache.freemarker.core.util._StringUtil; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import freemarker.template.Configuration; import freemarker.template.Template; @@ -267,7 +266,7 @@ public class FM2ASTToFM3SourceConverter { } } - private static final ImmutableList<String> NO_PARSE_FM_2_TAG_NAMES = ImmutableList.of("noparse", "noParse"); + private static final Set<String> NO_PARSE_FM_2_TAG_NAMES = ImmutableSet.of("noparse", "noParse"); private void printComment(Comment node) throws UnexpectedNodeContentException, UnconvertableLegacyFeatureException { print(tagBeginChar); @@ -342,6 +341,7 @@ public class FM2ASTToFM3SourceConverter { * Prints a directive */ private void printDir(TemplateElement node) throws ConverterException { + _NullArgumentException.check("node", node); if (node instanceof IfBlock) { printDirIfElseElseIfContainer((IfBlock) node); } else if (node instanceof ConditionalBlock) { @@ -408,11 +408,26 @@ public class FM2ASTToFM3SourceConverter { printDirFallback((FallbackInstruction) node); } else if (node instanceof TransformBlock) { printDirTransform((TransformBlock) node); + } else if (node instanceof OutputFormatBlock) { + printDirOutputFormat((OutputFormatBlock) node); } else { throw new ConverterException("Unhandled AST TemplateElement class: " + node.getClass().getName()); } } + private void printDirOutputFormat(OutputFormatBlock node) throws ConverterException { + printDirStartTagPartBeforeParams(node, "outputFormat"); + Expression value = getParam(node, 0, ParameterRole.VALUE, Expression.class); + printExp(value); + printDirStartTagEnd(node, value, false); + + printChildElements(node); + + printDirEndTag(node, OUTPUT_FORMAT_FM2_TAG_NAMES, "outputFormat"); + } + + private static final Set<String> OUTPUT_FORMAT_FM2_TAG_NAMES = ImmutableSet.of("outputFormat", "outputformat"); + private void printDirTransform(TransformBlock node) throws ConverterException { Expression callee = getParam(node, 0, ParameterRole.CALLEE, Expression.class); @@ -440,7 +455,7 @@ public class FM2ASTToFM3SourceConverter { pos = printWSAndExpComments(getEndPositionExclusive(paramValue)); } - printStartTagEnd(node, pos, false); + printDirStartTagEnd(node, pos, false); printChildElements(node); @@ -482,7 +497,7 @@ public class FM2ASTToFM3SourceConverter { lastParam = ns; } - printStartTagEnd(node, lastParam, false); + printDirStartTagEnd(node, lastParam, false); } private void printDirCase(Case node) throws ConverterException { @@ -506,7 +521,7 @@ public class FM2ASTToFM3SourceConverter { pos = getEndPositionExclusive(value); } - printStartTagEnd(node, pos, false); + printDirStartTagEnd(node, pos, false); printChildElements(node); @@ -521,7 +536,7 @@ public class FM2ASTToFM3SourceConverter { Expression param = getOnlyParam(node, ParameterRole.VALUE, Expression.class); printExp(param); - printStartTagEnd(node, param, false); + printDirStartTagEnd(node, param, false); // FM2 have allowed #case after #default, FM3 doesn't: boolean pastDefault = false; @@ -552,7 +567,7 @@ public class FM2ASTToFM3SourceConverter { printExp(message); pos = getEndPositionExclusive(message); } - printStartTagEnd(node, pos, false); + printDirStartTagEnd(node, pos, false); } private void printDirSetting(PropertySetting node) throws ConverterException { @@ -570,7 +585,7 @@ public class FM2ASTToFM3SourceConverter { Expression paramValue = getParam(node, 1, ParameterRole.ITEM_VALUE, Expression.class); printExp(paramValue); - printStartTagEnd(node, paramValue, false); + printDirStartTagEnd(node, paramValue, false); } private String convertSettingName(String name, TemplateObject node) throws ConverterException { @@ -618,7 +633,7 @@ public class FM2ASTToFM3SourceConverter { printOptionalSeparatorAndWSAndExpComments(pos, ","); } } - printStartTagEnd(node, pos, true); + printDirStartTagEnd(node, pos, true); } private void printDirBreak(BreakInstruction node) throws ConverterException { @@ -642,7 +657,7 @@ public class FM2ASTToFM3SourceConverter { pos = getPositionAfterIdentifier(pos); } - printStartTagEnd(node, pos, false); + printDirStartTagEnd(node, pos, false); printChildElements(node); @@ -753,7 +768,7 @@ public class FM2ASTToFM3SourceConverter { } } - private static final ImmutableList<String> LIST_FM_2_TAG_NAMES = ImmutableList.of("list", "foreach", "forEach"); + private static final Set<String> LIST_FM_2_TAG_NAMES = ImmutableSet.of("list", "foreach", "forEach"); private void printDirInclude(Include node) throws ConverterException { assertParamCount(node, 4); @@ -765,7 +780,8 @@ public class FM2ASTToFM3SourceConverter { Expression parseParam = getParam(node, 1, ParameterRole.PARSE_PARAMETER, Expression.class); if (parseParam != null) { - markers.markInSource(parseParam.getBeginLine(), parseParam.getBeginColumn(), Type.WARN, + markers.markInSource(parseParam.getBeginLine(), parseParam.getBeginColumn(), + ConversionMarkers.Type.WARN, "The \"parse\" parameter of #include was removed, as it's not supported anymore. Use the " + "templateConfigurations configuration setting to specify which files are not parsed."); @@ -773,7 +789,8 @@ public class FM2ASTToFM3SourceConverter { Expression encodingParam = getParam(node, 2, ParameterRole.ENCODING_PARAMETER, Expression.class); if (encodingParam != null) { - markers.markInSource(encodingParam.getBeginLine(), encodingParam.getBeginColumn(), Type.WARN, + markers.markInSource(encodingParam.getBeginLine(), encodingParam.getBeginColumn(), + ConversionMarkers.Type.WARN, "The \"encoding\" parameter of #include was removed, as it's not supported anymore. Use the " + "templateConfigurations configuration setting to specify which files has a different " + "encoding than the configured default."); @@ -851,15 +868,18 @@ public class FM2ASTToFM3SourceConverter { print(FTLUtil.escapeIdentifier(getParam(node, 1, ParameterRole.NAMESPACE, String.class))); pos = getPositionAfterIdentifier(pos); - printStartTagEnd(node, pos, false); + printDirStartTagEnd(node, pos, false); } private void printDirReturn(ReturnInstruction node) throws ConverterException { - printDirStartTagPartBeforeParams(node, "return"); + int pos = printDirStartTagPartBeforeParams(node, "return"); Expression value = getOnlyParam(node, ParameterRole.VALUE, Expression.class); - printExp(value); - printStartTagEnd(node, value, false); + if (value != null) { + printExp(value); + pos = getEndPositionExclusive(value); + } + printDirStartTagEnd(node, pos, false); } private void printDirFlush(FlushInstruction node) throws ConverterException { @@ -870,7 +890,7 @@ public class FM2ASTToFM3SourceConverter { printDirGenericNoParamsHasNested(node, NO_ESCAPE_FM_2_TAG_NAMES, "noEscape"); } - private static final ImmutableList<String> NO_ESCAPE_FM_2_TAG_NAMES = ImmutableList.of("noescape", "noEscape"); + private static final Set<String> NO_ESCAPE_FM_2_TAG_NAMES = ImmutableSet.of("noescape", "noEscape"); private void printDirEscape(EscapeBlock node) throws ConverterException { assertParamCount(node, 2); @@ -884,7 +904,7 @@ public class FM2ASTToFM3SourceConverter { Expression expTemplate = getParam(node, 1, ParameterRole.EXPRESSION_TEMPLATE, Expression.class); printExp(expTemplate); - printStartTagEnd(node, expTemplate, false); + printDirStartTagEnd(node, expTemplate, false); printChildElements(node); @@ -899,27 +919,26 @@ public class FM2ASTToFM3SourceConverter { printDirGenericNoParamsHasNested(node, AUTO_ESC_FM_2_TAG_NAMES, "autoEsc"); } - private static final ImmutableList<String> AUTO_ESC_FM_2_TAG_NAMES = ImmutableList.of("autoesc", "autoEsc"); + private static final Set<String> AUTO_ESC_FM_2_TAG_NAMES = ImmutableSet.of("autoesc", "autoEsc"); private void printDirNoAutoEsc(NoAutoEscBlock node) throws ConverterException { printDirGenericNoParamsHasNested(node, NO_AUTO_ESC_FM_2_TAG_NAMES, "noAutoEsc"); } - private static final ImmutableList<String> NO_AUTO_ESC_FM_2_TAG_NAMES = ImmutableList.of("noautoesc", "noAutoEsc"); + private static final Set<String> NO_AUTO_ESC_FM_2_TAG_NAMES = ImmutableSet.of("noautoesc", "noAutoEsc"); private void printDirGenericNoParamsHasNested(TemplateElement node, String fm3TagName) throws ConverterException { printDirGenericNoParamsHasNested(node, Collections.singleton(fm3TagName), fm3TagName); } - private void printDirGenericNoParamsHasNested(TemplateElement node, - Collection<String> fm2TagName, String fm3TagName) + private void printDirGenericNoParamsHasNested(TemplateElement node, Set<String> fm2TagNames, String fm3TagName) throws ConverterException { assertParamCount(node, 0); printDirStartTagNoParamsHasNested(node, fm3TagName); printChildElements(node); - printDirEndTag(node, fm2TagName, fm3TagName); + printDirEndTag(node, fm2TagNames, fm3TagName); } private void printDirGenericNoParamsNoNested(TemplateElement node, String name) @@ -945,7 +964,7 @@ public class FM2ASTToFM3SourceConverter { printDirEndTag(node, ATTEMPT_RECOVER_FM_2_TAG_NAMES, "attempt", false); } - private static final ImmutableList<String> ATTEMPT_RECOVER_FM_2_TAG_NAMES = ImmutableList.of("attempt", "recover"); + private static final Set<String> ATTEMPT_RECOVER_FM_2_TAG_NAMES = ImmutableSet.of("attempt", "recover"); private void printDirAssignmentMultiple(AssignmentInstruction node) throws ConverterException { assertParamCount(node, 2); @@ -987,7 +1006,7 @@ public class FM2ASTToFM3SourceConverter { pos = getEndPositionExclusive(namespace); } - printStartTagEnd(node, pos, true); + printDirStartTagEnd(node, pos, true); printChildElements(node); @@ -1002,11 +1021,8 @@ public class FM2ASTToFM3SourceConverter { printExp(ns); pos = getEndPositionExclusive(ns); } - pos = printWSAndExpComments(pos); - char c = src.charAt(pos); - assertNodeContent(c == tagEndChar, node, "End of tag was expected, but found {}", c); - print(tagEndChar); + printDirStartTagEnd(node, pos, false); } private int printDirAssignmentCommonTagTillAssignmentExp(TemplateElement node, int scopeParamIdx) @@ -1229,7 +1245,7 @@ public class FM2ASTToFM3SourceConverter { if (legacyCallDirMode) { print('/'); } - int startTagEndPos = printStartTagEnd(node, pos, false); + int startTagEndPos = printDirStartTagEnd(node, pos, false); int elementEndPos = getEndPositionInclusive(node); { @@ -1282,7 +1298,7 @@ public class FM2ASTToFM3SourceConverter { if (conditionExp != null) { printDirStartTagPartBeforeParams(node, tagName); printNode(conditionExp); - printStartTagEnd(node, conditionExp, true); + printDirStartTagEnd(node, conditionExp, true); } else { printDirStartTagNoParamsHasNested(node, tagName); } @@ -1304,6 +1320,7 @@ public class FM2ASTToFM3SourceConverter { * Prints an expression */ private void printExp(Expression node) throws ConverterException { + _NullArgumentException.check("node", node); if (node instanceof Identifier) { printExpIdentifier((Identifier) node); } else if (node instanceof NumberLiteral) { @@ -1349,6 +1366,7 @@ public class FM2ASTToFM3SourceConverter { } else if (node instanceof ExistsExpression) { printExpExists((ExistsExpression) node); } else { + throw new ConverterException("Unhandled AST node expression class: " + node.getClass().getName()); } } @@ -1650,37 +1668,39 @@ public class FM2ASTToFM3SourceConverter { } private void printExpBuiltIn(BuiltIn node) throws ConverterException { - assertParamCount(node, 2); Expression lho = getParam(node, 0, ParameterRole.LEFT_HAND_OPERAND, Expression.class); String rho = getParam(node, 1, ParameterRole.RIGHT_HAND_OPERAND, String.class); - printExp(lho); // [lho]?biName + // <lho>?biName + printExp(lho); + int pos = getEndPositionExclusive(lho); + + // lho<?>biName + pos = printSeparatorAndWSAndExpComments(pos, "?"); - int postLHOPos = getEndPositionExclusive(lho); - int endPos = getEndPositionInclusive(node); - boolean foundQuestionMark = false; - int pos = postLHOPos; - scanForRHO: - while (pos < endPos) { - char c = src.charAt(pos); - if (c == '?') { - foundQuestionMark = true; - pos++; - } else if (Character.isWhitespace(c)) { - pos++; - } else if (isCoreNameChar(c)) { - break scanForRHO; - } else { - throw new UnexpectedNodeContentException(node, - "Unexpected character when scanning for for built-in key: {}", c); + // lho?<biName> + print(convertBuiltInName(rho)); + + if (node instanceof BuiltInWithParseTimeParameters) { + // lho?biName<(> + pos = getPositionAfterIdentifier(pos); + pos = printSeparatorAndWSAndExpComments(pos, "("); + int paramCnt = node.getParameterCount(); + for (int paramIdx = 2; paramIdx < paramCnt; paramIdx++) { + Expression argValue = getParam(node, paramIdx, ParameterRole.ARGUMENT_VALUE, Expression.class); + printExp(argValue); + pos = getEndPositionExclusive(argValue); + + if (paramIdx + 1 < paramCnt) { + printSeparatorAndWSAndExpComments(pos, ","); + } } + pos = printSeparatorAndWSAndExpComments(pos, ")"); + assertNodeContent(pos == getEndPositionExclusive(node), node, + "Actual end position doesn't match node end position."); + } else { + assertParamCount(node, 2); } - if (pos == endPos || !foundQuestionMark) { - throw new UnexpectedNodeContentException(node, "Couldn't find built-in key in source", null); - } - print(src.substring(postLHOPos, pos)); // lho[?]biName - - print(convertBuiltInName(rho)); } private void printExpStringLiteral(StringLiteral node) throws ConverterException { @@ -1740,10 +1760,9 @@ public class FM2ASTToFM3SourceConverter { } private String convertBuiltInName(String name) throws ConverterException { - String converted = name.indexOf('_') == -1 ? name : ConverterUtils.snakeCaseToCamelCase(name); - - if (converted.equals("webSafe")) { - return "html"; + String converted = IRREGULAR_BUILT_IN_NAME_CONVERSIONS.get(name); + if (converted == null) { + converted = name.indexOf('_') == -1 ? name : ConverterUtils.snakeCaseToCamelCase(name); } if (!fm3BuiltInNames.contains(converted)) { @@ -1753,6 +1772,24 @@ public class FM2ASTToFM3SourceConverter { return converted; } + private static Map<String, String> IRREGULAR_BUILT_IN_NAME_CONVERSIONS = new ImmutableMap.Builder<String, String>() + .put("webSafe", "html") + .put("web_safe", "html") + .put("iso_utc_fz", "isoUtcFZ") + .put("iso_utc_nz", "isoUtcNZ") + .put("iso_utc_ms_nz", "isoUtcMsNZ") + .put("iso_utc_m_nz", "isoUtcMNZ") + .put("iso_utc_h_nz", "isoUtcHNZ") + .put("iso_local_nz", "isoLocalNZ") + .put("iso_local_ms_nz", "isoLocalMsNZ") + .put("iso_local_m_nz", "isoLocalMNZ") + .put("iso_local_h_nz", "isoLocalHNZ") + .put("iso_nz", "isoNZ") + .put("iso_ms_nz", "isoMsNZ") + .put("iso_m_nz", "isoMNZ") + .put("iso_h_nz", "isoHNZ") + .build(); + private void printParameterSeparatorSource(Expression lho, Expression rho) { print(getSrcSectionExclEnd( lho.getEndColumn() + 1, lho.getEndLine(), @@ -1793,7 +1830,7 @@ public class FM2ASTToFM3SourceConverter { private int printDirStartTagNoParams(TemplateElement node, String fm3TagName, boolean removeSlash) throws ConverterException { int pos = printDirStartTagPartBeforeParams(node, fm3TagName); - printStartTagEnd(node, pos, removeSlash); + printDirStartTagEnd(node, pos, removeSlash); return pos + 1; } @@ -1801,21 +1838,20 @@ public class FM2ASTToFM3SourceConverter { printDirEndTag(node, Collections.singleton(tagName), tagName); } - private void printDirEndTag(TemplateElement node, Collection<String> fm2TagName, String fm3TagName) throws + private void printDirEndTag(TemplateElement node, Set<String> fm2TagNames, String fm3TagName) throws UnexpectedNodeContentException { - if (fm2TagName.size() == 0) { + if (fm2TagNames.size() == 0) { throw new IllegalArgumentException("You must specify at least 1 FM2 tag names"); } - if (fm2TagName.size() == 1 && containsUpperCaseLetter(fm3TagName)) { + if (fm2TagNames.size() == 1 && containsUpperCaseLetter(fm3TagName)) { throw new IllegalArgumentException( "You must specify multiple FM2 tag names when the FM3 tag name (" + fm3TagName + ") contains upper case letters"); } - printDirEndTag(node, fm2TagName, fm3TagName, false); + printDirEndTag(node, fm2TagNames, fm3TagName, false); } - private void printDirEndTag(TemplateElement node, Collection<String> fm2TagNames, String fm3TagName, - boolean optional) + private void printDirEndTag(TemplateElement node, Set<String> fm2TagNames, String fm3TagName, boolean optional) throws UnexpectedNodeContentException { int tagEndPos = getEndPositionInclusive(node); { @@ -1900,10 +1936,10 @@ public class FM2ASTToFM3SourceConverter { * @return The position of the last character of the start tag. Note that the printed string never includes this * character. */ - private int printStartTagEnd(TemplateElement node, Expression lastParam, boolean trimSlash) + private int printDirStartTagEnd(TemplateElement node, Expression lastParam, boolean trimSlash) throws ConverterException { _NullArgumentException.check("lastParam", lastParam); - return printStartTagEnd( + return printDirStartTagEnd( node, getPosition(lastParam.getEndColumn() + 1, lastParam.getEndLine()), trimSlash); @@ -1932,13 +1968,13 @@ public class FM2ASTToFM3SourceConverter { } /** - * Similar to {@link #printStartTagEnd(TemplateElement, Expression, boolean)}, but with explicitly + * Similar to {@link #printDirStartTagEnd(TemplateElement, Expression, boolean)}, but with explicitly * specified scan start position. * * @param pos * The position where the first skipped character can occur (or the tag end character). */ - private int printStartTagEnd(TemplateElement node, int pos, boolean removeSlash) + private int printDirStartTagEnd(TemplateElement node, int pos, boolean removeSlash) throws ConverterException { final int startPos = pos; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ea7a0890/freemarker-converter/src/main/java/org/apache/freemarker/converter/Converter.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/main/java/org/apache/freemarker/converter/Converter.java b/freemarker-converter/src/main/java/org/apache/freemarker/converter/Converter.java index 3d4d4f6..514ffe0 100644 --- a/freemarker-converter/src/main/java/org/apache/freemarker/converter/Converter.java +++ b/freemarker-converter/src/main/java/org/apache/freemarker/converter/Converter.java @@ -179,7 +179,10 @@ public abstract class Converter { prepare(); LOG.debug("Source: {}", source); - LOG.debug("Destination directory: {}", destinationDirectory); + LOG.debug("DestinationDirectory: {}", destinationDirectory); + LOG.debug("CreateDestinationDirectory: {}", createDestinationDirectory); + LOG.debug("Include: {}", include); + LOG.debug("Exclude: {}", exclude); // Just so that no confusing marker file remains there: File markerFile = new File(destinationDirectory, CONVERSION_MARKERS_FILE_NAME); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ea7a0890/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3ConverterCLI.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3ConverterCLI.java b/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3ConverterCLI.java index d17c113..208a727 100644 --- a/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3ConverterCLI.java +++ b/freemarker-converter/src/main/java/org/apache/freemarker/converter/FM2ToFM3ConverterCLI.java @@ -23,6 +23,8 @@ import java.io.File; import java.io.PrintWriter; import java.util.Arrays; import java.util.List; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; @@ -126,6 +128,12 @@ public class FM2ToFM3ConverterCLI { if (cl.hasOption(CREATE_DESTINATION_OPTION)) { converter.setCreateDestinationDirectory(true); } + if (cl.hasOption(INCLUDE_OPTION)) { + converter.setInclude(getRegexpOption(cl, INCLUDE_OPTION)); + } + if (cl.hasOption(EXCLUDE_OPTION)) { + converter.setExclude(getRegexpOption(cl, EXCLUDE_OPTION)); + } converter.setFreeMarker2Settings(cl.getOptionProperties(FREEMARKER_2_SETTING_OPTION_SHORT)); try { converter.execute(); @@ -136,7 +144,7 @@ public class FM2ToFM3ConverterCLI { printWrapped("Conversion was finished successfully. " + "Converted " + converter.getConvertedFileCount() + " file(s)."); } - } catch (Throwable e) { + } catch (ConverterException e) { printWrapped("Conversion was terminated with error. See details in the Java stack " + "trace:\n"); printConciseStackTrace(e); @@ -152,6 +160,16 @@ public class FM2ToFM3ConverterCLI { return SUCCESS_EXIT_STATUS; } + private Pattern getRegexpOption(CommandLine cl, String optionName) throws ParseException { + String optionValue = cl.getOptionValue(optionName); + try { + return Pattern.compile(optionValue); + } catch (PatternSyntaxException e) { + throw new ParseException( + "The value of the \"" + optionName + "\" is not a valid regular expression: " + optionValue); + } + } + private void printConciseStackTrace(Throwable e) { boolean first = true; while (e != null) { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ea7a0890/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterCLITest.java ---------------------------------------------------------------------- diff --git a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterCLITest.java b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterCLITest.java index 982cccf..2d794d6 100644 --- a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterCLITest.java +++ b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterCLITest.java @@ -77,7 +77,8 @@ public class FM2ToFM3ConverterCLITest extends ConverterTest { srcDir.toString(), "-d", dstDir.toString(), "--include", ".*", "--exclude", ".*2\\.ftl"); assertTrue(new File(dstDir, "1.fm3").exists()); - assertFalse(new File(dstDir, "3.txt").exists()); + assertFalse(new File(dstDir, "2.fm3").exists()); + assertTrue(new File(dstDir, "3.txt").exists()); } public void assertCLIResult(int expectedExitStatus, String stdoutContains, String stdoutNotContains, String... http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ea7a0890/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 07af58b..4852604 100644 --- a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java +++ b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java @@ -25,7 +25,9 @@ import static org.junit.Assert.*; import java.io.File; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.Properties; +import java.util.Set; import org.apache.commons.io.FileUtils; import org.apache.freemarker.converter.ConverterException; @@ -34,6 +36,8 @@ import org.apache.freemarker.converter.UnconvertableLegacyFeatureException; import org.freemarker.converter.test.ConverterTest; import org.junit.Test; +import com.google.common.collect.ImmutableSet; + import freemarker.template.Configuration; public class FM2ToFM3ConverterTest extends ConverterTest { @@ -198,6 +202,7 @@ public class FM2ToFM3ConverterTest extends ConverterTest { assertConvertedSame("<#macro m><#nested x + 1 2 3></#macro>"); assertConvertedSame("<#macro m><#nested <#--1--> x + 1 <#--2--> 2 <#--3-->></#macro>"); assertConverted("<#macro m><#nested x></#macro>", "<#macro m><#nested x /></#macro>"); + assertConvertedSame("<#macro m><#return><#return ></#macro>"); assertConvertedSame("<#assign x = 1>"); assertConvertedSame("<#global x = 1>"); @@ -213,6 +218,7 @@ public class FM2ToFM3ConverterTest extends ConverterTest { assertConvertedSame("<#assign <#--0-->x = 1<#--1-->,<#--2-->y++<#--3-->z/=2<#--4-->>"); // Only works with " now, as it doesn't keep the literal kind. Later we will escape differently anyway: assertConvertedSame("<#assign \"x y\" = 1>"); + assertConvertedSame("<#assign x = 1/>"); assertConvertedSame("<#assign x>t</#assign>"); assertConvertedSame("<#assign x in ns>t</#assign>"); @@ -362,6 +368,8 @@ public class FM2ToFM3ConverterTest extends ConverterTest { assertConvertedSame("<#recurse node <#--1--> using <#--2--> ns <#--3-->>"); assertConvertedSame("<#macro m><#fallback></#macro>"); assertConvertedSame("<#macro m><#fallback /></#macro>"); + + assertConvertedSame("<#outputFormat 'HTML'>${x}</#outputFormat>"); } @Test @@ -412,6 +420,35 @@ public class FM2ToFM3ConverterTest extends ConverterTest { assertConverted("${s?upperCase} ${s?leftPad(123)}", "${s?upper_case} ${s?left_pad(123)}"); assertConverted("${s?html}", "${s?web_safe}"); assertConvertedSame("${s ? upperCase\t?\t\tleftPad(5)}"); + assertConvertedSame("${s <#--1--> ? <#--2--> upperCase}"); + // Runtime params: + assertConvertedSame("${s?leftPad(9)}"); + // Parse time params: + assertConvertedSame("${s?then(1, 2)}"); + assertConvertedSame("${s?switch(1, 'one', 2, 'two', 'more')}"); + assertConvertedSame("${s?then <#--1--> ( <#--2--> 1 <#--3-->, <#--5--> 2 <#--6--> )}"); + } + + /** Tests if the names of all current FM2 built-ins can be converted to FM3 names. */ + @Test + public void testBuiltInNameConversion() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, + ConverterException { + Configuration cfg = new Configuration(Configuration.getVersion()); + + StringBuilder sb = new StringBuilder(); + sb.append("<#outputformat 'HTML'><#list xs as x>"); + for (String builtInName : cfg.getSupportedBuiltInNames(Configuration.LEGACY_NAMING_CONVENTION)) { + if (!LEGACY_ESCAPING_BUTILT_INS.contains(builtInName)) { + sb.append("${x?").append(builtInName).append("(1, 2)").append("}"); + } + } + sb.append("</#list></#outputformat>"); + for (String builtInName : LEGACY_ESCAPING_BUTILT_INS) { + sb.append("${x?").append(builtInName).append("}"); + } + + convert(sb.toString()); } @Test @@ -476,6 +513,9 @@ public class FM2ToFM3ConverterTest extends ConverterTest { assertTrue(new File(dstDir, "t10.Foo3").exists()); } + private static final Set<String> LEGACY_ESCAPING_BUTILT_INS = ImmutableSet.of( + "html", "xml", "xhtml", "rtf", "web_safe"); + private void assertConvertedSame(String ftl2) throws IOException, ConverterException { assertConverted(ftl2, ftl2); }
