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