Better error message when <#assign x++> and such fails because x doesn't exist in the same scope as the target scope.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/470971a2 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/470971a2 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/470971a2 Branch: refs/heads/2.3 Commit: 470971a2381fceee421337a7a5070d500c2b0d4a Parents: afccb10 Author: ddekany <ddek...@apache.org> Authored: Tue Mar 20 18:55:31 2018 +0100 Committer: ddekany <ddek...@apache.org> Committed: Tue Mar 20 18:55:31 2018 +0100 ---------------------------------------------------------------------- src/main/java/freemarker/core/Assignment.java | 13 +++++++++++-- .../freemarker/core/InvalidReferenceException.java | 6 +++--- .../java/freemarker/core/MiscErrorMessagesTest.java | 7 +++++++ 3 files changed, 21 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/470971a2/src/main/java/freemarker/core/Assignment.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/Assignment.java b/src/main/java/freemarker/core/Assignment.java index 0f15112..0495f14 100644 --- a/src/main/java/freemarker/core/Assignment.java +++ b/src/main/java/freemarker/core/Assignment.java @@ -152,7 +152,7 @@ final class Assignment extends TemplateElement { if (env.isClassicCompatible()) { lhoValue = TemplateScalarModel.EMPTY_STRING; } else { - throw InvalidReferenceException.getInstance( + throw InvalidReferenceException.getInstance(scope, variableName, getOperatorTypeAsString(), env); } } @@ -171,7 +171,7 @@ final class Assignment extends TemplateElement { if (lhoValue instanceof TemplateNumberModel) { lhoNumber = EvalUtil.modelToNumber((TemplateNumberModel) lhoValue, null); } else if (lhoValue == null) { - throw InvalidReferenceException.getInstance(variableName, getOperatorTypeAsString(), env); + throw InvalidReferenceException.getInstance(scope, variableName, getOperatorTypeAsString(), env); } else { throw new NonNumericalException(variableName, lhoValue, null, env); } @@ -292,4 +292,13 @@ final class Assignment extends TemplateElement { } } + static String scopeAsString(int scope) { + switch (scope) { + case NAMESPACE: return "template namespace"; + case LOCAL: return "local scope"; + case GLOBAL: return "global scope"; + default: throw new AssertionError("Unsupported scope: " + scope); + } + } + } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/470971a2/src/main/java/freemarker/core/InvalidReferenceException.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/InvalidReferenceException.java b/src/main/java/freemarker/core/InvalidReferenceException.java index 791263b..d6a75bf 100644 --- a/src/main/java/freemarker/core/InvalidReferenceException.java +++ b/src/main/java/freemarker/core/InvalidReferenceException.java @@ -141,7 +141,7 @@ public class InvalidReferenceException extends TemplateException { /** * Used for assignments that use operators like {@code +=}, when the target variable was null/missing. */ - static InvalidReferenceException getInstance(String missingAssignedVarName, String assignmentOperator, + static InvalidReferenceException getInstance(int scope, String missingAssignedVarName, String assignmentOperator, Environment env) { if (env != null && env.getFastInvalidReferenceExceptions()) { return FAST_INSTANCE; @@ -149,8 +149,8 @@ public class InvalidReferenceException extends TemplateException { final _ErrorDescriptionBuilder errDescBuilder = new _ErrorDescriptionBuilder( "The target variable of the assignment, ", new _DelayedJQuote(missingAssignedVarName), - ", was null or missing, but the \"", - assignmentOperator, "\" operator needs to get its value before assigning to it." + ", was null or missing in the " + Assignment.scopeAsString(scope) + ", and the \"", + assignmentOperator, "\" operator must get its value from there before assigning to it." ); if (missingAssignedVarName.startsWith("$")) { errDescBuilder.tips(TIP_NO_DOLLAR, TIP_MISSING_ASSIGNMENT_TARGET); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/470971a2/src/test/java/freemarker/core/MiscErrorMessagesTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/core/MiscErrorMessagesTest.java b/src/test/java/freemarker/core/MiscErrorMessagesTest.java index 5799c12..df10fde 100644 --- a/src/test/java/freemarker/core/MiscErrorMessagesTest.java +++ b/src/test/java/freemarker/core/MiscErrorMessagesTest.java @@ -56,4 +56,11 @@ public class MiscErrorMessagesTest extends TemplateTest { assertEquals((Integer) 2, ((TemplateException) e).getLineNumber()); } + @Test + public void incrementalAssignmentsTest() throws Exception { + assertErrorContains("<#assign x++>", "\"x\"", "++", "template namespace"); + assertErrorContains("<#global x += 2>", "\"x\"", "+=", "global scope"); + assertErrorContains("<#macro m><#local x--></#macro><@m/>", "\"x\"", "--", "local scope"); + } + }