@@ -142,17 +142,17 @@ private void maybeRecord(Class<?> clazz, Supplier<String> message) {
142142 delegate .setProperty (lhs , name , value );
143143 if (SystemProperties .getBoolean (LoggingInvoker .class .getName () + ".fieldSetWarning" , true )) {
144144 if (value != null && !CLOSURE_METAPROPS .contains (name )) {
145- var owner = findOwner (lhs );
146- if (owner instanceof CpsScript ) {
145+ var receiver = findReceiver (lhs );
146+ if (receiver instanceof CpsScript ) {
147147 try {
148- owner .getClass ().getDeclaredField (name );
148+ receiver .getClass ().getDeclaredField (name );
149149 // OK, @Field, ignore
150150 } catch (NoSuchFieldException x ) {
151151 var g = CpsThreadGroup .current ();
152152 if (g != null ) {
153153 var e = g .getExecution ();
154154 if (e != null ) {
155- e .getOwner ().getListener ().getLogger ().println (Messages .LoggingInvoker_field_set (owner .getClass ().getSimpleName (), name , value .getClass ().getSimpleName ()));
155+ e .getOwner ().getListener ().getLogger ().println (Messages .LoggingInvoker_field_set (receiver .getClass ().getSimpleName (), name , value .getClass ().getSimpleName ()));
156156 }
157157 }
158158 }
@@ -161,8 +161,28 @@ private void maybeRecord(Class<?> clazz, Supplier<String> message) {
161161 }
162162 }
163163
164- private Object findOwner (Object o ) {
165- return o instanceof Closure <?> c ? findOwner (c .getOwner ()) : o ;
164+ private Object findReceiver (Object o ) {
165+ if (o instanceof Closure <?> c ) {
166+ // c.f. https://github.com/apache/groovy/blob/41b990d0a20e442f29247f0e04cbed900f3dcad4/src/main/groovy/lang/Closure.java#L344
167+ return switch (c .getResolveStrategy ()) {
168+ case Closure .DELEGATE_ONLY -> findReceiver (c .getDelegate ());
169+ case Closure .OWNER_ONLY -> findReceiver (c .getOwner ());
170+ case Closure .TO_SELF -> c ;
171+ case Closure .DELEGATE_FIRST -> {
172+ var delegate = c .getDelegate ();
173+ if (delegate == null ) {
174+ yield findReceiver (c .getOwner ());
175+ }
176+ // TODO: Groovy will actually try the delegate first and then the owner if needed, but it is
177+ // difficult for us to know what will happen in advance.
178+ yield findReceiver (delegate );
179+ }
180+ default ->
181+ // TODO: Groovy will actually try the owner first and then the delegate if needed.
182+ findReceiver (c .getOwner ());
183+ };
184+ }
185+ return o ;
166186 }
167187
168188 @ Override public Object getAttribute (Object lhs , String name ) throws Throwable {
0 commit comments