You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/05/24 18:45:21 UTC
[groovy] branch GROOVY_3_0_X updated: GROOVY-10143: super trait field access
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
new d29589d143 GROOVY-10143: super trait field access
d29589d143 is described below
commit d29589d1435ce77d1bbb6de6b454cf866b03741d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue May 24 13:33:24 2022 -0500
GROOVY-10143: super trait field access
3_0_X backport
---
.../transform/trait/TraitReceiverTransformer.java | 19 +++--
.../traitx/TraitASTTransformationTest.groovy | 92 ++++++++++++++++++++++
2 files changed, 101 insertions(+), 10 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 879b7a992f..2277acbee2 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
@@ -43,6 +43,7 @@ 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 org.codehaus.groovy.syntax.Types;
import java.lang.reflect.Modifier;
import java.util.Collection;
@@ -100,8 +101,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
return transformBinaryExpression((BinaryExpression) exp, weavedType);
} else if (exp instanceof StaticMethodCallExpression) {
StaticMethodCallExpression call = (StaticMethodCallExpression) exp;
- ClassNode ownerType = call.getOwnerType();
- if (traitClass.equals(ownerType)) {
+ if (call.getOwnerType().equals(traitClass)) {
MethodCallExpression mce = callX(
varX(weaved),
call.getMethod(),
@@ -187,9 +187,8 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
Expression leftExpression = exp.getLeftExpression();
Expression rightExpression = exp.getRightExpression();
Token operation = exp.getOperation();
- if (operation.getText().equals("=")) {
+ if (operation.getType() == Types.ASSIGN) {
String leftFieldName = null;
- // it's an assignment
if (leftExpression instanceof VariableExpression && ((VariableExpression) leftExpression).getAccessedVariable() instanceof FieldNode) {
leftFieldName = ((VariableExpression) leftExpression).getAccessedVariable().getName();
} else if (leftExpression instanceof FieldExpression) {
@@ -197,14 +196,13 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
} else if (leftExpression instanceof PropertyExpression
&& (((PropertyExpression) leftExpression).isImplicitThis() || "this".equals(((PropertyExpression) leftExpression).getObjectExpression().getText()))) {
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 binX(propX(varX(weaved), leftFieldName), operation, transform(rightExpression));
- }
}
if (leftFieldName != null) {
- FieldNode fn = weavedType.getDeclaredField(leftFieldName);
FieldNode staticField = tryGetFieldNode(weavedType, leftFieldName);
+ if (fieldHelper == null || staticField == null && !fieldHelper.hasPossibleMethod(Traits.helperSetterName(new FieldNode(leftFieldName, 0, ClassHelper.OBJECT_TYPE, weavedType, null)), rightExpression)) {
+ return binX(propX(varX(weaved), leftFieldName), operation, transform(rightExpression)); // GROOVY-7342, GROOVY-7456, GROOVY-9739, GROOVY-10143, et al.
+ }
+ FieldNode fn = weavedType.getDeclaredField(leftFieldName);
if (fn == null) {
fn = new FieldNode(leftFieldName, 0, ClassHelper.OBJECT_TYPE, weavedType, null);
}
@@ -217,7 +215,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
MethodCallExpression mce = callX(
receiver,
method,
- args(super.transform(rightExpression))
+ super.transform(rightExpression)
);
mce.setImplicitThis(false);
mce.setSourcePosition(leftExpression instanceof PropertyExpression ? ((PropertyExpression) leftExpression).getProperty() : leftExpression);
@@ -225,6 +223,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
return mce;
}
}
+
Expression leftTransform = transform(leftExpression);
Expression rightTransform = transform(rightExpression);
Expression ret = exp instanceof DeclarationExpression ?
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index be886add9c..df8589a62a 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -22,6 +22,8 @@ import groovy.transform.SelfType
import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.expr.ClassExpression
import org.codehaus.groovy.ast.expr.ListExpression
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.CompilerConfiguration
import org.junit.Test
import static groovy.test.GroovyAssert.assertScript
@@ -3352,6 +3354,96 @@ final class TraitASTTransformationTest {
'''
}
+ @Test // GROOVY-10143
+ void testTraitAccessToInheritedProperty() {
+ def sourceDir = File.createTempDir()
+ def config = new CompilerConfiguration(
+ targetDirectory: File.createTempDir(),
+ jointCompilationOptions: [memStub: true]
+ )
+ try {
+ def a = new File(sourceDir, 'A.groovy')
+ a.write '''
+ abstract class A {
+ }
+ '''
+ def b = new File(sourceDir, 'B.groovy')
+ b.write '''
+ @groovy.transform.SelfType(A)
+ trait B {
+ abstract boolean booleanMethod1()
+ abstract boolean booleanMethod2()
+ abstract boolean booleanMethod3()
+ Object getManager() {
+ if (this.managerObject == null) {
+ this.managerObject = new C(this as B)
+ }
+ this.managerObject
+ }
+ C managerObject
+ }
+ '''
+ def c = new File(sourceDir, 'C.groovy')
+ c.write '''
+ class C {
+ final B base
+ C(B base) {
+ this.base = base
+ }
+ }
+ '''
+ def d = new File(sourceDir, 'D.groovy')
+ d.write '''
+ @groovy.transform.SelfType([A])
+ trait D extends B {
+ boolean booleanMethod1() {
+ true
+ }
+ boolean booleanMethod2() {
+ true
+ }
+ boolean booleanMethod3() {
+ true
+ }
+ @Override
+ Object getManager() {
+ if (managerObject == null) {
+ managerObject = new E(this as B)
+ }
+ managerObject
+ }
+ }
+ '''
+ def e = new File(sourceDir, 'E.groovy')
+ e.write '''
+ @groovy.transform.InheritConstructors
+ class E extends C {
+ String getStringValue() {
+ 'string value'
+ }
+ }
+ '''
+ def f = new File(sourceDir, 'Main.groovy')
+ f.write '''
+ class X extends A implements D {
+ }
+ def x = new X()
+ assert x.manager.base === x
+ assert x.manager.stringValue == 'string value'
+ '''
+
+ def loader = new GroovyClassLoader(this.class.classLoader)
+ def cu = new CompilationUnit(config, null, loader)
+ cu.addSources(a, b, c, d, e, f)
+ cu.compile()
+
+ loader.addClasspath(config.targetDirectory.absolutePath)
+ loader.loadClass('Main').main()
+ } finally {
+ [sourceDir, config.targetDirectory]*.deleteDir()
+ }
+ }
+
@Test // GROOVY-9386
void testTraitPropertyInitializedByTap() {
assertScript '''