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/02/02 16:23:41 UTC

[groovy] branch master updated: GROOVY-10922: STC: forthcoming generated property method stub

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 282ba5cd6d GROOVY-10922: STC: forthcoming generated property method stub
282ba5cd6d is described below

commit 282ba5cd6d74acbe7f8aa57244a82730d0aae2d5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 2 10:11:46 2023 -0600

    GROOVY-10922: STC: forthcoming generated property method stub
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 31 ++++++++++++----------
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 26 ++++++++++++++++++
 2 files changed, 43 insertions(+), 14 deletions(-)

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 9e0d5b9351..7971299de2 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4742,7 +4742,7 @@ out:                if (mn.size() != 1) {
         return methods;
     }
 
-    private static List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<MethodNode> methods) {
+    private static List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<? extends MethodNode> methods) {
         // using a comparator of parameters
         List<MethodNode> result = new LinkedList<>();
         for (MethodNode method : methods) {
@@ -4802,7 +4802,7 @@ out:                if (mn.size() != 1) {
 
         List<MethodNode> methods;
         if ("<init>".equals(name) && !receiver.isInterface()) {
-            methods = addGeneratedMethods(receiver, new ArrayList<>(receiver.getDeclaredConstructors()));
+            methods = addGeneratedMethods(receiver, receiver.getDeclaredConstructors());
             if (methods.isEmpty()) {
                 MethodNode node = new ConstructorNode(Opcodes.ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
                 node.setDeclaringClass(receiver);
@@ -4835,8 +4835,8 @@ out:                if (mn.size() != 1) {
             if (methods.isEmpty()) {
                 addArrayMethods(methods, receiver, name, args);
             }
-            if (methods.isEmpty() && (args == null || args.length == 0)) {
-                // check if it's a property
+            if (args == null || args.length == 0) {
+                // check for property accessor
                 String pname = extractPropertyNameFromMethodName("get", name);
                 if (pname == null) {
                     pname = extractPropertyNameFromMethodName("is", name);
@@ -4855,24 +4855,27 @@ out:                if (mn.size() != 1) {
                         }
                     }
                 }
-                if (property != null) {
-                    int mods = Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0);
-                    MethodNode node = new MethodNode(name, mods, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
+                if (property != null && property.getDeclaringClass().getGetterMethod(name) == null) {
+                    MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0),
+                            property.getOriginType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
                     node.setDeclaringClass(property.getDeclaringClass());
-                    return Collections.singletonList(node);
+                    node.setSynthetic(true);
+                    methods.add(node);
                 }
-            } else if (methods.isEmpty() && args.length == 1) {
-                // maybe we are looking for a setter ?
+            } else if (args.length == 1 && (methods.isEmpty()
+                    || methods.stream().allMatch(MethodNode::isAbstract))) { // GROOVY-10922
+                // check for property mutator
                 String pname = extractPropertyNameFromMethodName("set", name);
                 if (pname != null) {
                     PropertyNode property = findProperty(receiver, pname);
-                    if (property != null && !Modifier.isFinal(property.getModifiers())) {
+                    if (property != null && !property.isFinal()) {
                         ClassNode type = property.getOriginType();
                         if (implementsInterfaceOrIsSubclassOf(wrapTypeIfNecessary(args[0]), wrapTypeIfNecessary(type))) {
-                            int mods = Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0);
-                            MethodNode node = new MethodNode(name, mods, VOID_TYPE, new Parameter[]{new Parameter(type, name)}, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
+                            MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0),
+                                    VOID_TYPE, new Parameter[]{new Parameter(type, name)}, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
                             node.setDeclaringClass(property.getDeclaringClass());
-                            return Collections.singletonList(node);
+                            node.setSynthetic(true);
+                            methods.add(node);
                         }
                     }
                 }
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 9fb1c016dd..2838725971 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -330,6 +330,32 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
         'Default method m(T) requires qualified super'
     }
 
+    // GROOVY-10922
+    void testCallToSuperGenerated() {
+        assertScript '''
+            interface Foo {
+                String getString()
+                void setString(String s)
+            }
+            class Bar implements Foo {
+                String string
+            }
+            class Baz extends Bar {
+                String object
+                @Override
+                void setString(String string) {
+                    super.setString(string)
+                    object = string
+                }
+            }
+;
+            def obj = new Baz()
+            obj.setString('xx')
+            assert obj.object == 'xx'
+            assert obj.string == 'xx'
+        '''
+    }
+
     void testMethodCallFromSuperOwner() {
         assertScript '''
             class Child extends groovy.transform.stc.MethodCallsSTCTest.GroovyPage {