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 f30978567e GROOVY-10380: return getter generated later by default 
argument(s)
f30978567e is described below

commit f30978567e5f77c6876e8b13e807d4cf329efc84
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Sun May 19 09:40:34 2024 -0500

    GROOVY-10380: return getter generated later by default argument(s)
---
 .../java/org/codehaus/groovy/ast/ClassNode.java    |  29 +++-
 .../transform/DelegateASTTransformation.java       |   2 +-
 .../stc/FieldsAndPropertiesSTCTest.groovy          | 191 +++++++++++----------
 3 files changed, 123 insertions(+), 99 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java 
b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
index 47220eb468..b01d8770fc 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -18,6 +18,7 @@
  */
 package org.codehaus.groovy.ast;
 
+import org.apache.groovy.ast.tools.AnnotatedNodeUtils;
 import org.apache.groovy.ast.tools.ClassNodeUtils;
 import org.apache.groovy.lang.annotation.Incubating;
 import org.codehaus.groovy.GroovyBugError;
@@ -48,6 +49,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.IntStream;
+import java.util.stream.Stream;
 
 import static java.util.Objects.requireNonNull;
 import static java.util.stream.Collectors.toList;
@@ -1050,14 +1052,25 @@ public class ClassNode extends AnnotatedNode {
 
         boolean booleanReturnOnly = getterName.startsWith("is");
         for (MethodNode method : getDeclaredMethods(getterName)) {
-            if (method.getName().equals(getterName) && 
method.getParameters().length == 0
-                    && (booleanReturnOnly ? 
ClassHelper.isPrimitiveBoolean(method.getReturnType()) : 
!method.isVoidMethod())) {
-                // GROOVY-7363, GROOVY-11341: There can be multiple matches if 
a method returns a non-final type due to
-                // the generation of a bridge method. The real getter is 
really the non-bridge, non-synthetic one as it
-                // has the most specific and exact return type of the two. 
Picking the bridge method results in loss of
-                // type information, as it down-casts the return type to the 
lower bound of the generic parameter.
-                if (isNullOrSynthetic.test(getterMethod)) {
-                    getterMethod = method;
+            if (booleanReturnOnly ? 
ClassHelper.isPrimitiveBoolean(method.getReturnType()) : 
!method.isVoidMethod()) {
+                if (method.getParameters().length == 0) {
+                    // GROOVY-7363, GROOVY-11341: There can be multiple 
matches if a method returns a non-final type due to
+                    // the generation of a bridge method. The real getter is 
really the non-bridge, non-synthetic one as it
+                    // has the most specific and exact return type of the two. 
Picking the bridge method results in loss of
+                    // type information, as it down-casts the return type to 
the lower bound of the generic parameter.
+                    if (isNullOrSynthetic.test(getterMethod)) {
+                        getterMethod = method;
+                    }
+                } else if (method.hasDefaultValue() && 
Stream.of(method.getParameters()).allMatch(Parameter::hasInitialExpression)) {
+                    // GROOVY-11380: getter generated later by default 
arguments
+                    if (isNullOrSynthetic.test(getterMethod)) {
+                        getterMethod = new MethodNode(method.getName(), 
method.getModifiers() & ~ACC_ABSTRACT, method.getReturnType(), 
Parameter.EMPTY_ARRAY, method.getExceptions(), null);
+                        getterMethod.setSynthetic(true);
+                        getterMethod.setDeclaringClass(this);
+                        getterMethod.addAnnotations(method.getAnnotations());
+                        AnnotatedNodeUtils.markAsGenerated(this, getterMethod);
+                        
getterMethod.setGenericsTypes(method.getGenericsTypes());
+                    }
                 }
             }
         }
diff --git 
a/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java 
b/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
index 2c79b242e3..38d586219b 100644
--- a/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java
@@ -310,7 +310,7 @@ public class DelegateASTTransformation extends 
AbstractASTTransformation {
 
     private static void addSetterIfNeeded(final DelegateDescription delegate, 
final PropertyNode prop, final String name, final boolean allNames) {
         String setterName = getSetterName(name);
-        if ((prop.getModifiers() & ACC_FINAL) == 0
+        if (!prop.isFinal()
                 && delegate.owner.getSetterMethod(setterName) == null && 
delegate.owner.getProperty(name) == null
                 && !shouldSkipPropertyMethod(name, setterName, 
delegate.excludes, delegate.includes, allNames)) {
             addGeneratedMethod(
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy 
b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 530f72c097..b078243307 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -393,7 +393,7 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
-    void testGetterForProperty1() {
+    void testGetterForProperty() {
         assertScript '''
             class C {
                 String p
@@ -403,89 +403,14 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
-    // GROOVY-10981
-    void testGetterForProperty2() {
-        for (mode in ['', 'public', 'private', 'protected', 
'@groovy.transform.PackageScope']) {
-            assertScript """
-                abstract class A {
-                    $mode Object p = 'field'
-                    CharSequence getP() { 'property' }
-                }
-                class C extends A {
-                    def m() {
-                        final int len = p.length()
-                        if (p instanceof String) {
-                            p.toLowerCase()
-                            p.toUpperCase()
-                        }
-                    }
-                }
-                String which = new C().m()
-                assert which == 'PROPERTY'
-            """
-        }
-    }
-
-    // GROOVY-9973
-    void testGetterForProperty3() {
-        assertScript '''
-            class C {
-                private int f
-                int getP() { f }
-                Integer m() { 123456 - p }
-                Integer m(int i) { i - p }
-            }
-            def c = new C()
-            assert c.m() == 123456 // BUG! exception in phase 'class 
generation' ...
-            assert c.m(123) == 123 // ClassCastException: class 
org.codehaus.groovy.ast.Parameter cannot be cast to ...
-        '''
-    }
-
-    // GROOVY-11005
-    void testGetterForProperty4() {
-        File parentDir = File.createTempDir()
-        config.with {
-            targetDirectory = File.createTempDir()
-            jointCompilationOptions = [memStub: true]
-        }
-        try {
-            def a = new File(parentDir, 'Pogo.groovy')
-            a.write '''
-                class Pogo {
-                    String value
-                    String getValue() { value }
-                }
-            '''
-            def b = new File(parentDir, 'Test.groovy')
-            b.write '''
-                class Test extends Pogo {
-                    void test() {
-                        value = 'string'
-                    }
-                }
-            '''
-
-            def loader = new GroovyClassLoader(this.class.classLoader)
-            def cu = new JavaAwareCompilationUnit(config, loader)
-            cu.addSources(a, b)
-            cu.compile()
-
-            loader.loadClass('Test').newInstance().test()
-        } finally {
-            parentDir.deleteDir()
-            config.targetDirectory.deleteDir()
-        }
-    }
-
     // GROOVY-5232
-    void testSetterForProperty1() {
+    void testSetterForProperty() {
         assertScript '''
             class Person {
                 String name
                 static Person create() {
                     def p = new Person()
                     p.setName("Guillaume")
-                    // but p.name = "Guillaume" works
                     return p
                 }
             }
@@ -493,16 +418,6 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
-    // GROOVY-11372
-    void testSetterForProperty2() {
-        assertScript '''
-            def baos = new ByteArrayOutputStream()
-            assert baos.size() == 0
-            baos.bytes= new byte[1]
-            assert baos.size() == 1
-        '''
-    }
-
     // GROOVY-5443
     void testFieldInitShouldPass() {
         assertScript '''
@@ -585,15 +500,27 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10380
+    void testGetterUsingPropertyNotation() {
+        assertScript '''
+            class C {
+                def getFoo(foo = 'foo') { foo }
+            }
+            def c = new C()
+            def v = c.foo
+            assert v == 'foo'
+        '''
+    }
+
     void testSetterUsingPropertyNotation() {
         assertScript '''
             class C {
-                boolean ok = false
-                void setFoo(String foo) { ok = (foo == 'foo') }
+                boolean set
+                void setFoo(foo) { set = (foo == 'foo') }
             }
             def c = new C()
             c.foo = 'foo'
-            assert c.ok
+            assert c.set
         '''
     }
 
@@ -611,6 +538,16 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-11372
+    void testSetterUsingPropertyNotationViaExtension() {
+        assertScript '''
+            def baos = new ByteArrayOutputStream()
+            assert baos.size() == 0
+            baos.bytes= new byte[1]
+            assert baos.size() == 1
+        '''
+    }
+
     void testListDotProperty1() {
         assertScript '''class Elem { int value }
             List<Elem> list = new LinkedList<Elem>()
@@ -1163,6 +1100,65 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10981
+    void testSuperPropertyAccess4() {
+        for (mode in ['', 'public', 'private', 'protected', 
'@groovy.transform.PackageScope']) {
+            assertScript """
+                abstract class A {
+                    $mode Object p = 'field'
+                    CharSequence getP() { 'property' }
+                }
+                class C extends A {
+                    def m() {
+                        final int len = p.length()
+                        if (p instanceof String) {
+                            p.toLowerCase()
+                            p.toUpperCase()
+                        }
+                    }
+                }
+                String which = new C().m()
+                assert which == 'PROPERTY'
+            """
+        }
+    }
+
+    // GROOVY-11005
+    void testSuperPropertyAccess5() {
+        File parentDir = File.createTempDir()
+        config.with {
+            targetDirectory = File.createTempDir()
+            jointCompilationOptions = [memStub: true]
+        }
+        try {
+            def a = new File(parentDir, 'Pogo.groovy')
+            a.write '''
+                class Pogo {
+                    String value
+                    String getValue() { value }
+                }
+            '''
+            def b = new File(parentDir, 'Test.groovy')
+            b.write '''
+                class Test extends Pogo {
+                    void test() {
+                        value = 'string'
+                    }
+                }
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b)
+            cu.compile()
+
+            loader.loadClass('Test').newInstance().test()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+        }
+    }
+
     void testPrivateFieldAccessInClosure1() {
         assertScript '''
             class C {
@@ -1251,6 +1247,21 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-9973
+    void testPrivateFieldVersusPublicGetter() {
+        assertScript '''
+            class C {
+                private int f
+                int getP() { f }
+                Integer m() { 123456 - p }
+                Integer m(int i) { i - p }
+            }
+            def c = new C()
+            assert c.m() == 123456 // BUG! exception in phase 'class 
generation' ...
+            assert c.m(123) == 123 // ClassCastException: class 
org.codehaus.groovy.ast.Parameter cannot be cast to ...
+        '''
+    }
+
     // GROOVY-6277
     void testPublicFieldVersusPrivateGetter() {
         assertScript '''

Reply via email to