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

blackdrag pushed a commit to branch feature/GROOVY-8299/default_methods
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 796985f78ebd562134a761af2772c60cca2e7632
Author: Jochen Theodorou <blackd...@gmx.org>
AuthorDate: Mon Sep 11 14:38:30 2023 +0200

    GROOVY-8299: implement interfaces with default methods (initial commit)
---
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 10 +---
 .../groovy/classgen/ClassCompletionVerifier.java   |  2 +-
 .../groovy/lang/DefaultInterfaceMethodsTest.groovy | 54 ++++++++++++++++++++++
 3 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java 
b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 62c08cd53c..add2787794 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -1313,9 +1313,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
         } else if (isNonSealed) {
             classNode.addAnnotation(makeAnnotationNode(NonSealed.class));
         }
-        if (isInterfaceWithDefaultMethods || asBoolean(ctx.TRAIT())) {
-            classNode.addAnnotation(makeAnnotationNode(Trait.class));
-        }
+
         classNode.addAnnotations(modifierManager.getAnnotations());
         if (isRecord && classNode.getAnnotations().stream().noneMatch(a ->
                         a.getClassNode().getName().equals(RECORD_TYPE_NAME))) {
@@ -1338,10 +1336,6 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
             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.setInterfaces(this.visitTypeList(ctx.scs));
@@ -1877,7 +1871,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
 
         }
 
-        modifiers |= !modifierManager.containsAny(STATIC) && 
(classNode.isInterface() || (isTrue(classNode, 
IS_INTERFACE_WITH_DEFAULT_METHODS) && !modifierManager.containsAny(DEFAULT))) ? 
Opcodes.ACC_ABSTRACT : 0;
+        modifiers |= !modifierManager.containsAny(STATIC) && 
classNode.isInterface() && !(isTrue(classNode, 
IS_INTERFACE_WITH_DEFAULT_METHODS) && modifierManager.containsAny(DEFAULT)) ? 
Opcodes.ACC_ABSTRACT : 0;
         MethodNode methodNode = new MethodNode(methodName, modifiers, 
returnType, parameters, exceptions, code);
         classNode.addMethod(methodNode);
 
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java 
b/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java
index 8ff9c1ef00..43abd86f23 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java
@@ -310,7 +310,7 @@ public class ClassCompletionVerifier extends 
ClassCodeVisitorSupport {
     }
 
     private void checkAbstractDeclaration(final MethodNode methodNode) {
-        if (!methodNode.isAbstract() || currentClass.isAbstract()) return;
+        if (!methodNode.isAbstract() || currentClass.isAbstract() || 
methodNode.isDefault()) return;
 
         addError("Can't have an abstract method in a non-abstract class." +
                 " The " + getDescription(currentClass) + " must be declared 
abstract or the method '" +
diff --git a/src/test/groovy/lang/DefaultInterfaceMethodsTest.groovy 
b/src/test/groovy/lang/DefaultInterfaceMethodsTest.groovy
new file mode 100644
index 0000000000..bc833b8069
--- /dev/null
+++ b/src/test/groovy/lang/DefaultInterfaceMethodsTest.groovy
@@ -0,0 +1,54 @@
+/*
+ *  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.lang
+
+import groovy.test.GroovyTestCase
+
+/**
+ * Test for the BenchmarkInterceptor
+ */
+class DefaultInterfaceMethodsTest extends GroovyTestCase {
+
+    void testSimpleDeclarationAndCall() {
+        assertScript '''
+            public interface InterfaceWithDefault {
+                default String hello() {
+                    return 'Hello'
+                }
+            }
+            class UseDefault implements InterfaceWithDefault {}
+            assert new UseDefault().hello() == 'Hello'
+        '''
+    }
+    void testSimpleDeclarationAndOverride() {
+        assertScript '''
+            public interface InterfaceWithDefault {
+                default String hello() {
+                    return 'Hello'
+                }
+            }
+            class OverrideDefault implements InterfaceWithDefault {
+                public String hello() {
+                    return 'Bon jour'
+                }
+            }
+            assert new OverrideDefault().hello() == 'Bon jour'
+        '''
+    }
+}

Reply via email to