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/08/17 19:47:57 UTC

[groovy] branch GROOVY-8788 created (now 488f8a8f33)

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

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


      at 488f8a8f33 GROOVY-8788: STC: prefer closer parameter match over self-type match

This branch includes the following new commits:

     new 488f8a8f33 GROOVY-8788: STC: prefer closer parameter match over self-type match

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[groovy] 01/01: GROOVY-8788: STC: prefer closer parameter match over self-type match

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 488f8a8f336efae32349317f219a8f8df8994114
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Aug 17 14:47:33 2022 -0500

    GROOVY-8788: STC: prefer closer parameter match over self-type match
---
 .../groovy/runtime/DefaultGroovyMethods.java       | 27 ++++++++++++++++++++--
 .../transform/stc/StaticTypeCheckingSupport.java   | 24 ++++++++++++++-----
 .../groovy/transform/stc/GenericsSTCTest.groovy    |  4 ++--
 .../groovy/transform/DelegateTransformTest.groovy  |  6 ++---
 4 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index 6695419a25..2f7d71171c 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -8290,8 +8290,11 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
 
     /**
      * Support the subscript operator for a Map.
-     * <pre class="groovyTestCase">def map = [a:10]
-     * assert map["a"] == 10</pre>
+     * <pre class="groovyTestCase">
+     * def map = [:]
+     * map.put(1,10)
+     * assert map[1] == 10
+     * </pre>
      *
      * @param self a Map
      * @param key  an Object as a key for the map
@@ -8302,6 +8305,26 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
         return self.get(key);
     }
 
+    /**
+     * Prevent {@link #getAt(Object,String)} for Map.
+     * <pre class="groovyTestCase">
+     * def map = [a:10]
+     * assert map["a"] == 10
+     *
+     * class HM extends HashMap {
+     *   String a = 'x'
+     * }
+     * map = new HM()
+     * map.put("a",1)
+     * assert map["a"] == 1 // not 'x'
+     * </pre>
+     *
+     * @since 5.0.0
+     */
+    public static <K,V> V getAt(Map<K,V> self, String key) {
+        return self.get(key);
+    }
+
     /**
      * Returns a new <code>Map</code> containing all entries from <code>left</code> and <code>right</code>,
      * giving precedence to <code>right</code>.  Any keys appearing in both Maps
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 4d4090fc82..de55e6992b 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1084,8 +1084,9 @@ public abstract class StaticTypeCheckingSupport {
             Parameter[] params = makeRawTypes(safeNode.getParameters(), spec);
             int dist = measureParametersAndArgumentsDistance(params, safeArgs);
             if (dist >= 0) {
-                dist += getClassDistance(declaringClass, actualReceiver);
-                dist += getExtensionDistance(isExtensionMethod);
+                if (!isExtensionMethod) { // GROOVY-6849, GROOVY-8788, et al.
+                    dist += (1 + getClassDistance(declaringClass, actualReceiver));
+                }
                 if (dist < bestDist) {
                     bestDist = dist;
                     bestChoices.clear();
@@ -1103,6 +1104,21 @@ public abstract class StaticTypeCheckingSupport {
                     onlyExtensionMethods.add(choice);
                 }
             }
+            if (onlyExtensionMethods.size() > 1) {
+                // GROOVY-8788: prefer closer parameter match over closer self-type match
+                bestDist = Integer.MAX_VALUE; List<MethodNode> bestExtensions = new LinkedList<>();
+                for (MethodNode extension : onlyExtensionMethods) { // exclude self-type from distance checking
+                    int dist = measureParametersAndArgumentsDistance(extension.getParameters(), argumentTypes);
+                    if (dist < bestDist) {
+                        bestDist = dist;
+                        bestExtensions.clear();
+                        bestExtensions.add(extension);
+                    } else if (dist == bestDist) {
+                        bestExtensions.add(extension);
+                    }
+                }
+                onlyExtensionMethods = bestExtensions;
+            }
             if (onlyExtensionMethods.size() == 1) {
                 return onlyExtensionMethods;
             }
@@ -1169,10 +1185,6 @@ public abstract class StaticTypeCheckingSupport {
         return getDistance(actualReceiverForDistance, declaringClassForDistance);
     }
 
-    private static int getExtensionDistance(final boolean isExtensionMethodNode) {
-        return isExtensionMethodNode ? 0 : 1;
-    }
-
     private static Parameter[] makeRawTypes(final Parameter[] parameters, final Map<GenericsType, GenericsType> genericsPlaceholderAndTypeMap) {
         return Arrays.stream(parameters).map(param -> {
             String name = param.getType().getUnresolvedName();
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index a22068beec..2595990a69 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -2024,8 +2024,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 }
             }
         ''',
-        'Cannot find matching method java.util.Map#put(java.lang.String, java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>). Please check if the declared type is correct and if the method exists.',
-        'Cannot call <K,V> org.codehaus.groovy.runtime.DefaultGroovyMethods#putAt(java.util.Map<K, V>, K, V) with arguments [java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>>, java.lang.String, java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>]'
+        'Cannot find matching method java.util.Map#put(java.lang.String, java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>)',
+        'Cannot assign java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>> to: java.util.Map<java.lang.String, java.util.List<java.lang.String>>'
     }
 
     void testPutAtWithWrongValueType3() {
diff --git a/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy b/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
index 7ad281e6ce..1e20c733f9 100644
--- a/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
@@ -112,12 +112,12 @@ final class DelegateTransformTest {
 
             def ms = new MapSet()
             assert ms.size() == 1
-            assert ms.toString() == '{a=1} [2, 3, 4]'
+            assert ms.toString() == '[a:1] [2, 3, 4]'
             ms.remove(3)
             assert ms.size() == 1
-            assert ms.toString() == '{a=1} [2, 4]'
+            assert ms.toString() == '[a:1] [2, 4]'
             ms.clear()
-            assert ms.toString() == '{a=1} []'
+            assert ms.toString() == '[a:1] []'
         '''
     }