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/08/25 23:39:33 UTC
[07/19] incubator-freemarker git commit: Bug fixed (FREEMARKER-70):
The usage of loop variable built-ins, like loopVar?index,
was disallowed by the parser inside interpolations that are inside a string
literal expression (as in <#list 1..3 as loopVar>${'
Bug fixed (FREEMARKER-70): The usage of loop variable built-ins, like loopVar?index, was disallowed by the parser inside interpolations that are inside a string literal expression (as in <#list 1..3 as loopVar>${'${loopVar?index}'}</#list>), saying that there's no loop variable in scope with loopVar name.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/056bf1cd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/056bf1cd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/056bf1cd
Branch: refs/heads/2.3
Commit: 056bf1cd7e59740af304b2566caacd921378a5bd
Parents: 924a420
Author: ddekany <dd...@apache.org>
Authored: Sat Aug 12 00:20:32 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sat Aug 12 00:20:32 2017 +0200
----------------------------------------------------------------------
src/main/java/freemarker/core/StringLiteral.java | 12 +++++-------
src/main/javacc/FTL.jj | 19 +++++++++++++------
src/manual/en_US/book.xml | 13 +++++++++++++
.../java/freemarker/core/ListErrorsTest.java | 5 +++++
4 files changed, 36 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/056bf1cd/src/main/java/freemarker/core/StringLiteral.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/StringLiteral.java b/src/main/java/freemarker/core/StringLiteral.java
index c2b69a6..7c25623 100644
--- a/src/main/java/freemarker/core/StringLiteral.java
+++ b/src/main/java/freemarker/core/StringLiteral.java
@@ -41,15 +41,13 @@ final class StringLiteral extends Expression implements TemplateScalarModel {
}
/**
- * @param parentTkMan
- * The token source of the template that contains this string literal. As of this writing, we only need
- * this to share the {@code namingConvetion} with that.
+ * @param parentParser
+ * The parser of the template that contains this string literal.
*/
- void parseValue(FMParserTokenManager parentTkMan, OutputFormat outputFormat) throws ParseException {
+ void parseValue(FMParser parentParser, OutputFormat outputFormat) throws ParseException {
// The way this works is incorrect (the literal should be parsed without un-escaping),
// but we can't fix this backward compatibly.
if (value.length() > 3 && (value.indexOf("${") >= 0 || value.indexOf("#{") >= 0)) {
-
Template parentTemplate = getTemplate();
ParserConfiguration pcfg = parentTemplate.getParserConfiguration();
@@ -65,12 +63,12 @@ final class StringLiteral extends Expression implements TemplateScalarModel {
FMParser parser = new FMParser(parentTemplate, false, tkMan, pcfg);
// We continue from the parent parser's current state:
- parser.setupStringLiteralMode(parentTkMan, outputFormat);
+ parser.setupStringLiteralMode(parentParser, outputFormat);
try {
dynamicValue = parser.StaticTextAndInterpolations();
} finally {
// The parent parser continues from this parser's current state:
- parser.tearDownStringLiteralMode(parentTkMan);
+ parser.tearDownStringLiteralMode(parentParser);
}
} catch (ParseException e) {
e.setTemplateName(parentTemplate.getSourceName());
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/056bf1cd/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index 175614c..2963a41 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -78,7 +78,7 @@ public class FMParser {
private ParserConfiguration pCfg;
/** Keeps track of #list and #foreach nesting. */
- private List/*<ParserIteratorBlockContext>*/ iteratorBlockContexts;
+ private List<ParserIteratorBlockContext> iteratorBlockContexts;
/**
* Keeps track of the nesting depth of directives that support #break.
@@ -273,7 +273,9 @@ public class FMParser {
}
}
- void setupStringLiteralMode(FMParserTokenManager parentTokenSource, OutputFormat outputFormat) {
+ void setupStringLiteralMode(FMParser parentParser, OutputFormat outputFormat) {
+ FMParserTokenManager parentTokenSource = parentParser.token_source;
+
token_source.initialNamingConvention = parentTokenSource.initialNamingConvention;
token_source.namingConvention = parentTokenSource.namingConvention;
token_source.namingConventionEstabilisher = parentTokenSource.namingConventionEstabilisher;
@@ -285,9 +287,14 @@ public class FMParser {
// Emulate bug, where the string literal parser haven't inherited the IcI:
incompatibleImprovements = _TemplateAPI.VERSION_INT_2_3_0;
}
+
+ // So that loop variable built-ins, like ?index, works inside the interpolations in the string literal:
+ iteratorBlockContexts = parentParser.iteratorBlockContexts;
}
- void tearDownStringLiteralMode(FMParserTokenManager parentTokenSource) {
+ void tearDownStringLiteralMode(FMParser parentParser) {
+ // If the naming convention was established inside the string literal, it's inherited by the parent:
+ FMParserTokenManager parentTokenSource = parentParser.token_source;
parentTokenSource.namingConvention = token_source.namingConvention;
parentTokenSource.namingConventionEstabilisher = token_source.namingConventionEstabilisher;
}
@@ -507,7 +514,7 @@ public class FMParser {
private ParserIteratorBlockContext pushIteratorBlockContext() {
if (iteratorBlockContexts == null) {
- iteratorBlockContexts = new ArrayList(4);
+ iteratorBlockContexts = new ArrayList<ParserIteratorBlockContext>(4);
}
ParserIteratorBlockContext newCtx = new ParserIteratorBlockContext();
iteratorBlockContexts.add(newCtx);
@@ -527,7 +534,7 @@ public class FMParser {
throws ParseException {
int size = iteratorBlockContexts != null ? iteratorBlockContexts.size() : 0;
for (int i = size - 1; i >= 0; i--) {
- ParserIteratorBlockContext ctx = (ParserIteratorBlockContext) iteratorBlockContexts.get(i);
+ ParserIteratorBlockContext ctx = iteratorBlockContexts.get(i);
if (loopVarName.equals(ctx.loopVarName) || loopVarName.equals(ctx.loopVar2Name)) {
if (ctx.kind == ITERATOR_BLOCK_KIND_USER_DIRECTIVE) {
throw new ParseException(
@@ -2297,7 +2304,7 @@ StringLiteral StringLiteral(boolean interpolate) :
result.setLocation(template, t, t);
if (interpolate && !raw) {
// TODO: This logic is broken. It can't handle literals that contains both ${...} and $\{...}.
- if (t.image.indexOf("${") >= 0 || t.image.indexOf("#{") >= 0) result.parseValue(token_source, outputFormat);
+ if (t.image.indexOf("${") >= 0 || t.image.indexOf("#{") >= 0) result.parseValue(this, outputFormat);
}
return result;
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/056bf1cd/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 6d6d6f9..03c42b0 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26926,6 +26926,19 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
</listitem>
<listitem>
+ <para>Bug fixed (<link
+ xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-70">FREEMARKER-70</link>):
+ The usage of loop variable built-ins, like
+ <literal><replaceable>loopVar</replaceable>?index</literal>, was
+ disallowed by the parser inside interpolations that are inside a
+ string literal expression (as in <literal><#list 1..3 as
+ loopVar>${'${loopVar?index}'}</#list></literal>),
+ saying that there's no loop variable in scope with
+ <literal><replaceable>loopVar</replaceable></literal>
+ name.</para>
+ </listitem>
+
+ <listitem>
<para>Bug fixed: Comments were not allowed by the parser between
the <literal>switch</literal> tag and the first
<literal>case</literal> tag.</para>
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/056bf1cd/src/test/java/freemarker/core/ListErrorsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ListErrorsTest.java b/src/test/java/freemarker/core/ListErrorsTest.java
index 60ca7e6..7a4aaa4 100644
--- a/src/test/java/freemarker/core/ListErrorsTest.java
+++ b/src/test/java/freemarker/core/ListErrorsTest.java
@@ -47,6 +47,11 @@ public class ListErrorsTest extends TemplateTest {
+ "</#list>",
"1@0[3,4@0]1@0; 2@1[3,4@0]2@1; ");
}
+
+ @Test
+ public void stringInterpolationBugFixTest() throws IOException, TemplateException {
+ assertOutput("<#list 1..3 as x>${'${x?index}'}</#list>", "012");
+ }
@Test
public void testInvalidItemsParseTime() throws IOException, TemplateException {