This is an automated email from the ASF dual-hosted git repository.
ddekany pushed a commit to branch FREEMARKER-183
in repository https://gitbox.apache.org/repos/asf/freemarker.git
The following commit(s) were added to refs/heads/FREEMARKER-183 by this push:
new 44b8c4a6 FREEMARKER-183 continued: Some code and javadoc cleanup
44b8c4a6 is described below
commit 44b8c4a68567a426bff6a1dce69412b4e9eb27a7
Author: ddekany <[email protected]>
AuthorDate: Sun Feb 18 01:53:55 2024 +0100
FREEMARKER-183 continued: Some code and javadoc cleanup
---
.../src/main/java/freemarker/core/Dot.java | 6 +-
.../java/freemarker/core/DotBeforeMethodCall.java | 4 +-
.../main/java/freemarker/ext/beans/BeanModel.java | 46 +++---
.../java/freemarker/ext/beans/BeansWrapper.java | 6 +-
.../freemarker/ext/beans/ClassIntrospector.java | 10 +-
.../ext/beans/FastPropertyDescriptor.java | 3 +-
.../ext/beans/ZeroArgumentNonVoidMethodPolicy.java | 4 +-
.../template/MethodCallAwareTemplateHashModel.java | 7 +-
.../beans/TestZeroArgumentNonVoidMethodPolicy.java | 164 ++++++++++++---------
9 files changed, 129 insertions(+), 121 deletions(-)
diff --git a/freemarker-core/src/main/java/freemarker/core/Dot.java
b/freemarker-core/src/main/java/freemarker/core/Dot.java
index f360a955..a2d2f27b 100644
--- a/freemarker-core/src/main/java/freemarker/core/Dot.java
+++ b/freemarker-core/src/main/java/freemarker/core/Dot.java
@@ -29,7 +29,7 @@ import freemarker.template.TemplateModel;
*/
class Dot extends Expression {
private final Expression target;
- private final String key;
+ protected final String key;
Dot(Expression target, String key) {
this.target = target;
@@ -61,10 +61,6 @@ class Dot extends Expression {
return leftModel.get(key);
}
- String getKey() {
- return key;
- }
-
@Override
public String getCanonicalForm() {
return target.getCanonicalForm() + getNodeTypeSymbol() +
_CoreStringUtils.toFTLIdentifierReferenceAfterDot(key);
diff --git
a/freemarker-core/src/main/java/freemarker/core/DotBeforeMethodCall.java
b/freemarker-core/src/main/java/freemarker/core/DotBeforeMethodCall.java
index c842c7d6..17ae026c 100644
--- a/freemarker-core/src/main/java/freemarker/core/DotBeforeMethodCall.java
+++ b/freemarker-core/src/main/java/freemarker/core/DotBeforeMethodCall.java
@@ -20,8 +20,8 @@
package freemarker.core;
import freemarker.ext.beans.BeansWrapper;
-import freemarker.template.MethodCallAwareTemplateHashModel;
import freemarker.ext.beans.ZeroArgumentNonVoidMethodPolicy;
+import freemarker.template.MethodCallAwareTemplateHashModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateModel;
@@ -43,7 +43,7 @@ class DotBeforeMethodCall extends Dot {
protected TemplateModel evalOnHash(TemplateHashModel leftModel) throws
TemplateException {
if (leftModel instanceof MethodCallAwareTemplateHashModel) {
try {
- return ((MethodCallAwareTemplateHashModel)
leftModel).getBeforeMethodCall(getKey());
+ return ((MethodCallAwareTemplateHashModel)
leftModel).getBeforeMethodCall(key);
} catch
(MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException e) {
String hint = e.getHint();
throw new NonMethodException(
diff --git a/freemarker-core/src/main/java/freemarker/ext/beans/BeanModel.java
b/freemarker-core/src/main/java/freemarker/ext/beans/BeanModel.java
index fd92bab8..c983ae03 100644
--- a/freemarker-core/src/main/java/freemarker/ext/beans/BeanModel.java
+++ b/freemarker-core/src/main/java/freemarker/ext/beans/BeanModel.java
@@ -158,27 +158,6 @@ implements TemplateHashModelEx, AdapterTemplateModel,
WrapperTemplateModel, Temp
}
}
- /**
- * Can be overridden to be public, to implement {@link
MethodCallAwareTemplateHashModel}. We don't implement that
- * in {@link BeanModel} for backward compatibility, but the functionality
is present. If you expose this method by
- * implementing {@link MethodCallAwareTemplateHashModel}, then be sure
that {@link #get(String)} is
- * not overridden in custom subclasses; if it is, then those subclasses
should be modernized to override
- * {@link #get(String, boolean)} instead.
- *
- * @since 2.3.33
- */
- protected TemplateModel getBeforeMethodCall(String key)
- throws TemplateModelException,
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException {
- TemplateModel result = get(key, true);
- if (result instanceof TemplateMethodModelEx) {
- return (TemplateMethodModelEx) result;
- }
- if (result == null) {
- return null;
- }
- throw new
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException(result, null);
- }
-
/**
* Override this if you want to customize the behavior of {@link
#get(String)}.
* In standard implementations at least, this is what {@link
#get(String)}, and
@@ -200,11 +179,11 @@ implements TemplateHashModelEx, AdapterTemplateModel,
WrapperTemplateModel, Temp
// instead, as this class didn't exist before 2.3.33. So with
incompatibleImprovements before that, that should be
// the only place where this gets called, or else the behavior of the
model will be inconsistent.
protected TemplateModel get(String key, boolean beforeMethodCall)
- throws TemplateModelException,
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException {
+ throws TemplateModelException,
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException {
Class<?> clazz = object.getClass();
Map<Object, Object> classInfo =
wrapper.getClassIntrospector().get(clazz);
TemplateModel retval = null;
-
+
try {
if (wrapper.isMethodsShadowItems()) {
Object fd = classInfo.get(key);
@@ -242,9 +221,6 @@ implements TemplateHashModelEx, AdapterTemplateModel,
WrapperTemplateModel, Temp
} catch (TemplateModelException |
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException e) {
throw e;
} catch (Exception e) {
- if (beforeMethodCall && e instanceof
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException) {
- throw
(MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException) e;
- }
throw new _TemplateModelException(e,
"An error has occurred when reading existing sub-variable
", new _DelayedJQuote(key),
"; see cause exception! The type of the containing value
was: ",
@@ -253,6 +229,24 @@ implements TemplateHashModelEx, AdapterTemplateModel,
WrapperTemplateModel, Temp
}
}
+ /**
+ * Can be overridden to be public, to implement {@link
MethodCallAwareTemplateHashModel}. We don't implement that
+ * in {@link BeanModel} for backward compatibility, but the functionality
is present. If you expose this method by
+ * implementing {@link MethodCallAwareTemplateHashModel}, then be sure
that {@link #get(String)} is
+ * not overridden in custom subclasses; if it is, then those subclasses
should be modernized to override
+ * {@link #get(String, boolean)} instead.
+ *
+ * @since 2.3.33
+ */
+ protected TemplateModel getBeforeMethodCall(String key)
+ throws TemplateModelException,
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException {
+ TemplateModel result = get(key, true);
+ if (result instanceof TemplateMethodModelEx || result == null) {
+ return result;
+ }
+ throw new
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException(result, null);
+ }
+
private void logNoSuchKey(String key, Map<?, ?> keyMap) {
LOG.debug("Key " + StringUtil.jQuoteNoXSS(key) + " was not found on
instance of " +
object.getClass().getName() + ". Introspection information for " +
diff --git
a/freemarker-core/src/main/java/freemarker/ext/beans/BeansWrapper.java
b/freemarker-core/src/main/java/freemarker/ext/beans/BeansWrapper.java
index 0fbf3561..0e202662 100644
--- a/freemarker-core/src/main/java/freemarker/ext/beans/BeansWrapper.java
+++ b/freemarker-core/src/main/java/freemarker/ext/beans/BeansWrapper.java
@@ -267,7 +267,7 @@ public class BeansWrapper implements RichObjectWrapper,
WriteProtectable {
* <li>
* <p>2.3.33 (or higher):
* The default of {@link
BeansWrapper#setRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy)}
- * has changes to {@link
ZeroArgumentNonVoidMethodPolicy#BOTH_PROPERTY_AND_METHOD}, from
+ * has changed to {@link
ZeroArgumentNonVoidMethodPolicy#BOTH_PROPERTY_AND_METHOD}, from
* {@link ZeroArgumentNonVoidMethodPolicy#METHOD_ONLY}. This means
that Java records public methods with
* 0-arguments and non-void return type are now exposed both as
properties, and as methods, while earlier they
* were only exposed as methods. That is, if in a record you have
{@code public String name()}, now in
@@ -667,8 +667,8 @@ public class BeansWrapper implements RichObjectWrapper,
WriteProtectable {
/**
* Sets the {@link ZeroArgumentNonVoidMethodPolicy} for classes that are
Java records; if the
* {@code BeansWrapper#BeansWrapper(Version) incompatibleImprovements} of
the object wrapper is at least 2.3.33,
- * then it defaults to {@link
ZeroArgumentNonVoidMethodPolicy#BOTH_PROPERTY_AND_METHOD}, otherwise it
defaults to
- * {@link ZeroArgumentNonVoidMethodPolicy#METHOD_ONLY}.
+ * then this defaults to {@link
ZeroArgumentNonVoidMethodPolicy#BOTH_PROPERTY_AND_METHOD}, otherwise this
defaults
+ * to {@link ZeroArgumentNonVoidMethodPolicy#METHOD_ONLY}.
*
* <p>Note that methods in this class are inherited by {@link
DefaultObjectWrapper}, which is what you normally use.
*
diff --git
a/freemarker-core/src/main/java/freemarker/ext/beans/ClassIntrospector.java
b/freemarker-core/src/main/java/freemarker/ext/beans/ClassIntrospector.java
index 81f4ffe0..bc4a5ddd 100644
--- a/freemarker-core/src/main/java/freemarker/ext/beans/ClassIntrospector.java
+++ b/freemarker-core/src/main/java/freemarker/ext/beans/ClassIntrospector.java
@@ -350,7 +350,7 @@ class ClassIntrospector {
// For real Java Beans properties only, used to exclude them from
creating fake properties based on ZeroArgumentNonVoidMethod.
Set<String> beanPropertyReadMethodNameCollector =
zeroArgumentNonVoidMethodPolicy != ZeroArgumentNonVoidMethodPolicy.METHOD_ONLY
- ? new HashSet<String>()
+ ? new HashSet<>()
: null;
List<PropertyDescriptor> pdas = getPropertyDescriptors(beanInfo,
clazz);
@@ -443,11 +443,9 @@ class ClassIntrospector {
private static ZeroArgumentNonVoidMethodPolicy
getAppliedZeroArgumentNonVoidMethodPolicy(Method method, Set<String>
beanPropertyReadMethodNameCollector, ZeroArgumentNonVoidMethodPolicy
zeroArgumentNonVoidMethodPolicy) {
if (method.getParameterCount() == 0 && method.getReturnType() !=
void.class) {
- if (beanPropertyReadMethodNameCollector != null &&
beanPropertyReadMethodNameCollector.contains(method.getName())) {
- return ZeroArgumentNonVoidMethodPolicy.METHOD_ONLY;
- } else {
- return zeroArgumentNonVoidMethodPolicy;
- }
+ return beanPropertyReadMethodNameCollector != null &&
beanPropertyReadMethodNameCollector.contains(method.getName())
+ ? ZeroArgumentNonVoidMethodPolicy.METHOD_ONLY
+ : zeroArgumentNonVoidMethodPolicy;
} else {
return null;
}
diff --git
a/freemarker-core/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java
b/freemarker-core/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java
index 7ae8b674..d66f06d2 100644
---
a/freemarker-core/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java
+++
b/freemarker-core/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java
@@ -23,6 +23,7 @@ import java.lang.reflect.Method;
/**
* Used instead of {@link PropertyDescriptor}, because the methods of that are
synchronized.
+ * Also, we use this for "fake" Java Beans properties too (see {@link
BeansWrapper.MethodAppearanceDecision}).
*
* @since 2.3.27
*/
@@ -48,7 +49,7 @@ final class FastPropertyDescriptor {
/**
* If this is true, and the property value is referred directly before
it's called in a template, then
- * the instead of the property value, it the value should be the read
method (which therefore will be called).
+ * instead of the property value, the value should be the read method.
*
* @since 2.3.33
*/
diff --git
a/freemarker-core/src/main/java/freemarker/ext/beans/ZeroArgumentNonVoidMethodPolicy.java
b/freemarker-core/src/main/java/freemarker/ext/beans/ZeroArgumentNonVoidMethodPolicy.java
index 85f2390a..add78f0b 100644
---
a/freemarker-core/src/main/java/freemarker/ext/beans/ZeroArgumentNonVoidMethodPolicy.java
+++
b/freemarker-core/src/main/java/freemarker/ext/beans/ZeroArgumentNonVoidMethodPolicy.java
@@ -25,7 +25,7 @@ import freemarker.template.DefaultObjectWrapper;
* How to show 0 argument non-void public methods to templates, which are not
standard Java Beans read methods.
* Used in {@link BeansWrapper}, and therefore in {@link DefaultObjectWrapper}.
* This policy doesn't apply to methods that Java Beans introspector discovers
as a property read method (which
- * typically look like {@code getSomething()}/{@code getSomething()}). It's
only applicable to methods like
+ * typically look like {@code getSomething()}, or {@code isSomething()}). It's
only applicable to methods like
* {@code something()}, including the component read methods of Java records.
*
* @see
BeansWrapperConfiguration#setNonRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy)
@@ -46,7 +46,7 @@ public enum ZeroArgumentNonVoidMethodPolicy {
* {@code SomeType getSomething()} spreads in the Java ecosystem (and is a
standard in some other JVM languages),
* and thus we can't tell anymore if {@code SomeType something()} just
reads a value, and hence should be accessed
* like {@code obj.something}, or it's more like an operation that has
side effect, and therefore should be
- * accessed like {@code obj.something()}. So with be allowing both, the
template author is free to decide which is
+ * accessed like {@code obj.something()}. So with allowing both, the
template author is free to decide which is
* the more fitting. Also, for accessing Java records components, the
proper way is {@code obj.something}, but
* before FreeMarker was aware of records (and hence that those methods
are like property read methods), the
* only way that worked was {@code obj.something()}, so to be more
backward compatible, we have to support both.
diff --git
a/freemarker-core/src/main/java/freemarker/template/MethodCallAwareTemplateHashModel.java
b/freemarker-core/src/main/java/freemarker/template/MethodCallAwareTemplateHashModel.java
index 6c4912e2..a3e80560 100644
---
a/freemarker-core/src/main/java/freemarker/template/MethodCallAwareTemplateHashModel.java
+++
b/freemarker-core/src/main/java/freemarker/template/MethodCallAwareTemplateHashModel.java
@@ -29,9 +29,10 @@ import freemarker.ext.beans.ZeroArgumentNonVoidMethodPolicy;
import freemarker.template.utility.NullArgumentException;
/**
- * Adds a getter method to {@link TemplateHashModel}, that can return
different result than {@link #get(String)},
+ * Adds an extra getter method to {@link TemplateHashModel} that can return
different result than {@link #get(String)},
* knowing that the result of it will be called as a method. At least as of
2.3.33, this is only utilized by the
- * template language for 0-argument method calls directly after the dot
operator and the key. For example, if in the
+ * template language for 0-argument non-void method calls directly after the
dot operator and the key (like
+ * {@code obj.m()}), or for the equivalent with square brackets ({@code
obj["m"]()}). For example, if in the
* template you have {@code someRecord.someComponent()}, and there {@code
someRecord} was wrapped by the
* {@link ObjectWrapper} into a {@link TemplateHashModel} that also implements
this interface, then the dot operator
* will call {@link #getBeforeMethodCall(String)
getBeforeMethodCall("someComponent")}, rather than
@@ -39,7 +40,7 @@ import freemarker.template.utility.NullArgumentException;
* {@link
BeansWrapper.MethodAppearanceDecision#setMethodInsteadOfPropertyValueBeforeCall(boolean)},
* which is needed to implement {@link
ZeroArgumentNonVoidMethodPolicy#BOTH_PROPERTY_AND_METHOD}.
*
- * <p>While technically we could do the same for method calls with more the 0
arguments, as of 2.3.33 at least we
+ * <p>While technically we could do the same for method calls with more the 0
arguments, as of 2.3.33 at least, we
* don't want to generalize this to that case. The FreeMarker 2.x template
language doesn't have separated namespace for
* methods, so this is already a hack as is, but we had to address the issue
with Java records (see that at
* {@link
BeansWrapper.MethodAppearanceDecision#setMethodInsteadOfPropertyValueBeforeCall(boolean)}).
diff --git
a/freemarker-core16/src/test/java/freemarker/ext/beans/TestZeroArgumentNonVoidMethodPolicy.java
b/freemarker-core16/src/test/java/freemarker/ext/beans/TestZeroArgumentNonVoidMethodPolicy.java
index 56b80d53..ee834f88 100644
---
a/freemarker-core16/src/test/java/freemarker/ext/beans/TestZeroArgumentNonVoidMethodPolicy.java
+++
b/freemarker-core16/src/test/java/freemarker/ext/beans/TestZeroArgumentNonVoidMethodPolicy.java
@@ -37,20 +37,12 @@ import freemarker.template.TemplateException;
import freemarker.test.TemplateTest;
public class TestZeroArgumentNonVoidMethodPolicy extends TemplateTest {
- private static final Pattern DOT_REPLACE_PATTERN =
Pattern.compile("\\.(\\w+)");
-
- private static String withDotOrSquareBracket(String s, boolean dot) {
- if (dot) {
- return s;
- }
- return DOT_REPLACE_PATTERN.matcher(s).replaceFirst(key -> "['" +
key.group(1) + "']");
- }
-
@Override
protected Configuration createConfiguration() throws Exception {
Configuration cfg = super.createConfiguration();
// Don't use default, as then the object wrapper is a shared static
mutable object:
cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_32);
+ cfg.setAPIBuiltinEnabled(true);
return cfg;
}
@@ -174,104 +166,104 @@ public class TestZeroArgumentNonVoidMethodPolicy
extends TemplateTest {
}
private void assertRecIsBothPropertyAndMethod() throws IOException,
TemplateException {
- for (boolean dot : List.of(true, false)) {
- assertOutput(withDotOrSquareBracket("${rec.x}", dot), "1");
- assertOutput(withDotOrSquareBracket("${rec.x()}", dot), "1");
- assertOutput(withDotOrSquareBracket("${rec.s}", dot), "S");
- assertOutput(withDotOrSquareBracket("${rec.s()}", dot), "S");
- assertOutput(withDotOrSquareBracket("${rec.y}", dot), "2");
- assertOutput(withDotOrSquareBracket("${rec.y()}", dot), "2");
- assertOutput(withDotOrSquareBracket("${rec.tenX}", dot), "10");
- assertOutput(withDotOrSquareBracket("${rec.tenX()}", dot), "10");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertOutput(modifyTemplate("${rec.x}", tempMods), "1");
+ assertOutput(modifyTemplate("${rec.x()}", tempMods), "1");
+ assertOutput(modifyTemplate("${rec.s}", tempMods), "S");
+ assertOutput(modifyTemplate("${rec.s()}", tempMods), "S");
+ assertOutput(modifyTemplate("${rec.y}", tempMods), "2");
+ assertOutput(modifyTemplate("${rec.y()}", tempMods), "2");
+ assertOutput(modifyTemplate("${rec.tenX}", tempMods), "10");
+ assertOutput(modifyTemplate("${rec.tenX()}", tempMods), "10");
}
assertRecPolicyIndependentMembers();
}
private void assertRecIsMethodOnly() throws IOException, TemplateException
{
- for (boolean dot : List.of(true, false)) {
- assertErrorContains(withDotOrSquareBracket("${rec.x}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${rec.x()}", dot), "1");
- assertErrorContains(withDotOrSquareBracket("${rec.s}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${rec.s()}", dot), "S");
- assertErrorContains(withDotOrSquareBracket("${rec.y}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${rec.y()}", dot), "2");
- assertErrorContains(withDotOrSquareBracket("${rec.tenX}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${rec.tenX()}", dot), "10");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertErrorContains(modifyTemplate("${rec.x}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${rec.x()}", tempMods), "1");
+ assertErrorContains(modifyTemplate("${rec.s}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${rec.s()}", tempMods), "S");
+ assertErrorContains(modifyTemplate("${rec.y}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${rec.y()}", tempMods), "2");
+ assertErrorContains(modifyTemplate("${rec.tenX}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${rec.tenX()}", tempMods), "10");
}
assertRecPolicyIndependentMembers();
}
private void assertRecIsPropertyOnly() throws IOException,
TemplateException {
- for (boolean dot : List.of(true, false)) {
- assertOutput(withDotOrSquareBracket("${rec.x}", dot), "1");
- assertErrorContains(withDotOrSquareBracket("${rec.x()}", dot),
"SimpleNumber", "must not be called as a method");
- assertOutput(withDotOrSquareBracket("${rec.s}", dot), "S");
- assertErrorContains(withDotOrSquareBracket("${rec.s()}", dot),
"SimpleScalar");
- assertOutput(withDotOrSquareBracket("${rec.y}", dot), "2");
- assertErrorContains(withDotOrSquareBracket("${rec.y()}", dot),
"SimpleNumber");
- assertOutput(withDotOrSquareBracket("${rec.tenX}", dot), "10");
- assertErrorContains(withDotOrSquareBracket("${rec.tenX()}", dot),
"SimpleNumber");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertOutput(modifyTemplate("${rec.x}", tempMods), "1");
+ assertErrorContains(modifyTemplate("${rec.x()}", tempMods),
"SimpleNumber", "must not be called as a method");
+ assertOutput(modifyTemplate("${rec.s}", tempMods), "S");
+ assertErrorContains(modifyTemplate("${rec.s()}", tempMods),
"SimpleScalar");
+ assertOutput(modifyTemplate("${rec.y}", tempMods), "2");
+ assertErrorContains(modifyTemplate("${rec.y()}", tempMods),
"SimpleNumber");
+ assertOutput(modifyTemplate("${rec.tenX}", tempMods), "10");
+ assertErrorContains(modifyTemplate("${rec.tenX()}", tempMods),
"SimpleNumber");
}
assertRecPolicyIndependentMembers();
}
private void assertRecPolicyIndependentMembers() throws IOException,
TemplateException {
- for (boolean dot : List.of(true, false)) {
- assertOutput(withDotOrSquareBracket("${rec.z}", dot), "3");
- assertErrorContains(withDotOrSquareBracket("${rec.z()}", dot),
"SimpleNumber");
- assertOutput(withDotOrSquareBracket("${rec.getZ()}", dot), "3");
- assertOutput(withDotOrSquareBracket("${rec.xTimes(5)}", dot), "5");
- assertErrorContains(withDotOrSquareBracket("${rec.xTimes}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${rec.voidMethod()}", dot),
"");
- assertErrorContains(withDotOrSquareBracket("${rec.voidMethod}",
dot), "SimpleMethodModel");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertOutput(modifyTemplate("${rec.z}", tempMods), "3");
+ assertErrorContains(modifyTemplate("${rec.z()}", tempMods),
"SimpleNumber");
+ assertOutput(modifyTemplate("${rec.getZ()}", tempMods), "3");
+ assertOutput(modifyTemplate("${rec.xTimes(5)}", tempMods), "5");
+ assertErrorContains(modifyTemplate("${rec.xTimes}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${rec.voidMethod()}", tempMods), "");
+ assertErrorContains(modifyTemplate("${rec.voidMethod}", tempMods),
"SimpleMethodModel");
}
}
private void assertNrcIsMethodOnly() throws IOException, TemplateException
{
- for (boolean dot : List.of(true, false)) {
- assertErrorContains(withDotOrSquareBracket("${nrc.x}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${nrc.x()}", dot), "1");
- assertErrorContains(withDotOrSquareBracket("${nrc.y}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${nrc.y()}", dot), "2");
- assertErrorContains(withDotOrSquareBracket("${nrc.tenX}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${nrc.tenX()}", dot), "10");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertErrorContains(modifyTemplate("${nrc.x}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${nrc.x()}", tempMods), "1");
+ assertErrorContains(modifyTemplate("${nrc.y}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${nrc.y()}", tempMods), "2");
+ assertErrorContains(modifyTemplate("${nrc.tenX}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${nrc.tenX()}", tempMods), "10");
}
assertNrcPolicyIndependentMembers();
}
private void assertNrcIsBothPropertyAndMethod() throws IOException,
TemplateException {
- for (boolean dot : List.of(true, false)) {
- assertOutput(withDotOrSquareBracket("${nrc.x}", dot), "1");
- assertOutput(withDotOrSquareBracket("${nrc.x()}", dot), "1");
- assertOutput(withDotOrSquareBracket("${nrc.y}", dot), "2");
- assertOutput(withDotOrSquareBracket("${nrc.y()}", dot), "2");
- assertOutput(withDotOrSquareBracket("${nrc.tenX}", dot), "10");
- assertOutput(withDotOrSquareBracket("${nrc.tenX()}", dot), "10");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertOutput(modifyTemplate("${nrc.x}", tempMods), "1");
+ assertOutput(modifyTemplate("${nrc.x()}", tempMods), "1");
+ assertOutput(modifyTemplate("${nrc.y}", tempMods), "2");
+ assertOutput(modifyTemplate("${nrc.y()}", tempMods), "2");
+ assertOutput(modifyTemplate("${nrc.tenX}", tempMods), "10");
+ assertOutput(modifyTemplate("${nrc.tenX()}", tempMods), "10");
}
assertNrcPolicyIndependentMembers();
}
private void assertNrcIsPropertyOnly() throws IOException,
TemplateException {
- for (boolean dot : List.of(true, false)) {
- assertOutput(withDotOrSquareBracket("${nrc.x}", dot), "1");
- assertErrorContains(withDotOrSquareBracket("${nrc.x()}", dot),
"SimpleNumber", "must not be called as a method");
- assertOutput(withDotOrSquareBracket("${nrc.y}", dot), "2");
- assertErrorContains(withDotOrSquareBracket("${nrc.y()}", dot),
"SimpleNumber");
- assertOutput(withDotOrSquareBracket("${nrc.tenX}", dot), "10");
- assertErrorContains(withDotOrSquareBracket("${nrc.tenX()}", dot),
"SimpleNumber");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertOutput(modifyTemplate("${nrc.x}", tempMods), "1");
+ assertErrorContains(modifyTemplate("${nrc.x()}", tempMods),
"SimpleNumber", "must not be called as a method");
+ assertOutput(modifyTemplate("${nrc.y}", tempMods), "2");
+ assertErrorContains(modifyTemplate("${nrc.y()}", tempMods),
"SimpleNumber");
+ assertOutput(modifyTemplate("${nrc.tenX}", tempMods), "10");
+ assertErrorContains(modifyTemplate("${nrc.tenX()}", tempMods),
"SimpleNumber");
}
assertNrcPolicyIndependentMembers();
}
private void assertNrcPolicyIndependentMembers() throws IOException,
TemplateException {
- for (boolean dot : List.of(true, false)) {
- assertOutput(withDotOrSquareBracket("${nrc.z}", dot), "3");
- assertErrorContains(withDotOrSquareBracket("${nrc.z()}", dot),
"SimpleNumber");
- assertOutput(withDotOrSquareBracket("${nrc.getZ()}", dot), "3");
- assertOutput(withDotOrSquareBracket("${nrc.xTimes(5)}", dot), "5");
- assertErrorContains(withDotOrSquareBracket("${nrc.xTimes}", dot),
"SimpleMethodModel");
- assertOutput(withDotOrSquareBracket("${nrc.voidMethod()}", dot),
"");
- assertErrorContains(withDotOrSquareBracket("${nrc.voidMethod}",
dot), "SimpleMethodModel");
+ for (TemplateModifications tempMods : TemplateModifications.values()) {
+ assertOutput(modifyTemplate("${nrc.z}", tempMods), "3");
+ assertErrorContains(modifyTemplate("${nrc.z()}", tempMods),
"SimpleNumber");
+ assertOutput(modifyTemplate("${nrc.getZ()}", tempMods), "3");
+ assertOutput(modifyTemplate("${nrc.xTimes(5)}", tempMods), "5");
+ assertErrorContains(modifyTemplate("${nrc.xTimes}", tempMods),
"SimpleMethodModel");
+ assertOutput(modifyTemplate("${nrc.voidMethod()}", tempMods), "");
+ assertErrorContains(modifyTemplate("${nrc.voidMethod}", tempMods),
"SimpleMethodModel");
}
}
@@ -349,4 +341,30 @@ public class TestZeroArgumentNonVoidMethodPolicy extends
TemplateTest {
}
}
+ private static final Pattern DOT_TO_SQUARE_BRACKETS_REPLACEMENT_PATTERN =
Pattern.compile("\\.(\\w+)");
+
+ private static String modifyTemplate(String s, TemplateModifications
tempMods) {
+ if (tempMods.useApi) {
+ s = s.replace(".", "?api.");
+ }
+ if (tempMods.doToSquareBrackets) {
+ s =
DOT_TO_SQUARE_BRACKETS_REPLACEMENT_PATTERN.matcher(s).replaceFirst(key -> "['"
+ key.group(1) + "']");
+ }
+ return s;
+ }
+
+ enum TemplateModifications {
+ DOT(true, false), SQUARE_BRACKETS(false, false),
+ API_DOT(true, true), API_SQUARE_BRACKETS(false, true);
+
+ private final boolean doToSquareBrackets;
+ private final boolean useApi;
+
+ TemplateModifications(boolean doToSquareBrackets, boolean useApi) {
+ this.doToSquareBrackets = doToSquareBrackets;
+ this.useApi = useApi;
+ }
+ }
+
+
}