5151import static org .codehaus .groovy .ast .tools .GeneralUtils .callX ;
5252import static org .codehaus .groovy .ast .tools .GeneralUtils .castX ;
5353import static org .codehaus .groovy .ast .tools .GeneralUtils .classX ;
54- import static org .codehaus .groovy .ast .tools .GeneralUtils .isInstanceOfX ;
5554import static org .codehaus .groovy .ast .tools .GeneralUtils .propX ;
56- import static org .codehaus .groovy .ast .tools .GeneralUtils .ternaryX ;
5755import static org .codehaus .groovy .ast .tools .GeneralUtils .varX ;
5856
5957/**
@@ -71,18 +69,18 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
7169 private final VariableExpression weaved ;
7270 private final SourceUnit unit ;
7371 private final ClassNode traitClass ;
74- private final ClassNode traitHelperClass ;
72+ private final ClassNode traitHelper ;
7573 private final ClassNode fieldHelper ;
7674 private final Collection <String > knownFields ;
7775
7876 private boolean inClosure ;
7977
8078 public TraitReceiverTransformer (final VariableExpression thisObject , final SourceUnit unit , final ClassNode traitClass ,
81- final ClassNode traitHelperClass , final ClassNode fieldHelper , final Collection <String > knownFields ) {
79+ final ClassNode traitHelper , final ClassNode fieldHelper , final Collection <String > knownFields ) {
8280 this .weaved = thisObject ;
8381 this .unit = unit ;
8482 this .traitClass = traitClass ;
85- this .traitHelperClass = traitHelperClass ;
83+ this .traitHelper = traitHelper ;
8684 this .fieldHelper = fieldHelper ;
8785 this .knownFields = knownFields ;
8886 }
@@ -94,9 +92,8 @@ protected SourceUnit getSourceUnit() {
9492
9593 @ Override
9694 public Expression transform (final Expression exp ) {
97- ClassNode weavedType = weaved .getOriginType ();
9895 if (exp instanceof BinaryExpression ) {
99- return transformBinaryExpression ((BinaryExpression ) exp , weavedType );
96+ return transformBinaryExpression ((BinaryExpression ) exp );
10097 } else if (exp instanceof MethodCallExpression mce ) {
10198 String obj = mce .getObjectExpression ().getText ();
10299 if ("super" .equals (obj )) {
@@ -105,15 +102,13 @@ public Expression transform(final Expression exp) {
105102 return transformMethodCallOnThis (mce ); // this.m(x) --> $self.m(x) or this.m($self, x)
106103 }
107104 } else if (exp instanceof FieldExpression ) {
108- FieldNode fn = ((FieldExpression ) exp ).getField ();
109- return transformFieldReference (exp , fn , fn .isStatic ());
105+ return transformFieldReference (exp , ((FieldExpression ) exp ).getField (), null );
110106 } else if (exp instanceof VariableExpression vexp ) {
111107 Variable accessedVariable = vexp .getAccessedVariable ();
112108 if (accessedVariable instanceof FieldNode || accessedVariable instanceof PropertyNode ) {
113109 if (knownFields .contains (vexp .getName ())) {
114- boolean isStatic = accessedVariable .isStatic ();
115110 return transformFieldReference (exp , accessedVariable instanceof FieldNode
116- ? (FieldNode ) accessedVariable : ((PropertyNode ) accessedVariable ).getField (), isStatic );
111+ ? (FieldNode ) accessedVariable : ((PropertyNode ) accessedVariable ).getField (), null );
117112 } else {
118113 PropertyExpression propertyExpression = propX (varX (weaved ), vexp .getName ());
119114 propertyExpression .getProperty ().setSourcePosition (exp );
@@ -137,8 +132,8 @@ public Expression transform(final Expression exp) {
137132 if (pexp .isImplicitThis () || "this" .equals (obj )) {
138133 String propName = pexp .getPropertyAsString ();
139134 if (knownFields .contains (propName )) {
140- FieldNode fn = new FieldNode (propName , 0 , ClassHelper .OBJECT_TYPE , weavedType , null );
141- return transformFieldReference (exp , fn , false );
135+ FieldNode fn = new FieldNode (propName , 0 , ClassHelper .OBJECT_TYPE , weaved . getOriginType () , null );
136+ return transformFieldReference (exp , fn , null );
142137 }
143138 }
144139 } else if (exp instanceof ClosureExpression ) {
@@ -164,7 +159,7 @@ public Expression transform(final Expression exp) {
164159 return super .transform (exp );
165160 }
166161
167- private Expression transformBinaryExpression (final BinaryExpression exp , final ClassNode weavedType ) {
162+ private Expression transformBinaryExpression (final BinaryExpression exp ) {
168163 Expression leftExpression = exp .getLeftExpression ();
169164 Expression rightExpression = exp .getRightExpression ();
170165 Token operation = exp .getOperation ();
@@ -179,29 +174,13 @@ private Expression transformBinaryExpression(final BinaryExpression exp, final C
179174 leftFieldName = ((PropertyExpression ) leftExpression ).getPropertyAsString ();
180175 }
181176 if (leftFieldName != null ) {
182- FieldNode staticField = tryGetFieldNode (weavedType , leftFieldName );
183- if (fieldHelper == null || staticField == null && !fieldHelper .hasPossibleMethod (Traits .helperSetterName (new FieldNode (leftFieldName , 0 , ClassHelper .OBJECT_TYPE , weavedType , null )), rightExpression )) {
177+ ClassNode weavedType = weaved .getOriginType ();
178+ FieldNode traitField = tryGetFieldNode (weavedType , leftFieldName );
179+ FieldNode dummyField = new FieldNode (leftFieldName , 0 , ClassHelper .OBJECT_TYPE , weavedType , null );
180+ if (fieldHelper == null || traitField == null && !fieldHelper .hasPossibleMethod (Traits .helperSetterName (dummyField ), rightExpression )) {
184181 return binX (propX (varX (weaved ), leftFieldName ), operation , transform (rightExpression )); // GROOVY-7342, GROOVY-7456, GROOVY-9739, GROOVY-10143, et al.
185182 }
186- FieldNode fn = weavedType .getDeclaredField (leftFieldName );
187- if (fn == null ) {
188- fn = new FieldNode (leftFieldName , 0 , ClassHelper .OBJECT_TYPE , weavedType , null );
189- }
190- Expression receiver = createFieldHelperReceiver ();
191- boolean isStatic = staticField != null && staticField .isStatic ();
192- if (fn .isStatic ()) { // DO NOT USE isStatic variable here!
193- receiver = propX (receiver , "class" );
194- }
195- String method = Traits .helperSetterName (fn );
196- MethodCallExpression mce = callX (
197- receiver ,
198- method ,
199- super .transform (rightExpression )
200- );
201- mce .setImplicitThis (false );
202- mce .setSourcePosition (exp );
203- markDynamicCall (mce , staticField , isStatic );
204- return mce ;
183+ return transformFieldReference (exp , traitField != null ? traitField : dummyField , rightExpression );
205184 }
206185 }
207186
@@ -214,23 +193,32 @@ private Expression transformBinaryExpression(final BinaryExpression exp, final C
214193 return ret ;
215194 }
216195
217- private Expression transformFieldReference (final Expression exp , final FieldNode fn , final boolean isStatic ) {
218- Expression receiver = createFieldHelperReceiver ();
219- if (isStatic ) {
220- receiver = asClass (receiver );
196+ private Expression transformFieldReference (final Expression exp , final FieldNode fn , final Expression value ) {
197+ Expression receiver ;
198+ if (ClassHelper .isClassType (weaved .getOriginType ())) {
199+ receiver = varX (weaved ); // $static$self
200+ } else if (fn .isStatic ()) {
201+ var call = callX (varX (weaved ), "getClass" ); // $self.getClass()
202+ call .setImplicitThis (false );
203+ call .setMethodTarget (ClassHelper .OBJECT_TYPE .getGetterMethod ("getClass" , false ));
204+ receiver = call ;
205+ } else {
206+ receiver = castX (fieldHelper , varX (weaved )); // (<trait class>$Trait$FieldHelper) $self
221207 }
222208
223- MethodCallExpression mce = callX (receiver , Traits .helperGetterName (fn ));
209+ MethodCallExpression mce ;
210+ if (value == null ) {
211+ mce = callX (receiver , Traits .helperGetterName (fn ));
212+ } else {
213+ mce = callX (receiver , Traits .helperSetterName (fn ), transform (value ));
214+ }
224215 mce .setImplicitThis (false );
225216 mce .setSourcePosition (exp );
226- markDynamicCall (mce , fn , isStatic );
227- return mce ;
228- }
229217
230- private static void markDynamicCall ( final MethodCallExpression mce , final FieldNode fn , final boolean isStatic ) {
231- if (isStatic ) {
232- mce . putNodeMetaData ( TraitASTTransformation . DO_DYNAMIC , fn . getOriginType ());
233- }
218+ // GROOVY-7255: static fields are available via the implementing class, which is not checkable
219+ if (fn . isStatic ()) mce . putNodeMetaData ( TraitASTTransformation . DO_DYNAMIC , fn . getOriginType ());
220+
221+ return mce ;
234222 }
235223
236224 private static FieldNode tryGetFieldNode (final ClassNode weavedType , final String fieldName ) {
@@ -287,7 +275,7 @@ private Expression transformMethodCallOnThis(final MethodCallExpression call) {
287275 if (methodNode != null ) {
288276 // this.m(x) --> (this or T$Trait$Helper).m($self or $static$self or (Class)$self.getClass(), x)
289277 Expression selfClassOrObject = methodNode .isStatic () && !ClassHelper .isClassType (weaved .getOriginType ()) ? castX (ClassHelper .CLASS_Type .getPlainNodeReference (), callX (weaved , "getClass" )) : weaved ;
290- MethodCallExpression newCall = callX (!inClosure ? thisExpr : classX (traitHelperClass ), method , createArgumentList (selfClassOrObject , arguments ));
278+ MethodCallExpression newCall = callX (!inClosure ? thisExpr : classX (traitHelper ), method , createArgumentList (selfClassOrObject , arguments ));
291279 newCall .setGenericsTypes (call .getGenericsTypes ());
292280 newCall .setSpreadSafe (call .isSpreadSafe ());
293281 newCall .setSourcePosition (call );
@@ -341,13 +329,4 @@ private ArgumentListExpression createArgumentList(final Expression self, final E
341329 }
342330 return newArgs ;
343331 }
344-
345- private Expression createFieldHelperReceiver () {
346- return ClassHelper .isClassType (weaved .getOriginType ()) ? weaved : castX (fieldHelper , weaved );
347- }
348-
349- private Expression asClass (final Expression e ) {
350- ClassNode rawClass = ClassHelper .CLASS_Type .getPlainNodeReference ();
351- return ternaryX (isInstanceOfX (e , rawClass ), e , callX (e , "getClass" ));
352- }
353332}
0 commit comments