For PR #88 forceAutoEscape: Better error messages. Some more test coverage.
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index a744727..55955c5 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -237,11 +237,9 @@
outputFormat = outputFormatFromExt;
}
}
- if (!(outputFormat instanceof MarkupOutputFormat)
- && autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
- throw new IllegalArgumentException(
- "Non-markup output format cannot be used when auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY.");
- }
+ if (!(outputFormat instanceof MarkupOutputFormat) && autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
+ throw new IllegalArgumentException(forcedAutoEscapingPolicyExceptionMessage(outputFormat));
+ }
recalculateAutoEscapingField();
token_source.setParser(this);
@@ -286,17 +284,17 @@
_TemplateAPI.setOutputFormat(template, 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;
token_source.SwitchTo(NO_DIRECTIVE);
-
+
this.outputFormat = outputFormat;
- recalculateAutoEscapingField();
+ recalculateAutoEscapingField();
if (incompatibleImprovements < _VersionInts.V_2_3_24) {
// Emulate bug, where the string literal parser haven't inherited the IcI:
incompatibleImprovements = _VersionInts.V_2_3_0;
@@ -527,6 +525,15 @@
}
}
+ private static String forcedAutoEscapingPolicyExceptionMessage(OutputFormat outputFormat) {
+ return forcedAutoEscapingPolicyExceptionMessage("Non-markup output format " + outputFormat);
+ }
+
+ private static String forcedAutoEscapingPolicyExceptionMessage(String whatCanNotBeUsed) {
+ return whatCanNotBeUsed + " can't be used when the \"" + Configuration.AUTO_ESCAPING_POLICY_KEY + "\" "
+ + "configuration setting was set to \"force\" (FORCE_AUTO_ESCAPING_POLICY).";
+ }
+
private ParserIteratorBlockContext pushIteratorBlockContext() {
if (iteratorBlockContexts == null) {
iteratorBlockContexts = new ArrayList<ParserIteratorBlockContext>(4);
@@ -571,7 +578,7 @@
// [2.4] Use camel case as the default
return token_source.namingConvention == Configuration.CAMEL_CASE_NAMING_CONVENTION ? "#forEach" : "#foreach";
}
-
+
}
PARSER_END(FMParser)
@@ -2230,13 +2237,13 @@
return result;
}
- if (result instanceof BuiltInBannedWhenForcedAutoEscaping) {
- if (autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
- throw new ParseException(
- "Using ?" + t.image + " is not allowed while auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY.",
- template, t);
- }
- }
+ if (result instanceof BuiltInBannedWhenForcedAutoEscaping) {
+ if (autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
+ throw new ParseException(
+ forcedAutoEscapingPolicyExceptionMessage("The ?" + t.image + " expression"),
+ template, t);
+ }
+ }
if (result instanceof MarkupOutputFormatBoundBuiltIn) {
if (!(outputFormat instanceof MarkupOutputFormat)) {
@@ -4060,12 +4067,10 @@
} else {
outputFormat = template.getConfiguration().getOutputFormat(paramStr);
}
- if (!(outputFormat instanceof MarkupOutputFormat)
- && autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
- throw new ParseException(
- "Non-markup output format cannot be used when auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY.",
- template, start);
- }
+ if (!(outputFormat instanceof MarkupOutputFormat)
+ && autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
+ throw new ParseException(forcedAutoEscapingPolicyExceptionMessage(outputFormat), template, start);
+ }
recalculateAutoEscapingField();
} catch (IllegalArgumentException e) {
throw new ParseException("Invalid format name: " + e.getMessage(), template, start, e.getCause());
@@ -4120,11 +4125,12 @@
{
start = <NOAUTOESC>
{
- if (autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
- throw new ParseException(
- "<#noautoesc> cannot be used when auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY.",
- template, start);
- }
+ if (autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
+ throw new ParseException(
+ forcedAutoEscapingPolicyExceptionMessage(
+ "<#" + (token_source.namingConvention == Configuration.CAMEL_CASE_NAMING_CONVENTION ? "noAutoEsc" : "noautoesc") + ">"),
+ template, start);
+ }
lastAutoEscapingPolicy = autoEscapingPolicy;
autoEscapingPolicy = Configuration.DISABLE_AUTO_ESCAPING_POLICY;
recalculateAutoEscapingField();
@@ -4564,11 +4570,11 @@
autoEscRequester = key;
autoEscapingPolicy = Configuration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY;
} else {
- if (autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
- throw new ParseException(
- "auto_esc setting cannot be used when auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY.",
- exp);
- }
+ if (autoEscapingPolicy == Configuration.FORCE_AUTO_ESCAPING_POLICY) {
+ throw new ParseException(
+ forcedAutoEscapingPolicyExceptionMessage("auto_esc setting"),
+ exp);
+ }
autoEscapingPolicy = Configuration.DISABLE_AUTO_ESCAPING_POLICY;
}
recalculateAutoEscapingField();
diff --git a/src/test/java/freemarker/core/OutputFormatTest.java b/src/test/java/freemarker/core/OutputFormatTest.java
index 14d3ecf..03672c7 100644
--- a/src/test/java/freemarker/core/OutputFormatTest.java
+++ b/src/test/java/freemarker/core/OutputFormatTest.java
@@ -868,10 +868,27 @@
cfg.setOutputFormat(DummyOutputFormat.INSTANCE);
assertOutput(commonFTL, esced);
+ // TODO Should work:
+ // cfg.setOutputFormat(PlainTextOutputFormat.INSTANCE);
+ // assertOutput("<#ftl outputFormat='seldomEscaped'>" + commonFTL, esced);
+
+ cfg.setOutputFormat(HTMLOutputFormat.INSTANCE);
+ assertOutput("<#outputFormat 'seldomEscaped'>" + commonFTL + "</#outputFormat>", esced);
+
+ cfg.setOutputFormat(PlainTextOutputFormat.INSTANCE);
+ assertErrorContains("", IllegalArgumentException.class,
+ "plainText", "auto_escaping_policy", "force");
cfg.setOutputFormat(DummyOutputFormat.INSTANCE);
- assertErrorContains("<#outputformat 'plainText'></#outputformat>", "auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY");
- assertErrorContains("<#noAutoEsc></#noAutoEsc>", "auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY");
- assertErrorContains("<#assign foo='bar'>${foo?noEsc}", "auto_escaping_policy is FORCE_AUTO_ESCAPING_POLICY");
+ assertErrorContains("<#outputformat 'plainText'></#outputformat>", ParseException.class,
+ "plainText", "auto_escaping_policy", "force");
+ assertErrorContains("<#noAutoEsc></#noAutoEsc>", ParseException.class,
+ "noAutoEsc", "auto_escaping_policy", "force");
+ assertErrorContains("<#noautoesc></#noautoesc>", ParseException.class,
+ "noautoesc", "auto_escaping_policy", "force");
+ assertErrorContains("<#assign foo='bar'>${foo?no_esc}", ParseException.class,
+ "?no_esc", "auto_escaping_policy", "force");
+ assertErrorContains("<#assign foo='bar'>${foo?noEsc}", ParseException.class,
+ "?noEsc", "auto_escaping_policy", "force");
}
@Test