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

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


The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
     new be6a0d7fba GROOVY-11292, GROOVY-11750: non-sealed super class
be6a0d7fba is described below

commit be6a0d7fbaed722889b2160c3168a305ffaa17c0
Author: Eric Milles <[email protected]>
AuthorDate: Tue Sep 2 11:26:11 2025 -0500

    GROOVY-11292, GROOVY-11750: non-sealed super class
    
    4_0_X backport
---
 .github/workflows/groovy-build-test-ea.yml         |  6 +-
 .github/workflows/groovy-build-test.yml            |  2 +-
 .../groovy/classgen/ClassCompletionVerifier.java   | 12 +--
 src/test/groovy/bugs/Groovy11292.groovy            | 90 ++++++++++++++++++++++
 .../groovy/groovy/BreakContinueLabelTest.groovy    |  4 +-
 5 files changed, 102 insertions(+), 12 deletions(-)

diff --git a/.github/workflows/groovy-build-test-ea.yml 
b/.github/workflows/groovy-build-test-ea.yml
index 4a70f0a0d9..49d0d7f309 100644
--- a/.github/workflows/groovy-build-test-ea.yml
+++ b/.github/workflows/groovy-build-test-ea.yml
@@ -26,10 +26,8 @@ jobs:
       fail-fast: false
       matrix:
         os: [ubuntu-latest]
-        java: [17]
         # The jdk links of "install-jdk.sh" are sometimes outdated, so we have 
to download openjdk releases from https://jdk.java.net/ by ourselves.
-        jdk: 
["https://download.java.net/java/GA/jdk20/bdc68b4b9cbc4ebcb30745c85038d91d/36/GPL/openjdk-20_linux-x64_bin.tar.gz";,
-              
"https://download.java.net/java/GA/jdk21/fd2272bbf8e04c3dbaee13770090416c/35/GPL/openjdk-21_linux-x64_bin.tar.gz";]
+        jdk: 
['https://download.java.net/java/early_access/jdk25/15/GPL/openjdk-25-ea+15_linux-x64_bin.tar.gz']
     runs-on: ${{ matrix.os }}
     env:
       DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
@@ -43,8 +41,8 @@ jobs:
         uses: actions/setup-java@v3
         with:
           distribution: 'zulu'
-          java-version: ${{ matrix.java }}
           check-latest: true
+          java-version: 17
       - uses: gradle/gradle-build-action@v2
       - name: Test with Gradle
         run: ./gradlew test -Ptarget.java.home=/home/runner/openjdk
diff --git a/.github/workflows/groovy-build-test.yml 
b/.github/workflows/groovy-build-test.yml
index 4fed3ba4ef..72cb68a5b5 100644
--- a/.github/workflows/groovy-build-test.yml
+++ b/.github/workflows/groovy-build-test.yml
@@ -53,7 +53,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        java: [9, 10, 12, 13, 14, 15, 16, 18, 19, 20, 22, 23]
+        java: [9, 10, 12, 13, 14, 15, 16, 18, 19, 20, 22, 23, 24]
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java 
b/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java
index f749f96711..bbdd5a7add 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java
@@ -18,8 +18,6 @@
  */
 package org.codehaus.groovy.classgen;
 
-import groovy.transform.NonSealed;
-import groovy.transform.Sealed;
 import org.apache.groovy.ast.tools.AnnotatedNodeUtils;
 import org.apache.groovy.ast.tools.ClassNodeUtils;
 import org.codehaus.groovy.ast.ASTNode;
@@ -317,7 +315,7 @@ public class ClassCompletionVerifier extends 
ClassCodeVisitorSupport {
     }
 
     private void checkClassForExtendingFinalOrSealed(final ClassNode cn) {
-        boolean sealed = Boolean.TRUE.equals(cn.getNodeMetaData(Sealed.class));
+        boolean sealed = 
Boolean.TRUE.equals(cn.getNodeMetaData(groovy.transform.Sealed.class));
         if (sealed && cn.getPermittedSubclasses().isEmpty()) {
             addError("Sealed " + getDescription(cn) + " has no explicit or 
implicit permitted subclasses.", cn);
             return;
@@ -362,8 +360,12 @@ public class ClassCompletionVerifier extends 
ClassCodeVisitorSupport {
         addError("You are not allowed to extend the final " + 
getDescription(superCN) + ".", cn);
     }
 
-    private boolean nonSealed(final ClassNode node) {
-        return Boolean.TRUE.equals(node.getNodeMetaData(NonSealed.class));
+    private boolean nonSealed(final ClassNode cn) {
+        if 
(Boolean.TRUE.equals(cn.getNodeMetaData(groovy.transform.NonSealed.class))) {
+            return true;
+        }
+        ClassNode sc = cn.getSuperClass(); // GROOVY-11292, GROOVY-11750: 
check super class
+        return (sc != null && sc.isSealed() && !(cn.isSealed() || 
isFinal(cn.getModifiers())));
     }
 
     private void checkSealedParent(final ClassNode cn, final ClassNode parent) 
{
diff --git a/src/test/groovy/bugs/Groovy11292.groovy 
b/src/test/groovy/bugs/Groovy11292.groovy
new file mode 100644
index 0000000000..07c167b1d8
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy11292.groovy
@@ -0,0 +1,90 @@
+/*
+ *  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 bugs
+
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.isAtLeastJdk
+import static org.junit.Assume.assumeTrue
+
+final class Groovy11292 {
+
+    @Test
+    void testClassWithNonSealedParent1() {
+        assumeTrue(isAtLeastJdk('17.0'))
+
+        def config = new CompilerConfiguration(
+            targetDirectory: File.createTempDir(),
+            jointCompilationOptions: [memStub: true]
+        )
+
+        def parentDir = File.createTempDir()
+        try {
+            def a = new File(parentDir, 'A.java')
+            a.write '''
+                public sealed class A permits B {}
+            '''
+            def b = new File(parentDir, 'B.java')
+            b.write '''
+                public non-sealed class B extends A {}
+            '''
+            def c = new File(parentDir, 'C.groovy')
+            c.write '''
+                class C extends B {}
+            '''
+            def d = new File(parentDir, 'D.groovy')
+            d.write '''
+                class D extends C {}
+            '''
+            def e = new File(parentDir, 'E.groovy')
+            e.write '''
+                class E extends B {}
+            '''
+            def f = new File(parentDir, 'F.groovy')
+            f.write '''
+                class F extends E {}
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b, c, d, e, f)
+            cu.compile()
+        } finally {
+            config.targetDirectory.deleteDir()
+            parentDir.deleteDir()
+        }
+    }
+
+    @Test
+    void testClassWithNonSealedParent2() {
+        assertScript '''import java.lang.ref.SoftReference // non-sealed type
+
+            class TestReference<T> extends SoftReference<T> {
+                TestReference(T referent) {
+                    super(referent)
+                }
+            }
+
+            assert new TestReference(null)
+        '''
+    }
+}
diff --git a/src/test/groovy/groovy/BreakContinueLabelTest.groovy 
b/src/test/groovy/groovy/BreakContinueLabelTest.groovy
index 703fb7ffdb..f500cfd313 100644
--- a/src/test/groovy/groovy/BreakContinueLabelTest.groovy
+++ b/src/test/groovy/groovy/BreakContinueLabelTest.groovy
@@ -18,9 +18,9 @@
  */
 package groovy
 
-import org.junit.jupiter.api.Test
+import org.junit.Test
 
-import static org.junit.jupiter.api.Assertions.fail
+import static org.junit.Assert.fail
 
 final class BreakContinueLabelTest {
 

Reply via email to