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/02 17:10:06 UTC
[2/2] incubator-freemarker git commit: Continued work on the FM2 to
FM3 converter
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/1f086e3f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/1f086e3f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/1f086e3f
Branch: refs/heads/3
Commit: 1f086e3f243e431408f613cbbc8b5f5d2831c18f
Parents: af17c34
Author: ddekany <dd...@apache.org>
Authored: Sun Jul 2 19:09:43 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sun Jul 2 19:09:43 2017 +0200
----------------------------------------------------------------------
.../core/FM2ASTToFM3SourceConverter.java | 233 ++++++++++++++-----
.../converter/FM2ToFM3ConverterTest.java | 68 ++++--
2 files changed, 215 insertions(+), 86 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1f086e3f/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 b88f9f2..b1f221c 100644
--- a/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java
+++ b/freemarker-converter/src/main/java/freemarker/core/FM2ASTToFM3SourceConverter.java
@@ -153,7 +153,7 @@ public class FM2ASTToFM3SourceConverter {
Expression content = getParam(node, 0, ParameterRole.CONTENT, Expression.class);
int pos = getPositionAfterWSAndExpComments(getEndPositionExclusive(content));
- assertNodeContent(pos < src.length(), node, "Unexpected EOF", null);
+ assertNodeContent(pos < src.length(), node, "Unexpected EOF");
char c = src.charAt(pos);
assertNodeContent(c == ';' || c == '}', node, "Expected ';' or '}', found {}", c);
if (c == ';') { // #{exp; m1M2} -> ${exp?string('0.0#')}
@@ -216,11 +216,128 @@ public class FM2ASTToFM3SourceConverter {
printDirCustom((UnifiedCall) node);
} else if (node instanceof Macro) {
printDirMacroOrFunction((Macro) node);
+ } else if (node instanceof Assignment) {
+ printDirAssignmentLonely((Assignment) node);
+ } else if (node instanceof AssignmentInstruction) {
+ printDirAssignmentMultiple((AssignmentInstruction) node);
+ } else if (node instanceof AttemptBlock) {
+ printDirAttemptRecover((AttemptBlock) node);
} else {
throw new ConverterException("Unhandled AST TemplateElement class: " + node.getClass().getName());
}
}
+ private void printDirAttemptRecover(AttemptBlock node) throws ConverterException {
+ print(tagBeginChar);
+ print("#attempt");
+ printStartTagSkippedTokens(node, null, true);
+ print(tagEndChar);
+
+ printNode(node.getChild(0));
+ assertNodeContent(node.getChild(1) instanceof RecoveryBlock, node, "child[1] should be #recover");
+
+ RecoveryBlock recoverDir = getOnlyParam(node, ParameterRole.ERROR_HANDLER, RecoveryBlock.class);
+ print(tagBeginChar);
+ print("#recover");
+ printStartTagSkippedTokens(recoverDir, null, true);
+ print(tagEndChar);
+
+ printChildrenElements(recoverDir);
+
+ print(tagBeginChar);
+ print("/#attempt"); // in FM2 this could be /#recover, but we normalize it
+ printEndTagSkippedTokens(node);
+ print(tagEndChar);
+ }
+
+ private void printDirAssignmentMultiple(AssignmentInstruction node) throws ConverterException {
+ assertParamCount(node, 2);
+
+ int pos = printDirAssignmentCommonTagTillAssignmentExp(node, 0);
+
+ int childCnt = node.getChildCount();
+ for (int childIdx = 0; childIdx < childCnt; childIdx++) {
+ Assignment assignment = (Assignment) node.getChild(childIdx);
+ pos = printDirAssignmentCommonExp(assignment, pos);
+ if (childIdx != childCnt - 1) {
+ pos = printWSAndExpComments(pos, ",", true);
+ }
+ }
+
+ printDirAssignmentCommonTagAfterLastAssignmentExp(node, 1, pos);
+ }
+
+ private void printDirAssignmentLonely(Assignment node) throws ConverterException {
+ assertParamCount(node, 5);
+
+ int pos = printDirAssignmentCommonTagTillAssignmentExp(node, 3);
+ pos = printDirAssignmentCommonExp(node, pos);
+ printDirAssignmentCommonTagAfterLastAssignmentExp(node, 4, pos);
+ }
+
+ private void printDirAssignmentCommonTagAfterLastAssignmentExp(TemplateElement node, int nsParamIdx, int pos) throws
+ ConverterException {
+ Expression ns = getParam(node, nsParamIdx, ParameterRole.NAMESPACE, Expression.class);
+ if (ns != null) {
+ pos = printWSAndExpComments(pos, "in", false);
+ 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);
+ }
+
+ private int printDirAssignmentCommonTagTillAssignmentExp(TemplateElement node, int scopeParamIdx)
+ throws ConverterException {
+ print(tagBeginChar);
+
+ int scope = getParam(node, scopeParamIdx, ParameterRole.VARIABLE_SCOPE, Integer.class);
+ String tagName;
+ if (scope == Assignment.NAMESPACE) {
+ tagName = "#assign";
+ } else if (scope == Assignment.GLOBAL) {
+ tagName = "#global";
+ } else if (scope == Assignment.LOCAL) {
+ tagName = "#local";
+ } else {
+ throw new UnexpectedNodeContentException(node, "Unhandled scope: {}", scope);
+ }
+ print(tagName);
+ int pos = getPositionAfterIdentifier(getStartPosition(node) + 2);
+
+ pos = printWSAndExpComments(pos);
+ return pos;
+ }
+
+ private int printDirAssignmentCommonExp(Assignment node, int pos) throws ConverterException {
+ {
+ String target = getParam(node, 0, ParameterRole.ASSIGNMENT_TARGET, String.class);
+ print(FTLUtil.escapeIdentifier(target));
+ pos = getPositionAfterIdentifier(pos);
+ }
+
+ pos = printWSAndExpComments(pos);
+
+ {
+ String operator = getParam(node, 1, ParameterRole.ASSIGNMENT_OPERATOR, String.class);
+ print(operator);
+ pos += operator.length();
+ }
+
+ pos = printWSAndExpComments(pos);
+
+ Expression source = getParam(node, 2, ParameterRole.ASSIGNMENT_SOURCE, Expression.class);
+ if (source != null) {
+ printExp(source);
+ pos = getEndPositionExclusive(source);
+ }
+
+ return pos;
+ }
+
private void printDirMacroOrFunction(Macro node) throws ConverterException {
int paramCnt = node.getParameterCount();
@@ -236,30 +353,19 @@ public class FM2ASTToFM3SourceConverter {
print(tagBeginChar);
print(tagName);
- int pos = getStartPosition(node) + 1;
- assertNodeContent(src.substring(pos, pos + tagName.length()).equals(tagName), node,
- "Tag name doesn't match {}", tagName);
- pos += tagName.length();
+ int pos = getPositionAfterIdentifier(getStartPosition(node) + 2);
- {
- String sep = readWSAndExpComments(pos);
- printWithConvertedExpComments(sep);
- pos += sep.length();
- }
+ pos = printWSAndExpComments(pos);
String assignedName = getParam(node, 0, ParameterRole.ASSIGNMENT_TARGET, String.class);
print(FTLUtil.escapeIdentifier(assignedName));
{
int lastPos = pos;
pos = getPositionAfterIdentifier(pos);
- assertNodeContent(pos > lastPos, node, "Expected target name", null);
+ assertNodeContent(pos > lastPos, node, "Expected target name");
}
- {
- String sep = readWSAndExpComments(pos, '(', true);
- printWithConvertedExpComments(sep);
- pos += sep.length();
- }
+ pos = printWSAndExpComments(pos, "(", true);
int paramIdx = 1;
while (node.getParameterRole(paramIdx) == ParameterRole.PARAMETER_NAME) {
@@ -268,22 +374,17 @@ public class FM2ASTToFM3SourceConverter {
{
int lastPos = pos;
pos = getPositionAfterIdentifier(pos);
- assertNodeContent(pos > lastPos, node, "Expected parameter name", null);
+ assertNodeContent(pos > lastPos, node, "Expected parameter name");
}
Expression paramDefault = getParam(node, paramIdx++, ParameterRole.PARAMETER_DEFAULT, Expression.class);
if (paramDefault != null) {
- String sep = readWSAndExpComments(pos, '=', false);
- printWithConvertedExpComments(sep);
+ printWSAndExpComments(pos, "=", false);
printExp(paramDefault);
pos = getEndPositionExclusive(paramDefault);
}
- {
- String sep = readWSAndExpComments(pos);
- printWithConvertedExpComments(sep);
- pos += sep.length();
- }
+ pos = printWSAndExpComments(pos);
{
char c = src.charAt(pos);
assertNodeContent(
@@ -295,13 +396,11 @@ public class FM2ASTToFM3SourceConverter {
print(c);
pos++;
- String sep = readWSAndExpComments(pos);
- printWithConvertedExpComments(sep);
- pos += sep.length();
+ pos = printWSAndExpComments(pos);
}
if (c == ')') {
assertNodeContent(node.getParameterRole(paramIdx) != ParameterRole.PARAMETER_NAME, node,
- "Expected no parameter after \"(\"", null);
+ "Expected no parameter after \"(\"");
}
}
}
@@ -318,15 +417,11 @@ public class FM2ASTToFM3SourceConverter {
int lastPos = pos;
pos = getPositionAfterIdentifier(pos);
assertNodeContent(pos > lastPos, node,
- "Expected catch-all parameter name", null);
- }
- {
- String sep = readWSAndExpComments(pos);
- printWithConvertedExpComments(sep);
- pos += sep.length();
+ "Expected catch-all parameter name");
}
+ pos = printWSAndExpComments(pos);
assertNodeContent(src.startsWith("...", pos), node,
- "Expected \"...\" after catch-all parameter name", null);
+ "Expected \"...\" after catch-all parameter name");
print("...");
pos += 3;
}
@@ -334,12 +429,8 @@ public class FM2ASTToFM3SourceConverter {
assertNodeContent(paramIdx == paramCnt - 1, node,
"Expected AST parameter at index {} to be the last one", paramIdx);
- {
- String sep = readWSAndExpComments(pos, ')', true);
- printWithConvertedExpComments(sep);
- pos += sep.length();
- }
- assertNodeContent(src.charAt(pos) == tagEndChar, node, "Tag end not found", null);
+ pos = printWSAndExpComments(pos, ")", true);
+ assertNodeContent(src.charAt(pos) == tagEndChar, node, "Tag end not found");
print(tagEndChar);
printChildrenElements(node);
@@ -389,9 +480,9 @@ public class FM2ASTToFM3SourceConverter {
int pos = getEndPositionExclusive(lastPrintedExp);
boolean beforeFirstLoopVar = true;
while (paramIdx < paramCount) {
- String sep = readWSAndExpComments(pos, beforeFirstLoopVar ? ';' : ',', false);
+ String sep = readWSAndExpComments(pos, beforeFirstLoopVar ? ";" : ",", false);
assertNodeContent(sep.length() != 0, node,
- "Can't find loop variable separator", null);
+ "Can't find loop variable separator");
printWithConvertedExpComments(sep);
pos += sep.length();
@@ -399,7 +490,7 @@ public class FM2ASTToFM3SourceConverter {
print(_StringUtil.toFTLTopLevelIdentifierReference(loopVarName));
String identifierInSrc = readIdentifier(pos);
assertNodeContent(identifierInSrc.length() != 0, node,
- "Can't find loop variable identifier in source", null);
+ "Can't find loop variable identifier in source");
pos += identifierInSrc.length(); // skip loop var name
beforeFirstLoopVar = false;
@@ -417,7 +508,7 @@ public class FM2ASTToFM3SourceConverter {
}
if (startTagEndPos != elementEndPos) { // We have an end-tag
assertNodeContent(src.charAt(startTagEndPos - 1) != '/', node,
- "Not expected \"/\" at the end of the start tag", null);
+ "Not expected \"/\" at the end of the start tag");
printChildrenElements(node);
print(tagBeginChar);
@@ -427,15 +518,15 @@ public class FM2ASTToFM3SourceConverter {
nameStartPos--;
}
assertNodeContent(nameStartPos >= 2, node,
- "Couldn't extract name from end-tag.", null);
+ "Couldn't extract name from end-tag.");
// Also prints ignored WS after name, for now:
printWithConvertedExpComments(src.substring(nameStartPos, elementEndPos));
print(tagEndChar);
} else { // We don't have end-tag
assertNodeContent(src.charAt(startTagEndPos - 1) == '/', node,
- "Expected \"/\" at the end of the start tag", null);
+ "Expected \"/\" at the end of the start tag");
assertNodeContent(node.getChildCount() == 0, node,
- "Expected no children", null);
+ "Expected no children");
}
}
@@ -649,9 +740,10 @@ public class FM2ASTToFM3SourceConverter {
private void printExpBuiltinVariable(BuiltinVariable node) throws ConverterException {
int startPos = getStartPosition(node);
- String sep = readWSAndExpComments(startPos, '.', false);
- printWithConvertedExpComments(sep);
- String name = src.substring(startPos + sep.length(), getEndPositionExclusive(node));
+
+ int varNameStart = printWSAndExpComments(startPos, ".", false);
+
+ String name = src.substring(varNameStart, getEndPositionExclusive(node));
print(convertBuiltInVariableName(name));
}
@@ -668,8 +760,7 @@ public class FM2ASTToFM3SourceConverter {
Expression lho = getParam(node, 0, ParameterRole.LEFT_HAND_OPERAND, Expression.class);
String rho = getParam(node, 1, ParameterRole.RIGHT_HAND_OPERAND, String.class);
printNode(lho);
- printWithConvertedExpComments(
- readWSAndExpComments(getEndPositionExclusive(lho), '.', false));
+ printWSAndExpComments(getEndPositionExclusive(lho), ".", false);
print(FTLUtil.escapeIdentifier(rho));
}
@@ -707,9 +798,9 @@ public class FM2ASTToFM3SourceConverter {
int openCharPos = getStartPosition(node);
int closeCharPos = getEndPositionInclusive(node);
assertNodeContent(src.charAt(openCharPos) == '{', node,
- "Expected '{'", null);
+ "Expected '{'");
assertNodeContent(src.charAt(closeCharPos) == '}', node,
- "Expected '}'", null);
+ "Expected '}'");
int paramCnt = node.getParameterCount();
if (paramCnt == 0) {
@@ -740,9 +831,9 @@ public class FM2ASTToFM3SourceConverter {
int openCharPos = getStartPosition(node);
int closeCharPos = getEndPositionInclusive(node);
assertNodeContent(src.charAt(openCharPos) == '[', node,
- "Expected '['", null);
+ "Expected '['");
assertNodeContent(src.charAt(closeCharPos) == ']', node,
- "Expected ']'", null);
+ "Expected ']'");
int paramCnt = node.getParameterCount();
if (paramCnt == 0) {
@@ -1064,7 +1155,7 @@ public class FM2ASTToFM3SourceConverter {
}
assertNodeContent(pos > 0 && isCoreNameChar(src.charAt(pos)), node,
- "Can't find end tag name", null);
+ "Can't find end tag name");
printWithConvertedExpComments(src.substring(pos + 1, tagEndPos));
}
@@ -1134,6 +1225,11 @@ public class FM2ASTToFM3SourceConverter {
}
private void assertNodeContent(boolean good, TemplateObject node, String
+ errorMessage) throws UnexpectedNodeContentException {
+ assertNodeContent(good, node, errorMessage, null);
+ }
+
+ private void assertNodeContent(boolean good, TemplateObject node, String
errorMessage, Object msgParam) throws UnexpectedNodeContentException {
if (!good) {
throw new UnexpectedNodeContentException(node, errorMessage, msgParam);
@@ -1220,21 +1316,36 @@ public class FM2ASTToFM3SourceConverter {
return src.substring(startPos, getPositionAfterWSAndExpComments(startPos));
}
- private String readWSAndExpComments(int startPos, char separator, boolean separatorOptional)
+ private String readWSAndExpComments(int startPos, String separator, boolean separatorOptional)
throws ConverterException {
int pos = getPositionAfterWSAndExpComments(startPos);
- if (pos == src.length() || src.charAt(pos) != separator) {
+ if (pos == src.length() || !src.startsWith(separator, pos)) {
// No separator
return separatorOptional ? src.substring(startPos, pos) : "";
}
- pos++; // Skip separator
+ pos += separator.length();
pos = getPositionAfterWSAndExpComments(pos);
return src.substring(startPos, pos);
}
+ private int printWSAndExpComments(int pos) throws ConverterException {
+ String sep = readWSAndExpComments(pos);
+ printWithConvertedExpComments(sep);
+ pos += sep.length();
+ return pos;
+ }
+
+ private int printWSAndExpComments(int pos, String separator, boolean sepOptional) throws
+ ConverterException {
+ String sep = readWSAndExpComments(pos, separator, sepOptional);
+ printWithConvertedExpComments(sep);
+ pos += sep.length();
+ return pos;
+ }
+
private int getPositionAfterIdentifier(int startPos) throws ConverterException {
int pos = startPos;
scanUntilIdentifierEnd: while (pos < src.length()) {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1f086e3f/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 9166e35..0f74125 100644
--- a/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java
+++ b/freemarker-converter/src/test/java/org/freemarker/converter/FM2ToFM3ConverterTest.java
@@ -70,19 +70,19 @@ public class FM2ToFM3ConverterTest extends ConverterTest {
assertConvertedSame("${f([ <#-- C --> ])}");
assertConvertedSame("${f([1])}");
assertConvertedSame("${f([1, [x,y], 3])}");
- assertConvertedSame("${f([<#-- C1 --> 1, <#-- C2 --> 2, <#-- C3 --> 3 <#-- C4 -->])}");
+ assertConvertedSame("${f([<#--1--> 1, <#--2--> 2, <#--3--> 3 <#--4-->])}");
assertConvertedSame("${f({})}");
assertConvertedSame("${f({k: v})}");
assertConvertedSame("${f({k1: v1, k2: v2, 'k3': 33})}");
- assertConvertedSame("${f({ <#-- C1 --> k1 <#-- C1 --> : <#-- C1 --> v1 <#-- C1 -->,k2:v2 <#-- C1 -->})}");
+ assertConvertedSame("${f({ <#--1--> k1 <#--2--> : <#--3--> v1 <#--4-->,k2:v2 <#--5-->})}");
assertConvertedSame("${f(1 .. 9)}");
assertConvertedSame("${f(1 ..* 9)}");
assertConvertedSame("${f(1 ..! 9)}");
assertConvertedSame("${f(1 ..< 9)}");
assertConvertedSame("${f(1 ..)}");
- assertConvertedSame("${f(1<#-- C1 -->..\t<#-- C2 -->9)}");
+ assertConvertedSame("${f(1<#--1-->..\t<#--2-->9)}");
}
@Test
@@ -93,24 +93,24 @@ public class FM2ToFM3ConverterTest extends ConverterTest {
assertConvertedSame("${f()}");
assertConvertedSame("${f(1)}");
assertConvertedSame("${f(1, 2)}");
- assertConvertedSame("${f<#-- C1 -->(<#-- C2 --> 1, 2 ,<#-- C3 --> 3,<#-- C4 -->4 <#-- C5 -->)}");
+ assertConvertedSame("${f<#--1-->(<#--2--> 1, 2 ,<#--3--> 3,<#--4-->4 <#--5-->)}");
assertConvertedSame("${m[key]}");
assertConvertedSame("${m['key']}");
- assertConvertedSame("${m <#-- C1 --> [ <#-- C2 --> key <#-- C3 --> ]}");
+ assertConvertedSame("${m <#--1--> [ <#--2--> key <#--3--> ]}");
assertConvertedSame("${seq\\-foo[1]}");
assertConvertedSame("${m.key}");
- assertConvertedSame("${m <#-- C1 --> . <#-- C3 --> key}");
+ assertConvertedSame("${m <#--1--> . <#--3--> key}");
assertConvertedSame("${.outputFormat}");
assertConvertedSame("${. <#-- C --> outputFormat}");
assertConverted("${.outputFormat}","${.output_format}");
assertConvertedSame("${a < b}${a <= b}${(a > b)}${(a >= b)}${a == b}${a != b}");
- assertConvertedSame("${a<#-- C1 --><<#-- C2 -->b}${a<#-- C3 --><=<#-- C4 -->b}"
- + "${(a<#-- C7 -->><#-- C8 -->b)}${(a<#-- C9 -->>=<#-- CA -->b)}"
- + "${a<#-- CB -->==<#-- CC -->b}${a<#-- CD -->!=<#-- CE -->b}");
+ assertConvertedSame("${a<#--1--><<#--2-->b}${a<#--3--><=<#--4-->b}"
+ + "${(a<#--7-->><#--8-->b)}${(a<#--9-->>=<#--A-->b)}"
+ + "${a<#--B-->==<#--C-->b}${a<#--D-->!=<#--E-->b}");
// "Same" for now, will be different later.
assertConvertedSame("${a = b}${a == b}");
assertConvertedSame("${a < b}${a lt b}${a \\lt b}");
@@ -120,19 +120,19 @@ public class FM2ToFM3ConverterTest extends ConverterTest {
// [FM3] Add \and and && tests when 2.3.27 is released
assertConvertedSame("${a && b}${a & b}${a || b}${a | b}");
- assertConvertedSame("${a<#-- C1 -->&&<#-- C2 -->b}${a<#-- C3 -->&<#-- C4 -->b}"
- + "${a<#-- C5 -->||<#-- C6 -->b}${a<#-- C7 -->|<#-- C8 -->b}");
+ assertConvertedSame("${a<#--1-->&&<#--2-->b}${a<#--3-->&<#--4-->b}"
+ + "${a<#--5-->||<#--6-->b}${a<#--7-->|<#--8-->b}");
- assertConvertedSame("${!a}${! foo}${! <#-- C1 --> bar}${!!c}");
+ assertConvertedSame("${!a}${! foo}${! <#--1--> bar}${!!c}");
assertConvertedSame("${a!} ${a!0}");
- assertConvertedSame("${a <#-- C1 --> !} ${a <#-- C2 --> ! <#-- C3 --> 0}");
+ assertConvertedSame("${a <#--1--> !} ${a <#--2--> ! <#--3--> 0}");
assertConvertedSame("${a!b.c(x!0, y!0)}");
assertConvertedSame("${(a.b)!x}");
// [FM3] Will be: a!(x+1)
assertConvertedSame("${a!x+1}");
- assertConvertedSame("${a??} ${a <#-- C1 --> ??}");
+ assertConvertedSame("${a??} ${a <#--1--> ??}");
}
@Test
@@ -166,25 +166,43 @@ public class FM2ToFM3ConverterTest extends ConverterTest {
assertConvertedSame("<#if foo >1<#elseIf bar >2<#else >3</#if >");
assertConvertedSame("<#macro m>body</#macro>");
- assertConvertedSame("<#macro <#-- C1 --> m <#-- C2 -->></#macro >");
+ assertConvertedSame("<#macro <#--1--> m <#--2-->></#macro >");
assertConvertedSame("<#macro m()></#macro>");
- assertConvertedSame("<#macro m <#-- C1 --> ( <#-- C2 --> ) <#-- C3 --> ></#macro>");
+ assertConvertedSame("<#macro m <#--1--> ( <#--2--> ) <#--3--> ></#macro>");
assertConvertedSame("<#macro m p1></#macro>");
assertConvertedSame("<#macro m(p1)></#macro>");
assertConvertedSame("<#macro m p1 p2 p3></#macro>");
- assertConvertedSame("<#macro m p1 <#-- C1 --> p2 <#-- C2 --> p3 <#-- C3 -->></#macro>");
- assertConvertedSame("<#macro m(p1<#-- C1 -->,<#-- C2 --> p2<#-- C3 -->,<#-- C4 -->"
- + " p5<#-- C5 -->)<#-- C6 -->></#macro>");
+ assertConvertedSame("<#macro m p1 <#--1--> p2 <#--2--> p3 <#--3-->></#macro>");
+ assertConvertedSame("<#macro m(p1<#--1-->,<#--2--> p2<#--3-->,<#--4-->"
+ + " p5<#--5-->)<#--6-->></#macro>");
assertConvertedSame("<#macro m p1=11 p2=foo p3=a+b></#macro>");
assertConvertedSame("<#macro m(p1=11, p2=foo, p3=a+b)></#macro>");
- assertConvertedSame("<#macro m p1<#-- C1 -->=<#-- C2 -->11<#-- C3 -->,<#-- C4 -->p2=22></#macro>");
+ assertConvertedSame("<#macro m p1<#--1-->=<#--2-->11<#--3-->,<#--4-->p2=22></#macro>");
assertConvertedSame("<#macro m others...></#macro>");
assertConvertedSame("<#macro m p1 others...></#macro>");
assertConvertedSame("<#macro m p1 p2=22 others...></#macro>");
assertConvertedSame("<#macro m(others...)></#macro>");
- assertConvertedSame("<#macro m(others <#-- C1 --> ... <#-- C2 --> )></#macro>");
+ assertConvertedSame("<#macro m(others <#--1--> ... <#--2--> )></#macro>");
assertConvertedSame("<#function m x y>foo</#function>");
assertConvertedSame("<#macro m\\-1 p\\-1></#macro>");
+
+ assertConvertedSame("<#assign x = 1>");
+ assertConvertedSame("<#global x = 1>");
+ assertConvertedSame("<#macro m><#local x = 1></#macro>");
+ assertConvertedSame("<#assign x = 1 in someNs>");
+ assertConvertedSame("<#assign <#--1--> x <#--2--> = <#--3--> 1 <#--4--> in <#--5--> someNs <#--6-->>");
+ assertConvertedSame("<#assign x=1 y=2,z=3>");
+ assertConvertedSame("<#assign x += 1>");
+ assertConvertedSame("<#assign x *= 2>");
+ assertConvertedSame("<#assign x-->");
+ assertConvertedSame("<#global x = 1, y++, z /= 2>");
+ assertConvertedSame("<#assign x = 1 y++ z /= 2>");
+ assertConvertedSame("<#assign <#--0-->x = 1<#--1-->,<#--2-->y++<#--3-->z/=2<#--4-->>");
+
+ assertConvertedSame("<#attempt>a<#recover>r</#attempt>");
+ 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 >");
}
@Test
@@ -199,14 +217,14 @@ public class FM2ToFM3ConverterTest extends ConverterTest {
assertConvertedSame("<@foo x\\-y=1 />");
assertConvertedSame("<@foo\n\tx = 1\n\ty = 2\n/>");
assertConvertedSame("<@foo 1 2 />");
- assertConvertedSame("<@foo <#-- C1 --> 1 <#-- C2 --> 2 <#-- C3 --> />");
+ assertConvertedSame("<@foo <#--1--> 1 <#--2--> 2 <#--3--> />");
assertConvertedSame("<@foo 1, 2 />");
- assertConvertedSame("<@foo <#-- C1 --> 1 <#-- C2 -->, <#-- C3 --> 2 <#-- C4 --> />");
+ assertConvertedSame("<@foo <#--1--> 1 <#--2-->, <#--3--> 2 <#--4--> />");
assertConvertedSame("<@foo x=1; i, j></@>");
assertConvertedSame("<@foo 1; i, j></@>");
assertConvertedSame("<@foo 1 2; i\\-2, j></@>");
assertConvertedSame("<@foo x=1 y=2; i></@>");
- assertConvertedSame("<@foo x=1 ;\n i <#-- C0 --> , <#-- C1 -->\n\t<!-- C2 --> j <#-- C3 -->\n></@>");
+ assertConvertedSame("<@foo x=1 ;\n i <#-- C0 --> , <#--1-->\n\t<!-- C2 --> j <#--3-->\n></@>");
}
@Test
@@ -219,7 +237,7 @@ public class FM2ToFM3ConverterTest extends ConverterTest {
@Test
public void testComments() throws IOException, ConverterException {
assertConvertedSame("\n<#--\n c\n\t-->\n");
- assertConvertedSame("${1 + <#-- C1 -->\r\n2 +[#-- C2 --]3 +<!--\tC3\t-->4 +[!-- C4 --] 5 + -<!-- -->1}");
+ assertConvertedSame("${1 + <#--1-->\r\n2 +[#-- C2 --]3 +<!--\tC3\t-->4 +[!-- C4 --] 5 + -<!-- -->1}");
}
@Test