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/01/30 20:43:26 UTC

[groovy] 04/04: GROOVY-10379: interface default methods in `ClassNode#hasPossibleMethod`

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

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

commit 287a174e26c927f23b8237c983de8b551ab280ca
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Nov 23 12:13:14 2021 -0600

    GROOVY-10379: interface default methods in `ClassNode#hasPossibleMethod`
---
 .../java/org/codehaus/groovy/ast/ClassNode.java    |  7 +++
 src/test/groovy/bugs/Groovy8964.groovy             | 51 ++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
index 896b769..4769125 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -1264,6 +1264,13 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
                     return true;
                 }
             }
+            for (ClassNode in : cn.getAllInterfaces()) {
+                for (MethodNode mn : in.getDeclaredMethods(name)) {
+                    if (mn.isDefault() && hasCompatibleNumberOfArgs(mn, count)) {
+                        return true;
+                    }
+                }
+            }
         }
 
         return false;
diff --git a/src/test/groovy/bugs/Groovy8964.groovy b/src/test/groovy/bugs/Groovy8964.groovy
index 0a0e13a..df154e8 100644
--- a/src/test/groovy/bugs/Groovy8964.groovy
+++ b/src/test/groovy/bugs/Groovy8964.groovy
@@ -18,6 +18,8 @@
  */
 package groovy.bugs
 
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
 import org.junit.Test
 
 import static groovy.test.GroovyAssert.assertScript
@@ -77,6 +79,55 @@ final class Groovy8964 {
         '''
     }
 
+    @Test // GROOVY-10379
+    void testInstanceMethodNotMaskedByStaticMethodWithSameNumberOfArgs3() {
+        def config = new CompilerConfiguration(
+            targetDirectory: File.createTempDir(),
+            jointCompilationOptions: [memStub: true]
+        )
+
+        def parentDir = File.createTempDir()
+        try {
+            new File(parentDir, 'p').mkdir()
+
+            def a = new File(parentDir, 'p/A.java')
+            a.write '''
+                package p;
+                public abstract class A implements I {
+                    public static String m(Number n) { return "number"; }
+                }
+            '''
+            def b = new File(parentDir, 'p/I.java')
+            b.write '''
+                package p;
+                public interface I {
+                    default String m(String s) { return "string"; }
+                }
+            '''
+            def c = new File(parentDir, 'Main.groovy')
+            c.write '''
+                @groovy.transform.CompileStatic
+                class C extends p.A {
+                    void test() {
+                        String result = m('') // GroovyCastException: Cannot cast object 'class C' with class 'java.lang.Class' to class 'p.I'
+                        assert result == 'string'
+                    }
+                }
+                new C().test()
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b, c)
+            cu.compile()
+
+            loader.loadClass('Main').getDeclaredConstructor().newInstance().run()
+        } finally {
+            config.targetDirectory.deleteDir()
+            parentDir.deleteDir()
+        }
+    }
+
     static abstract class A {
         static void m(Integer i) {}
         protected void m(String s) {}