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 2022/07/18 18:25:24 UTC

[groovy] 02/02: GROOVY-9891: return bound type for wildcard GenericsType -> ClassNode

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

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

commit c3d1eff73093e2ee127d8bd0d98cc823b4111b2d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Jul 18 13:09:00 2022 -0500

    GROOVY-9891: return bound type for wildcard GenericsType -> ClassNode
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   |  5 ++
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 59 +++++++++++++++++++++-
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 086c98d2cc..3bf6b32ad7 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -417,6 +417,11 @@ public class GenericsUtils {
         if (type.isPlaceholder()) {
             String name = type.getName();
             ret = genericsSpec.get(name);
+        } else if (type.isWildcard()) { // GROOVY-9891
+            ret = type.getLowerBound(); // use lower or upper
+            if (ret == null && type.getUpperBounds() != null) {
+                ret = type.getUpperBounds()[0]; // ? supports 1
+            }
         }
         if (ret == null) ret = type.getType();
         return ret;
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index f76b57c149..1f3f814b16 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -2950,8 +2950,10 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             }
             null
         '''
+    }
 
-        // GROOVY-9821
+    // GROOVY-9821
+    void testBoundedReturnTypeChecking2() {
         File parentDir = createTempDir()
         config.with {
             targetDirectory = createTempDir()
@@ -2985,6 +2987,61 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         }
     }
 
+    // GROOVY-9891
+    void testBoundedReturnTypeChecking3() {
+        assertScript '''
+            class Pogo {
+                Map<String, ? extends Number> map
+            }
+            def test(Pogo p) {
+                Collection<? extends Number> c = p.map.values()
+                Iterable<? extends Number> i = p.map.values()
+                i.iterator().next()
+            }
+            def n = test(new Pogo(map:[x:1,y:2.3]))
+            assert n == 1
+        '''
+
+        //
+
+        File parentDir = createTempDir()
+        config.with {
+            targetDirectory = createTempDir()
+            jointCompilationOptions = [stubDir: createTempDir()]
+        }
+        try {
+            def a = new File(parentDir, 'Pojo.java')
+            a.write '''
+                import java.util.Map;
+                class Pojo {
+                    Map<String, ? extends Number> getMap() {
+                        return map;
+                    }
+                    void setMap(Map<String, ? extends Number> map) {
+                        this.map = map;
+                    }
+                    private Map<String, ? extends Number> map = null;
+                }
+            '''
+            def b = new File(parentDir, 'Script.groovy')
+            b.write '''
+                void test(Pojo p) {
+                    Collection<? extends Number> c = p.map.values()
+                    Iterable<? extends Number> i = p.map.values()
+                }
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b)
+            cu.compile()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+            config.jointCompilationOptions.stubDir.deleteDir()
+        }
+    }
+
     // GROOVY-10234
     void testSelfReferentialTypeParameter() {
         File parentDir = createTempDir()