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/02/24 16:24:35 UTC

[groovy] 02/04: GROOVY-9259: interface w/ `default` supports `extends` for interface(s)

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 06fbe4371108ee81927e7709399c298834728c1c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Feb 19 16:48:23 2022 -0600

    GROOVY-9259: interface w/ `default` supports `extends` for interface(s)
    
    Conflicts:
    	src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
---
 src/test/groovy/bugs/Groovy9259.groovy             | 109 +++++++++++++++++++++
 .../apache/groovy/parser/antlr4/AstBuilder.java    |  13 ++-
 2 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/src/test/groovy/bugs/Groovy9259.groovy b/src/test/groovy/bugs/Groovy9259.groovy
new file mode 100644
index 0000000..2fdf302
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9259.groovy
@@ -0,0 +1,109 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+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
+
+final class Groovy9259 {
+
+    @Test
+    void testInterfaceAndTrait() {
+        def config = new CompilerConfiguration(
+            targetDirectory: File.createTempDir(),
+            jointCompilationOptions: [memStub: true]
+        )
+
+        def parentDir = File.createTempDir()
+        try {
+            def a = new File(parentDir, 'J.java')
+            a.write '''
+                public interface J {
+                    String m();
+                }
+            '''
+            def b = new File(parentDir, 'G.groovy')
+            b.write '''
+                interface G extends J {
+                    default String m() {
+                        'G'
+                    }
+                }
+            '''
+            def c = new File(parentDir, 'Main.groovy')
+            c.write '''
+                class C implements G {
+                    @Override String m() {
+                        'C'
+                    }
+                }
+
+                @groovy.transform.CompileStatic
+                void test() {
+                    J obj = new C()
+                    def x = obj.m()
+                    assert x == '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').main()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+        }
+    }
+
+    @Test
+    void testInterfacesAndTrait() {
+        assertScript '''
+            interface A {
+                String m()
+            }
+            interface B {
+                String m()
+            }
+            interface C extends A, B {
+                default String m() {
+                    'C'
+                }
+            }
+
+            @groovy.transform.CompileStatic
+            void test() {
+                A one = new C() {}
+                def x = one.m()
+                assert x == 'C'
+
+                B two = new C() {}
+                def y = two.m()
+                assert y == 'C'
+            }
+            test()
+        '''
+    }
+}
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 2029a5d..6d4e23b 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -1011,24 +1011,23 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
         }
         classNode.putNodeMetaData(CLASS_NAME, className);
 
-        if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT()) || isInterfaceWithDefaultMethods) {
-            ClassNode superClass;
+        if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT())) {
             if (asBoolean(ctx.scs)) {
                 ClassNode[] scs = this.visitTypeList(ctx.scs);
                 if (scs.length > 1) {
                     throw createParsingFailedException("Cannot extend multiple classes", ctx.EXTENDS());
                 }
-                superClass = scs[0];
-            } else {
-                superClass = ClassHelper.OBJECT_TYPE;
+                classNode.setSuperClass(scs[0]);
             }
-            classNode.setSuperClass(superClass);
             classNode.setInterfaces(this.visitTypeList(ctx.is));
             this.initUsingGenerics(classNode);
 
+        } else if (isInterfaceWithDefaultMethods) { // GROOVY-9259
+            classNode.setInterfaces(this.visitTypeList(ctx.scs));
+            this.initUsingGenerics(classNode);
+
         } else if (isInterface) {
             classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT);
-            classNode.setSuperClass(ClassHelper.OBJECT_TYPE);
             classNode.setInterfaces(this.visitTypeList(ctx.scs));
             this.initUsingGenerics(classNode);
             this.hackMixins(classNode);