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 2023/04/28 16:43:59 UTC

[groovy] branch master updated: GROOVY-11029: STC: direct method target for `super.name` and `that.name`

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 707ed5a0e8 GROOVY-11029: STC: direct method target for `super.name` and `that.name`
707ed5a0e8 is described below

commit 707ed5a0e85b6182df44894419c32fb6600687f1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Apr 28 11:26:09 2023 -0500

    GROOVY-11029: STC: direct method target for `super.name` and `that.name`
    
    when property method has not yet been generated
---
 .../codehaus/groovy/classgen/asm/MopWriter.java    |  2 +-
 .../asm/sc/StaticCompilationMopWriter.java         |  7 +---
 .../MethodCallExpressionTransformer.java           |  2 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   | 31 +++++++++-----
 .../stc/FieldsAndPropertiesSTCTest.groovy          | 48 ++++++++++++++++------
 5 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/MopWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/MopWriter.java
index c096cbfaf6..addc0d16db 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/MopWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/MopWriter.java
@@ -81,7 +81,7 @@ public class MopWriter {
 
     //--------------------------------------------------------------------------
 
-    private final WriterController controller;
+    protected final WriterController controller;
 
     public MopWriter(final WriterController controller) {
         this.controller = requireNonNull(controller);
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticCompilationMopWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticCompilationMopWriter.java
index 4c3ba79e4a..44c940ee27 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticCompilationMopWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticCompilationMopWriter.java
@@ -37,21 +37,16 @@ public class StaticCompilationMopWriter extends MopWriter {
 
     public static final MopWriter.Factory FACTORY = StaticCompilationMopWriter::new;
 
-    private final StaticTypesWriterController controller;
-
     public StaticCompilationMopWriter(final WriterController wc) {
         super(wc);
-        this.controller = (StaticTypesWriterController) wc;
     }
 
-
     @Override
     public void createMopMethods() {
         ClassNode classNode = controller.getClassNode();
         LinkedList<MethodNode> requiredMopMethods = classNode.getNodeMetaData(StaticTypesMarker.SUPER_MOP_METHOD_REQUIRED);
-        if (requiredMopMethods!=null) {
+        if (requiredMopMethods != null) {
             generateMopCalls(requiredMopMethods, false);
         }
     }
-
 }
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java
index ee43582ac8..d0fbaa2c44 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java
@@ -56,7 +56,7 @@ public class MethodCallExpressionTransformer {
             return trn;
         }
         ClassNode superCallReceiver = expr.getNodeMetaData(StaticTypesMarker.SUPER_MOP_METHOD_REQUIRED);
-        if (superCallReceiver!=null) {
+        if (superCallReceiver != null) {
             return transformMethodCallExpression(transformToMopSuperCall(superCallReceiver, expr));
         }
         Expression objectExpression = expr.getObjectExpression();
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 26a5466a2a..fdc7b59d60 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1865,8 +1865,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     private boolean storeProperty(final PropertyNode property, final PropertyExpression expression, final ClassNode receiver, final ClassCodeVisitorSupport visitor, final String delegationData, final boolean lhsOfAssignment) {
         if (visitor != null) visitor.visitProperty(property);
-        ClassNode propertyType = property.getOriginType();
 
+        ClassNode propertyType = property.getOriginType();
         storeWithResolve(propertyType, receiver, property.getDeclaringClass(), property.isStatic(), expression);
 
         if (delegationData != null) {
@@ -1874,19 +1874,28 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
         if (Modifier.isFinal(property.getModifiers())) {
             expression.putNodeMetaData(READONLY_PROPERTY, Boolean.TRUE);
-            if (!lhsOfAssignment) {
-                MethodNode implicitGetter = new MethodNode(property.getGetterNameOrDefault(), Opcodes.ACC_PUBLIC, propertyType, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
-                implicitGetter.setDeclaringClass(property.getDeclaringClass());
-                extension.onMethodSelection(expression, implicitGetter);
-            }
         } else {
             expression.removeNodeMetaData(READONLY_PROPERTY);
-            if (lhsOfAssignment) {
-                MethodNode implicitSetter = new MethodNode(property.getSetterNameOrDefault(), Opcodes.ACC_PUBLIC, VOID_TYPE, new Parameter[] {new Parameter(propertyType, "value")}, ClassNode.EMPTY_ARRAY, null);
-                implicitSetter.setDeclaringClass(property.getDeclaringClass());
-                extension.onMethodSelection(expression, implicitSetter);
-            }
         }
+
+        String methodName;
+        ClassNode returnType;
+        Parameter[] parameters;
+        if (!lhsOfAssignment) {
+            methodName = property.getGetterNameOrDefault();
+            returnType = propertyType;
+            parameters = Parameter.EMPTY_ARRAY;
+        } else {
+            methodName = property.getSetterNameOrDefault();
+            returnType = VOID_TYPE;
+            parameters = new Parameter[] {new Parameter(propertyType, "value")};
+        }
+        MethodNode accessMethod = new MethodNode(methodName, Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0), returnType, parameters, ClassNode.EMPTY_ARRAY, null);
+        accessMethod.setDeclaringClass(property.getDeclaringClass());
+        accessMethod.setSynthetic(true);
+
+        expression.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, accessMethod); // GROOVY-11029
+        extension.onMethodSelection(expression, accessMethod);
         return true;
     }
 
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 7565730f18..1515953c49 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -889,26 +889,32 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
         }
     }
 
-    void testPrivateFieldAccessInAIC() {
+    // GROOVY-11029
+    void testSuperPropertyAccess1() {
         assertScript '''
-            class A {
-                private int x
-                void foo() {
-                    def aic = new Runnable() { void run() { x = 666 } }
-                    aic.run()
+            class Foo {
+                Object myThing
+            }
+            class Bar extends Foo {
+                @Override
+                Object getMyThing() {
+                    super.myThing
                 }
-                void ensure() {
-                    assert x == 666
+                @Override
+                void setMyThing(Object object) {
+                    super.myThing = object
                 }
             }
-            def a = new A()
-            a.foo()
-            a.ensure()
+
+            def bar = new Bar()
+            def value = 'thing'
+            bar.myThing = value
+            assert bar.myThing === value
         '''
     }
 
     // GROOVY-9562
-    void testSuperPropertyAccessInAIC() {
+    void testSuperPropertyAccess2() {
         assertScript '''
             abstract class One {
                 int prop = 1
@@ -934,6 +940,24 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    void testPrivateFieldAccessInAIC() {
+        assertScript '''
+            class A {
+                private int x
+                void foo() {
+                    def aic = new Runnable() { void run() { x = 666 } }
+                    aic.run()
+                }
+                void ensure() {
+                    assert x == 666
+                }
+            }
+            def a = new A()
+            a.foo()
+            a.ensure()
+        '''
+    }
+
     void testPrivateFieldAccessInClosure1() {
         assertScript '''
             class A {