You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/08/13 15:21:50 UTC

[groovy] branch master updated: Allow chooseBestMethod to match "? super T"

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

sunlan 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 62ab65a  Allow chooseBestMethod to match "? super T"
62ab65a is described below

commit 62ab65a7fcc4a63e9d8fdf920fe20b81afaf7138
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu May 30 12:38:34 2019 -0500

    Allow chooseBestMethod to match "? super T"
    
    See comment in GROOVY-9074 for next step(s)
---
 .../transform/stc/StaticTypeCheckingSupport.java   |  22 +--
 src/test/groovy/bugs/Groovy8609Bug.groovy          |  14 +-
 src/test/groovy/bugs/Groovy9074.groovy             | 157 +++++++++++++++++++++
 3 files changed, 175 insertions(+), 18 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index ef043d5..84728cd 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -23,6 +23,7 @@ import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
 import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
@@ -50,6 +51,7 @@ import org.objectweb.asm.Opcodes;
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -60,6 +62,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.UUID;
@@ -102,7 +105,6 @@ import static org.codehaus.groovy.ast.ClassHelper.make;
 import static org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching;
 import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.void_WRAPPER_TYPE;
-import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.getSuperClass;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
 import static org.codehaus.groovy.syntax.Types.ASSIGN;
@@ -1186,16 +1188,14 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static Parameter[] makeRawTypes(Parameter[] params, Map<GenericsType, GenericsType> genericsPlaceholderAndTypeMap) {
-
-        Parameter[] newParam = new Parameter[params.length];
-        for (int i = 0; i < params.length; i++) {
-            Parameter oldP = params[i];
-
-            ClassNode actualType = GenericsUtils.findActualTypeByGenericsPlaceholderName(oldP.getType().getUnresolvedName(), genericsPlaceholderAndTypeMap);
-            Parameter newP = new Parameter(makeRawType(null == actualType ? oldP.getType() : actualType), oldP.getName());
-            newParam[i] = newP;
-        }
-        return newParam;
+        return Arrays.stream(params).map(param -> {
+            String name = param.getType().getUnresolvedName();
+            Optional<GenericsType> value = genericsPlaceholderAndTypeMap.entrySet().stream()
+                .filter(e -> e.getKey().getName().equals(name)).findFirst().map(e -> e.getValue());
+            ClassNode type = value.map(GenericsType::getType).orElseGet(() -> makeRawType(param.getType()));
+
+            return new Parameter(type, param.getName());
+        }).toArray(Parameter[]::new);
     }
 
     private static ClassNode makeRawType(final ClassNode receiver) {
diff --git a/src/test/groovy/bugs/Groovy8609Bug.groovy b/src/test/groovy/bugs/Groovy8609Bug.groovy
index bfc021f..2ada73c 100644
--- a/src/test/groovy/bugs/Groovy8609Bug.groovy
+++ b/src/test/groovy/bugs/Groovy8609Bug.groovy
@@ -18,9 +18,11 @@
  */
 package groovy.bugs
 
-import gls.CompilableTestSupport
+import groovy.transform.CompileStatic
+
+@CompileStatic
+final class Groovy8609Bug extends GroovyTestCase {
 
-class Groovy8609Bug extends CompilableTestSupport {
     void testUpperBoundWithGenerics() {
         assertScript '''
         @groovy.transform.CompileStatic
@@ -96,7 +98,7 @@ class Groovy8609Bug extends CompilableTestSupport {
         }
         '''
 
-        assert errMsg.contains('[Static type checking] - Cannot call A <ArrayList, HashMap>#getFirstRecord(T) with arguments [java.util.ArrayList <TreeMap>]')
+        assert errMsg.contains('[Static type checking] - Cannot find matching method A#getFirstRecord(java.util.ArrayList <TreeMap>)')
     }
 
     void testUpperBoundWithGenericsThroughWrongType2() {
@@ -117,8 +119,7 @@ class Groovy8609Bug extends CompilableTestSupport {
         }
         '''
 
-        // TODO we should print generics details, e.g. [Static type checking] - Cannot call A <ArrayList, HashMap<String, Integer>>#getFirstRecord(T) with arguments [java.util.ArrayList <HashMap<String, Long>>]
-        assert errMsg.contains('[Static type checking] - Cannot call A <ArrayList, HashMap>#getFirstRecord(T) with arguments [java.util.ArrayList <HashMap>]')
+        assert errMsg.contains('[Static type checking] - Cannot find matching method A#getFirstRecord(java.util.ArrayList <HashMap>)')
     }
 
     void testUpperBoundWithGenericsThroughWrongType3() {
@@ -139,7 +140,6 @@ class Groovy8609Bug extends CompilableTestSupport {
         }
         '''
 
-        // TODO we should print generics details, e.g. [Static type checking] - Cannot call A <ArrayList, HashMap<String, Integer>>#getFirstRecord(T) with arguments [java.util.ArrayList <HashMap<StringBuffer, Integer>>]
-        assert errMsg.contains('[Static type checking] - Cannot call A <ArrayList, HashMap>#getFirstRecord(T) with arguments [java.util.ArrayList <HashMap>]')
+        assert errMsg.contains('[Static type checking] - Cannot find matching method A#getFirstRecord(java.util.ArrayList <HashMap>)')
     }
 }
diff --git a/src/test/groovy/bugs/Groovy9074.groovy b/src/test/groovy/bugs/Groovy9074.groovy
new file mode 100644
index 0000000..b3ebf16
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9074.groovy
@@ -0,0 +1,157 @@
+/*
+ * 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 groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.codehaus.groovy.control.CompilationUnit
+
+import static org.codehaus.groovy.control.Phases.CLASS_GENERATION
+
+@CompileStatic
+final class Groovy9074 extends GroovyTestCase {
+
+    void _FIXME_testWildcardCapture() {
+        def err = shouldFail '''
+            @groovy.transform.CompileStatic
+            class Main {
+                private static Collection<?> c = new ArrayList<String>()
+                static main(args) {
+                    c.add(new Object())
+                }
+            }
+        '''
+
+        // TODO: This is just a sample message; Java produces this for the equivalent code.
+        assert err =~ / The method add\(capture#1-of \?\) in the type Collection<capture#1-of \?> is not applicable for the arguments \(Object\)/
+    }
+
+    void _FIXME_testWildcardExtends() {
+        def err = shouldFail '''
+            import java.awt.Canvas
+            abstract class Shape {
+              abstract void draw(Canvas c)
+            }
+            class Circle extends Shape {
+              private int x, y, radius
+              @Override void draw(Canvas c) {}
+            }
+            class Rectangle extends Shape {
+              private int x, y, width, height
+              @Override void draw(Canvas c) {}
+            }
+
+            @groovy.transform.CompileStatic
+            void addRectangle(List<? extends Shape> shapes) {
+              shapes.add(0, new Rectangle()) // TODO: compile-time error!
+            }
+        '''
+
+        // TODO: This is just a sample message; Java produces this for the equivalent code.
+        assert err =~ / The method add(capture#1-of \?) in the type List<capture#1-of \?> is not applicable for the arguments \(Rectangle\)/
+    }
+
+    void testWildcardSuper() {
+        assertScript '''
+            import java.awt.Canvas
+            abstract class Shape {
+              abstract void draw(Canvas c)
+            }
+            class Circle extends Shape {
+              private int x, y, radius
+              @Override void draw(Canvas c) {}
+            }
+            class Rectangle extends Shape {
+              private int x, y, width, height
+              @Override void draw(Canvas c) {}
+            }
+
+            @groovy.transform.CompileStatic
+            void addRectangle(List<? super Shape> shapes) {
+              shapes.add(0, new Rectangle())
+            }
+
+            List<Shape> list = []
+            addRectangle(list)
+
+            assert list.size() == 1
+            assert list.get(0) instanceof Rectangle
+        '''
+    }
+
+    void testWildcardExtends2() {
+        new CompilationUnit().with {
+            addSource 'Main.groovy', '''
+                class Factory {
+                  def <T> T make(Class<T> type, ... args) {}
+                }
+
+                @groovy.transform.CompileStatic
+                void test(Factory fact, Rule rule) {
+                  Type bean = fact.make(rule.type)
+                }
+            '''
+
+            addSource 'Rule.groovy', '''
+                class Rule {
+                  Class<? extends Type> getType() {
+                  }
+                }
+            '''
+
+            addSource 'Type.groovy', '''
+                interface Type {
+                }
+            '''
+
+            compile CLASS_GENERATION
+        }
+    }
+
+    void _FIXME_testWildcardSuper2() {
+        new CompilationUnit().with {
+            addSource 'Main.groovy', '''
+                class Factory {
+                  def <T> T make(Class<T> type, ... args) {}
+                }
+
+                @groovy.transform.CompileStatic
+                void test(Factory fact, Rule rule) {
+                  Type bean = fact.make(rule.type) // can't assign "? super Type" to "Type"
+                }
+            '''
+
+            addSource 'Rule.groovy', '''
+                class Rule {
+                  Class<? super Type> getType() {
+                  }
+                }
+            '''
+
+            addSource 'Type.groovy', '''
+                interface Type {
+                }
+            '''
+
+            def err = shouldFail {
+                compile CLASS_GENERATION
+            }
+            assert err =~ "cannot convert from capture#1-of ? super Type to Type"
+        }
+    }
+}