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 2021/03/18 15:50:50 UTC

[groovy] 01/01: GROOVY-7306: apply type arguments of super to its constructor parameters

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

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

commit 68e1642927afe14ae523f1910f8d64ecf0fc51eb
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Mar 18 10:28:58 2021 -0500

    GROOVY-7306: apply type arguments of super to its constructor parameters
---
 .../groovy/tools/javac/JavaStubGenerator.java      | 38 ++++++++------
 .../groovy/tools/stubgenerator/Groovy7306.groovy   | 58 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 16 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
index 35b7ae5..0bce9d4 100644
--- a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
+++ b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
@@ -576,25 +576,31 @@ public class JavaStubGenerator {
         }
     }
 
-    private static Parameter[] selectAccessibleConstructorFromSuper(ConstructorNode node) {
-        ClassNode type = node.getDeclaringClass();
-        ClassNode superType = type.getUnresolvedSuperClass();
+    private static Parameter[] selectAccessibleConstructorFromSuper(final ConstructorNode source) {
+        ClassNode superType = source.getDeclaringClass().getUnresolvedSuperClass();
+        Map<String, ClassNode> superTypeGenerics = createGenericsSpec(superType);
 
         Parameter[] bestMatch = null;
-        for (ConstructorNode c : superType.getDeclaredConstructors()) {
-            // Only look at things we can actually call
-            if (!c.isPublic() && !c.isProtected()) continue;
-            Parameter[] parameters = c.getParameters();
-            // workaround for GROOVY-5859: remove generic type info
-            Parameter[] copy = new Parameter[parameters.length];
-            for (int i = 0; i < copy.length; i++) {
-                Parameter orig = parameters[i];
-                copy[i] = new Parameter(orig.getOriginType().getPlainNodeReference(), orig.getName());
-            }
-            if (noExceptionToAvoid(node,c)) return copy;
-            if (bestMatch==null) bestMatch = copy;
+        for (ConstructorNode target : superType.getDeclaredConstructors()) {
+            // only look at things we can actually call
+            // TODO: package-private and types are peers
+            if (!target.isPublic() && !target.isProtected()) continue;
+
+            Parameter[] parameters = target.getParameters();
+            Parameter[] normalized = Arrays.stream(parameters).map(parameter -> {
+                ClassNode normalizedType = parameter.getOriginType();
+                // GROOVY-7306: apply type arguments from declaring type to parameter type
+                normalizedType = correctToGenericsSpec(superTypeGenerics, normalizedType);
+                // workaround for GROOVY-5859: remove generic type info
+                normalizedType = normalizedType.getPlainNodeReference();
+
+                return new Parameter(normalizedType, parameter.getName());
+            }).toArray(Parameter[]::new);
+
+            if (noExceptionToAvoid(source, target)) return normalized;
+            if (bestMatch == null) bestMatch = normalized;
         }
-        if (bestMatch!=null) return bestMatch;
+        if (bestMatch != null) return bestMatch;
 
         // fall back for parameterless constructor
         if (superType.isPrimaryClassNode()) {
diff --git a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy
new file mode 100644
index 0000000..fec232a
--- /dev/null
+++ b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy7306.groovy
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.codehaus.groovy.tools.stubgenerator
+
+final class Groovy7306 extends StringSourcesStubTestCase {
+
+    @Override
+    Map<String, String> provideSources() {
+        [
+            'A7306.groovy': '''
+                abstract class A7306<T extends Number> {
+                    final T value
+                    A7306(T value) {
+                        this.value = value
+                    }
+                }
+            ''',
+            'C7306.groovy': '''
+                class C7306 extends A7306<Integer> {
+                    C7306(Integer value) {
+                        super(value)
+                    }
+                }
+            ''',
+            'Main.java': '''
+                public class Main {
+                    public static void main(String[] args) {
+                        new C7306();
+                    }
+                }
+            ''',
+        ]
+    }
+
+    @Override
+    void verifyStubs() {
+        compile([new File(stubDir,'A7306.java'), new File(stubDir,'C7306.java')])
+
+        def specialCtorCall = (stubJavaSourceFor('C7306') =~ /super\s*\((.+?)\);/)
+        assert specialCtorCall.find() && specialCtorCall.group(1) == '(java.lang.Integer)null'
+    }
+}