You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2019/04/08 12:59:07 UTC

[groovy] 15/20: Choose method candidate

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

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

commit 8b4cccde744bd7a52b5e4c267aea6180576cd880
Author: Daniel Sun <su...@apache.org>
AuthorDate: Wed Mar 20 23:58:38 2019 +0800

    Choose method candidate
---
 ...StaticTypesMethodReferenceExpressionWriter.java | 54 ++++++++++++++++++----
 .../transform/stc/MethodReferenceTest.groovy       | 17 ++++++-
 2 files changed, 61 insertions(+), 10 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
index 9fd304d..f41a37b 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
@@ -19,6 +19,7 @@
 package org.codehaus.groovy.classgen.asm.sc;
 
 import groovy.lang.GroovyRuntimeException;
+import groovy.lang.Tuple;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
@@ -171,7 +172,7 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
         return "new".equals(mrMethodName);
     }
 
-    private boolean isClassExpr(Expression mrExpr) {
+    private static boolean isClassExpr(Expression mrExpr) {
         return mrExpr instanceof ClassExpression;
     }
 
@@ -222,13 +223,11 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
         List<MethodNode> methodNodeList = mrExprType.getMethods(mrMethodName);
         ClassNode classNode = controller.getClassNode();
 
-        MethodNode mrMethodNode = null;
+        List<MethodNode> mrMethodNodeList = new LinkedList<>();
         for (MethodNode mn : filterMethodsByVisibility(methodNodeList, classNode)) {
-
             if (mn.isStatic()) {
                 if (ParameterUtils.parametersEqualWithWrapperType(mn.getParameters(), abstractMethodParameters)) {
-                    mrMethodNode = mn;
-                    break;
+                    mrMethodNodeList.add(mn);
                 }
             } else {
                 if (0 == abstractMethodParameters.length) {
@@ -246,12 +245,49 @@ public class StaticTypesMethodReferenceExpressionWriter extends MethodReferenceE
                 }
 
                 if (ParameterUtils.parametersEqualWithWrapperType(mn.getParameters(), parameters)) {
-                    mrMethodNode = mn;
-                    break;
+                    mrMethodNodeList.add(mn);
                 }
             }
         }
 
-        return mrMethodNode;
+        MethodNode result = chooseMrMethodNodeCandidate(mrExpr, mrMethodNodeList);
+
+        return result;
+    }
+
+    /**
+     * Choose the best method node for method reference.
+     */
+    private MethodNode chooseMrMethodNodeCandidate(Expression mrExpr, List<MethodNode> mrMethodNodeList) {
+        if (1 == mrMethodNodeList.size()) return mrMethodNodeList.get(0);
+
+        return mrMethodNodeList.stream()
+                .map(e -> Tuple.tuple(e, matchingScore(e, mrExpr)))
+                .sorted((t1, t2) -> Integer.compare(t2.getV2(), t1.getV2()))
+                .findFirst()
+                .get()
+                .getV1();
+    }
+
+    private static Integer matchingScore(MethodNode mn, Expression mrExpr) {
+        ClassNode mrExprType = mrExpr.getType();
+
+        int score = 9;
+        for (ClassNode cn = mn.getDeclaringClass(); null != cn && !cn.equals(mrExprType); cn = cn.getSuperClass()) {
+            score--;
+        }
+        if (score < 0) {
+            score = 0;
+        }
+        score *= 10;
+
+        boolean isClassExpr = isClassExpr(mrExpr);
+        boolean isStaticMethod = mn.isStatic();
+
+        if (isClassExpr && isStaticMethod || !isClassExpr && !isStaticMethod) {
+            score += 9;
+        }
+
+        return score;
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index e620ddd..ffe7297 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -38,6 +38,22 @@ class MethodReferenceTest extends GroovyTestCase {
     }
 
     // class::instanceMethod
+    void testFunctionCI_MULTI_MATCHED_METHODS() {
+        assertScript '''
+            import java.util.stream.Collectors
+            
+            @groovy.transform.CompileStatic
+            void p() {
+                def result = [1, 2, 3].stream().map(Integer::toString).collect(Collectors.toList())
+                assert 3 == result.size()
+                assert ['1', '2', '3'] == result
+            }
+            
+            p()
+        '''
+    }
+
+    // class::instanceMethod
     void testBinaryOperatorCI() {
         if (true) return
 
@@ -256,5 +272,4 @@ class MethodReferenceTest extends GroovyTestCase {
 
         '''
     }
-
 }