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:58 UTC
[groovy] 01/01: GROOVY-8788: STC: prefer closer parameter match over self-type match
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] []'
'''
}