This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY-11907 in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 19f38997a45ef17d77ecc5b188834e62948e07b1 Author: Eric Milles <[email protected]> AuthorDate: Wed Apr 8 13:15:05 2026 -0500 GROOVY-11907: trait field reference transform restructure --- .../transform/trait/TraitReceiverTransformer.java | 93 +++++++++------------- 1 file changed, 36 insertions(+), 57 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 99baf45201..f1f3ab30ff 100644 --- a/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java +++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java @@ -51,9 +51,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.binX; import static org.codehaus.groovy.ast.tools.GeneralUtils.callX; import static org.codehaus.groovy.ast.tools.GeneralUtils.castX; import static org.codehaus.groovy.ast.tools.GeneralUtils.classX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.isInstanceOfX; import static org.codehaus.groovy.ast.tools.GeneralUtils.propX; -import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX; import static org.codehaus.groovy.ast.tools.GeneralUtils.varX; /** @@ -71,18 +69,18 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { private final VariableExpression weaved; private final SourceUnit unit; private final ClassNode traitClass; - private final ClassNode traitHelperClass; + private final ClassNode traitHelper; private final ClassNode fieldHelper; private final Collection<String> knownFields; private boolean inClosure; public TraitReceiverTransformer(final VariableExpression thisObject, final SourceUnit unit, final ClassNode traitClass, - final ClassNode traitHelperClass, final ClassNode fieldHelper, final Collection<String> knownFields) { + final ClassNode traitHelper, final ClassNode fieldHelper, final Collection<String> knownFields) { this.weaved = thisObject; this.unit = unit; this.traitClass = traitClass; - this.traitHelperClass = traitHelperClass; + this.traitHelper = traitHelper; this.fieldHelper = fieldHelper; this.knownFields = knownFields; } @@ -94,9 +92,8 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { @Override public Expression transform(final Expression exp) { - ClassNode weavedType = weaved.getOriginType(); if (exp instanceof BinaryExpression) { - return transformBinaryExpression((BinaryExpression) exp, weavedType); + return transformBinaryExpression((BinaryExpression) exp); } else if (exp instanceof MethodCallExpression mce) { String obj = mce.getObjectExpression().getText(); if ("super".equals(obj)) { @@ -105,15 +102,13 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { return transformMethodCallOnThis(mce); // this.m(x) --> $self.m(x) or this.m($self, x) } } else if (exp instanceof FieldExpression) { - FieldNode fn = ((FieldExpression) exp).getField(); - return transformFieldReference(exp, fn, fn.isStatic()); + return transformFieldReference(exp, ((FieldExpression) exp).getField(), null); } else if (exp instanceof VariableExpression vexp) { Variable accessedVariable = vexp.getAccessedVariable(); if (accessedVariable instanceof FieldNode || accessedVariable instanceof PropertyNode) { if (knownFields.contains(vexp.getName())) { - boolean isStatic = accessedVariable.isStatic(); return transformFieldReference(exp, accessedVariable instanceof FieldNode - ? (FieldNode) accessedVariable : ((PropertyNode) accessedVariable).getField(), isStatic); + ? (FieldNode) accessedVariable : ((PropertyNode) accessedVariable).getField(), null); } else { PropertyExpression propertyExpression = propX(varX(weaved), vexp.getName()); propertyExpression.getProperty().setSourcePosition(exp); @@ -137,8 +132,8 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { if (pexp.isImplicitThis() || "this".equals(obj)) { String propName = pexp.getPropertyAsString(); if (knownFields.contains(propName)) { - FieldNode fn = new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null); - return transformFieldReference(exp, fn, false); + FieldNode fn = new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weaved.getOriginType(), null); + return transformFieldReference(exp, fn, null); } } } else if (exp instanceof ClosureExpression) { @@ -164,7 +159,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { return super.transform(exp); } - private Expression transformBinaryExpression(final BinaryExpression exp, final ClassNode weavedType) { + private Expression transformBinaryExpression(final BinaryExpression exp) { Expression leftExpression = exp.getLeftExpression(); Expression rightExpression = exp.getRightExpression(); Token operation = exp.getOperation(); @@ -179,29 +174,13 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { leftFieldName = ((PropertyExpression) leftExpression).getPropertyAsString(); } if (leftFieldName != null) { - FieldNode staticField = tryGetFieldNode(weavedType, leftFieldName); - if (fieldHelper == null || staticField == null && !fieldHelper.hasPossibleMethod(Traits.helperSetterName(new FieldNode(leftFieldName, 0, ClassHelper.OBJECT_TYPE, weavedType, null)), rightExpression)) { + ClassNode weavedType = weaved.getOriginType(); + FieldNode traitField = tryGetFieldNode(weavedType, leftFieldName); + FieldNode dummyField = new FieldNode(leftFieldName, 0, ClassHelper.OBJECT_TYPE, weavedType, null); + if (fieldHelper == null || traitField == null && !fieldHelper.hasPossibleMethod(Traits.helperSetterName(dummyField), 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); - } - Expression receiver = createFieldHelperReceiver(); - boolean isStatic = staticField != null && staticField.isStatic(); - if (fn.isStatic()) { // DO NOT USE isStatic variable here! - receiver = propX(receiver, "class"); - } - String method = Traits.helperSetterName(fn); - MethodCallExpression mce = callX( - receiver, - method, - super.transform(rightExpression) - ); - mce.setImplicitThis(false); - mce.setSourcePosition(exp); - markDynamicCall(mce, staticField, isStatic); - return mce; + return transformFieldReference(exp, traitField != null ? traitField : dummyField, rightExpression); } } @@ -214,23 +193,32 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { return ret; } - private Expression transformFieldReference(final Expression exp, final FieldNode fn, final boolean isStatic) { - Expression receiver = createFieldHelperReceiver(); - if (isStatic) { - receiver = asClass(receiver); + private Expression transformFieldReference(final Expression exp, final FieldNode fn, final Expression value) { + Expression receiver; + if (ClassHelper.isClassType(weaved.getOriginType())) { + receiver = varX(weaved); // $static$self + } else if (fn.isStatic()) { + var call = callX(varX(weaved), "getClass"); // $self.getClass() + call.setImplicitThis(false); + call.setMethodTarget(ClassHelper.OBJECT_TYPE.getGetterMethod("getClass", false)); + receiver = call; + } else { + receiver = castX(fieldHelper, varX(weaved)); // (<trait class>$Trait$FieldHelper) $self } - MethodCallExpression mce = callX(receiver, Traits.helperGetterName(fn)); + MethodCallExpression mce; + if (value == null) { + mce = callX(receiver, Traits.helperGetterName(fn)); + } else { + mce = callX(receiver, Traits.helperSetterName(fn), transform(value)); + } mce.setImplicitThis(false); mce.setSourcePosition(exp); - markDynamicCall(mce, fn, isStatic); - return mce; - } - private static void markDynamicCall(final MethodCallExpression mce, final FieldNode fn, final boolean isStatic) { - if (isStatic) { - mce.putNodeMetaData(TraitASTTransformation.DO_DYNAMIC, fn.getOriginType()); - } + // GROOVY-7255: static fields are available via the implementing class, which is not checkable + if (fn.isStatic()) mce.putNodeMetaData(TraitASTTransformation.DO_DYNAMIC, fn.getOriginType()); + + return mce; } private static FieldNode tryGetFieldNode(final ClassNode weavedType, final String fieldName) { @@ -287,7 +275,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { if (methodNode != null) { // this.m(x) --> (this or T$Trait$Helper).m($self or $static$self or (Class)$self.getClass(), x) Expression selfClassOrObject = methodNode.isStatic() && !ClassHelper.isClassType(weaved.getOriginType()) ? castX(ClassHelper.CLASS_Type.getPlainNodeReference(), callX(weaved, "getClass")) : weaved; - MethodCallExpression newCall = callX(!inClosure ? thisExpr : classX(traitHelperClass), method, createArgumentList(selfClassOrObject, arguments)); + MethodCallExpression newCall = callX(!inClosure ? thisExpr : classX(traitHelper), method, createArgumentList(selfClassOrObject, arguments)); newCall.setGenericsTypes(call.getGenericsTypes()); newCall.setSpreadSafe(call.isSpreadSafe()); newCall.setSourcePosition(call); @@ -341,13 +329,4 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer { } return newArgs; } - - private Expression createFieldHelperReceiver() { - return ClassHelper.isClassType(weaved.getOriginType()) ? weaved : castX(fieldHelper, weaved); - } - - private Expression asClass(final Expression e) { - ClassNode rawClass = ClassHelper.CLASS_Type.getPlainNodeReference(); - return ternaryX(isInstanceOfX(e, rawClass), e, callX(e, "getClass")); - } }
