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 2021/01/18 13:34:17 UTC

[groovy] branch master updated: GROOVY-9890: always search for default methods

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 43c8ef9  GROOVY-9890: always search for default methods
43c8ef9 is described below

commit 43c8ef93605b7a7b5e10649640062c76d88f812a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Jan 17 17:58:13 2021 -0600

    GROOVY-9890: always search for default methods
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 25 ++++---
 src/test/groovy/bugs/groovy9890/Face.java          |  8 +++
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 83 +++++++++++++++++++++-
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   | 12 ----
 4 files changed, 102 insertions(+), 26 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 7d2f5af..cf59147 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2377,7 +2377,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 ClassNode receiverType = wrapTypeIfNecessary(currentReceiver.getType());
 
                 candidates = findMethodsWithGenerated(receiverType, nameText);
-                collectAllInterfaceMethodsByName(receiverType, nameText, candidates);
                 if (isBeingCompiled(receiverType)) candidates.addAll(GROOVY_OBJECT_TYPE.getMethods(nameText));
                 candidates.addAll(findDGMMethodsForClassNode(getTransformLoader(), receiverType, nameText));
                 candidates = filterMethodsByVisibility(candidates, typeCheckingContext.getEnclosingClassNode());
@@ -4565,7 +4564,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      */
     protected List<MethodNode> findMethodsWithGenerated(final ClassNode receiver, final String name) {
         List<MethodNode> methods = receiver.getMethods(name);
-        if (methods.isEmpty() || receiver.isResolved()) return methods;
+        if (receiver.isAbstract()) {
+            collectAllInterfaceMethodsByName(receiver, name, methods);
+        } else { // GROOVY-9890: always search for default methods
+            List<MethodNode> interfaceMethods = new ArrayList<>();
+            collectAllInterfaceMethodsByName(receiver, name, interfaceMethods);
+            interfaceMethods.stream().filter(MethodNode::isDefault).forEach(methods::add);
+        }
+        if (receiver.isInterface()) {
+            methods.addAll(OBJECT_TYPE.getMethods(name));
+        }
+
+        if (methods.isEmpty() || receiver.isResolved()) {
+            return methods;
+        }
         return addGeneratedMethods(receiver, methods);
     }
 
@@ -4644,9 +4656,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         } else {
             methods = findMethodsWithGenerated(receiver, name);
             if (receiver.isInterface()) {
-                collectAllInterfaceMethodsByName(receiver, name, methods);
-                methods.addAll(OBJECT_TYPE.getMethods(name));
-
                 if ("call".equals(name) && isFunctionalInterface(receiver)) {
                     MethodNode sam = findSAM(receiver);
                     MethodNode callMethod = new MethodNode("call", sam.getModifiers(), sam.getReturnType(), sam.getParameters(), sam.getExceptions(), sam.getCode());
@@ -4722,12 +4731,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
         }
 
-        if (methods.isEmpty()) {
-            // look at the interfaces, there's a chance that a method is not implemented and we should not hide the
-            // error from the compiler
-            collectAllInterfaceMethodsByName(receiver, name, methods);
-        }
-
         if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
             // lookup in DGM methods too
             findDGMMethodsByNameAndArguments(getSourceUnit().getClassLoader(), receiver, name, args, methods);
diff --git a/src/test/groovy/bugs/groovy9890/Face.java b/src/test/groovy/bugs/groovy9890/Face.java
new file mode 100644
index 0000000..af8914b
--- /dev/null
+++ b/src/test/groovy/bugs/groovy9890/Face.java
@@ -0,0 +1,8 @@
+package groovy.bugs.groovy9890;
+
+public interface Face {
+    default Object foo(long n) {
+        return n;
+    }
+    Object foo(String s);
+}
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 4c5b818..2d504d5 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -984,14 +984,91 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
             Test.test(null)
         '''
     }
+
     void testShouldFindInheritedInterfaceMethod() {
         assertScript '''
-            interface Top { void close() }
+            interface Top { void foo() }
             interface Middle extends Top {}
             interface Bottom extends Middle {}
-            void foo(Bottom obj) {
-               obj.close()
+
+            void test(Bottom b) {
+               b.foo()
+            }
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod2() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { int foo(String s) }
+            interface Bottom extends Middle {}
+
+            void test(Bottom b) {
+                b.foo(123)
+            }
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod3() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { }
+            interface Bottom extends Middle { int foo(String s) }
+
+            void test(Bottom b) {
+                b.foo(123)
+            }
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod4() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { int foo(String s) }
+            abstract class Bottom implements Middle {}
+
+            int test(Bottom b) {
+                b.foo(123)
+            }
+            def bot = new Bottom() {
+                int foo(int i) { 1 }
+                int foo(String s) { 2 }
+            }
+            assert test(bot) == 1
+        '''
+    }
+
+    void testShouldFindInheritedInterfaceMethod5() {
+        assertScript '''
+            interface Top { int foo(int i) }
+            interface Middle extends Top { }
+            abstract class Bottom implements Middle { abstract int foo(String s) }
+
+            int test(Bottom b) {
+                b.foo(123)
+            }
+            def bot = new Bottom() {
+                int foo(int i) { 1 }
+                int foo(String s) { 2 }
+            }
+            assert test(bot) == 1
+        '''
+    }
+
+    // GROOVY-9890
+    void testShouldFindInheritedInterfaceDefaultMethod() {
+        assertScript '''
+            class Impl implements groovy.bugs.groovy9890.Face {
+                @Override def foo(String s) {
+                    return s
+                }
+                // abstract def foo(long n)
+            }
+            void test() {
+                def result = new Impl().foo(42L)
+                assert result.class == Long.class
             }
+            test()
         '''
     }
 
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
index fa5b0c6..ce5dc88 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -1484,18 +1484,6 @@ println someInt
         '''
     }
 
-    // GROOVY-7160
-    void testGenericsArrayPlaceholder() {
-        assertScript '''
-            import static java.nio.file.AccessMode.*
-            def test() {
-                // more than 5 to match of(E first, E[] rest) variant
-                EnumSet.of(READ, WRITE, EXECUTE, READ, WRITE, EXECUTE)
-            }
-            assert test() == [READ, WRITE, EXECUTE].toSet()
-        '''
-    }
-
     void testNumberWrapperMultiAssign() {
         assertScript '''
             import org.codehaus.groovy.ast.CodeVisitorSupport