You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/09/16 09:45:31 UTC
[groovy] 05/05: GROOVY-9739: check knownFields for accessedVariable
is FieldNode case (closes #1369)
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 4409282ee9cd0ef9504c9f62cdc9a7e8ff367718
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Sep 15 12:14:41 2020 -0500
GROOVY-9739: check knownFields for accessedVariable is FieldNode case (closes #1369)
- refactor to reduce repeated field helper getter call transformation
---
.../transform/trait/TraitReceiverTransformer.java | 109 ++++++++-------------
.../traitx/TraitASTTransformationTest.groovy | 31 ++++++
2 files changed, 71 insertions(+), 69 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
index ebb8947..0d40134 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
@@ -39,13 +39,13 @@ import org.codehaus.groovy.ast.expr.FieldExpression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.SyntaxException;
import org.codehaus.groovy.syntax.Token;
+import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.List;
@@ -104,48 +104,38 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
StaticMethodCallExpression call = (StaticMethodCallExpression) exp;
ClassNode ownerType = call.getOwnerType();
if (traitClass.equals(ownerType)) {
- MethodCallExpression result = callX(
+ MethodCallExpression mce = callX(
varX(weaved),
call.getMethod(),
transform(call.getArguments())
);
- result.setSafe(false);
- result.setSpreadSafe(false);
- result.setImplicitThis(false);
- result.setSourcePosition(exp);
- return result;
+ mce.setSafe(false);
+ mce.setSpreadSafe(false);
+ mce.setImplicitThis(false);
+ mce.setSourcePosition(exp);
+ return mce;
}
} else if (exp instanceof MethodCallExpression) {
- MethodCallExpression call = (MethodCallExpression) exp;
- Expression obj = call.getObjectExpression();
- if (call.isImplicitThis() || "this".equals(obj.getText())) {
- return transformMethodCallOnThis(call);
- } else if ("super".equals(obj.getText())) {
- return transformSuperMethodCall(call);
+ MethodCallExpression mce = (MethodCallExpression) exp;
+ String obj = mce.getObjectExpression().getText();
+ if (mce.isImplicitThis() || "this".equals(obj)) {
+ return transformMethodCallOnThis(mce);
+ } else if ("super".equals(obj)) {
+ return transformSuperMethodCall(mce);
}
} else if (exp instanceof FieldExpression) {
- return transformFieldExpression((FieldExpression) exp);
+ FieldNode fn = ((FieldExpression) exp).getField();
+ return transformFieldReference(exp, fn, fn.isStatic());
} else if (exp instanceof VariableExpression) {
VariableExpression vexp = (VariableExpression) exp;
Variable accessedVariable = vexp.getAccessedVariable();
- if (accessedVariable instanceof FieldNode) {
- FieldNode fn = (FieldNode) accessedVariable;
- Expression receiver = createFieldHelperReceiver();
- boolean isStatic = fn.isStatic();
- if (isStatic) {
- receiver = createStaticReceiver(receiver);
- }
- MethodCallExpression mce = callX(receiver, Traits.helperGetterName(fn));
- mce.setImplicitThis(false);
- mce.setSourcePosition(exp);
- markDynamicCall(mce, fn, isStatic);
- return mce;
- } else if (accessedVariable instanceof PropertyNode) {
- String propName = vexp.getName();
- if (knownFields.contains(propName)) {
- return createFieldHelperCall(exp, weavedType, propName);
+ if (accessedVariable instanceof FieldNode || accessedVariable instanceof PropertyNode) {
+ if (knownFields.contains(vexp.getName())) {
+ boolean isStatic = Modifier.isStatic(accessedVariable.getModifiers());
+ return transformFieldReference(exp, accessedVariable instanceof FieldNode
+ ? (FieldNode) accessedVariable : ((PropertyNode) accessedVariable).getField(), isStatic);
} else {
- PropertyExpression propertyExpression = propX(varX(weaved), propName);
+ PropertyExpression propertyExpression = propX(varX(weaved), vexp.getName());
propertyExpression.getProperty().setSourcePosition(exp);
return propertyExpression;
}
@@ -164,11 +154,12 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
}
} else if (exp instanceof PropertyExpression) {
PropertyExpression pexp = (PropertyExpression) exp;
- Expression objectExpression = pexp.getObjectExpression();
- if (pexp.isImplicitThis() || "this".equals(objectExpression.getText())) {
+ String obj = pexp.getObjectExpression().getText();
+ if (pexp.isImplicitThis() || "this".equals(obj)) {
String propName = pexp.getPropertyAsString();
if (knownFields.contains(propName)) {
- return createFieldHelperCall(exp, weavedType, propName);
+ FieldNode fn = new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null);
+ return transformFieldReference(exp, fn, false);
}
}
} else if (exp instanceof ClosureExpression) {
@@ -194,23 +185,6 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
return super.transform(exp);
}
- private Expression createFieldHelperCall(final Expression exp, final ClassNode weavedType, final String propName) {
- String method = Traits.helperGetterName(new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null));
- MethodCallExpression mce = callX(createFieldHelperReceiver(), method);
- mce.setImplicitThis(false);
- mce.setSourcePosition(exp instanceof PropertyExpression ? ((PropertyExpression) exp).getProperty() : exp);
- return mce;
- }
-
- private Expression transformFieldExpression(final FieldExpression exp) {
- FieldNode field = exp.getField();
- MethodCallExpression mce = callX(createFieldHelperReceiver(), Traits.helperGetterName(field));
- mce.setSourcePosition(exp);
- mce.setImplicitThis(false);
- markDynamicCall(mce, field, field.isStatic());
- return mce;
- }
-
private Expression transformBinaryExpression(final BinaryExpression exp, final ClassNode weavedType) {
Expression leftExpression = exp.getLeftExpression();
Expression rightExpression = exp.getRightExpression();
@@ -227,7 +201,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
leftFieldName = ((PropertyExpression) leftExpression).getPropertyAsString();
FieldNode fn = tryGetFieldNode(weavedType, leftFieldName);
if (fieldHelper == null || fn == null && !fieldHelper.hasPossibleMethod(Traits.helperSetterName(new FieldNode(leftFieldName, 0, ClassHelper.OBJECT_TYPE, weavedType, null)), rightExpression)) {
- return createAssignmentToField(rightExpression, operation, leftFieldName);
+ return binX(propX(varX(weaved), leftFieldName), operation, transform(rightExpression));
}
}
if (leftFieldName != null) {
@@ -247,8 +221,8 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
method,
args(super.transform(rightExpression))
);
- mce.setSourcePosition(exp);
mce.setImplicitThis(false);
+ mce.setSourcePosition(exp);
markDynamicCall(mce, staticField, isStatic);
return mce;
}
@@ -262,27 +236,24 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
return ret;
}
- private static void markDynamicCall(final MethodCallExpression mce, final FieldNode fn, final boolean isStatic) {
+ private Expression transformFieldReference(final Expression exp, final FieldNode fn, final boolean isStatic) {
+ Expression receiver = createFieldHelperReceiver();
if (isStatic) {
- mce.putNodeMetaData(TraitASTTransformation.DO_DYNAMIC, fn.getOriginType());
+ Expression isClass = binX(receiver, INSTANCEOF, classX(ClassHelper.CLASS_Type));
+ receiver = ternaryX(isClass, receiver, callX(receiver, "getClass"));
}
- }
- private TernaryExpression createStaticReceiver(final Expression receiver) {
- return ternaryX(
- binX(receiver, INSTANCEOF, classX(ClassHelper.CLASS_Type)),
- receiver,
- callX(createFieldHelperReceiver(), "getClass")
- );
+ MethodCallExpression mce = callX(receiver, Traits.helperGetterName(fn));
+ mce.setImplicitThis(false);
+ mce.setSourcePosition(exp);
+ markDynamicCall(mce, fn, isStatic);
+ return mce;
}
- private BinaryExpression createAssignmentToField(final Expression rightExpression,
- final Token operation, final String fieldName) {
- return binX(
- propX(varX(weaved), fieldName),
- operation,
- transform(rightExpression)
- );
+ private static void markDynamicCall(final MethodCallExpression mce, final FieldNode fn, final boolean isStatic) {
+ if (isStatic) {
+ mce.putNodeMetaData(TraitASTTransformation.DO_DYNAMIC, fn.getOriginType());
+ }
}
private static FieldNode tryGetFieldNode(final ClassNode weavedType, final String fieldName) {
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index 934eaf4..7a359f4 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -1733,6 +1733,37 @@ final class TraitASTTransformationTest {
'''
}
+ @Test // GROOVY-9739
+ void testTraitExtendsTraitWithDelegate() {
+ assertScript '''
+ class Main implements ClientSupport {
+ static main(args) {
+ def tester = new Main(client: new Client())
+
+ assert tester.isReady()
+ assert tester.client.getValue() == 'works'
+ }
+ }
+
+ class Client {
+ def getValue() { 'works' }
+ boolean waitForServer(int seconds) { true }
+ }
+
+ trait ClientDelegate {
+ @Delegate Client client
+ }
+
+ trait ClientSupport implements ClientDelegate {
+ boolean isReady() {
+ boolean ready = client.waitForServer(60)
+ // assert, log, etc.
+ return ready
+ }
+ }
+ '''
+ }
+
@Test
void testAnnotationShouldBeCarriedOver() {
assertScript '''