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 2025/04/07 15:26:12 UTC

(groovy) branch master updated (f2d3aace3b -> e87063ff20)

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

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


    from f2d3aace3b GROOVY-11229: limit scope of `instanceof` variable
     new c33c9c98b0 GROOVY-11600: inner enum, trait, record, interface or annotation: static
     new e87063ff20 GROOVY-11600: no implicit outer class argument on inner record ctor call

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 11 ++++------
 .../java/org/codehaus/groovy/antlr/EnumHelper.java |  2 +-
 .../org/codehaus/groovy/ast/InnerClassNode.java    |  8 ++++---
 .../org/codehaus/groovy/classgen/EnumVisitor.java  |  2 --
 .../groovy/classgen/InnerClassVisitorHelper.java   |  5 +++--
 .../transform/trait/TraitASTTransformation.java    |  3 ++-
 src/test/gls/innerClass/InnerClassTest.groovy      | 25 ++++++++++++++++++++++
 .../transform/stc/ConstructorsSTCTest.groovy       | 16 ++++++++++++++
 8 files changed, 56 insertions(+), 16 deletions(-)


(groovy) 02/02: GROOVY-11600: no implicit outer class argument on inner record ctor call

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e87063ff20f1de5c0e265ab7ddbd9f45034d89a7
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Apr 4 20:44:03 2025 -0500

    GROOVY-11600: no implicit outer class argument on inner record ctor call
---
 .../groovy/classgen/InnerClassVisitorHelper.java         |  5 +++--
 src/test/groovy/transform/stc/ConstructorsSTCTest.groovy | 16 ++++++++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
index e508caa945..32c5395164 100644
--- a/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/InnerClassVisitorHelper.java
@@ -96,7 +96,8 @@ public abstract class InnerClassVisitorHelper extends ClassCodeVisitorSupport {
     }
 
     protected static boolean shouldHandleImplicitThisForInnerClass(final ClassNode cn) {
-        final int explicitOrImplicitStatic = Opcodes.ACC_STATIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ENUM;
-        return (cn.getModifiers() & explicitOrImplicitStatic) == 0 && (cn instanceof InnerClassNode && !((InnerClassNode) cn).isAnonymous());
+        final int explicitOrImplicitStatic = Opcodes.ACC_ENUM | Opcodes.ACC_INTERFACE | Opcodes.ACC_RECORD | Opcodes.ACC_STATIC;
+        return (cn.getModifiers() & explicitOrImplicitStatic) == 0 && (cn instanceof InnerClassNode && !((InnerClassNode) cn).isAnonymous())
+                && cn.getAnnotations().stream().noneMatch(aNode -> "groovy.transform.RecordType".equals(aNode.getClassNode().getName())); // GROOVY-11600
     }
 }
diff --git a/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy b/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy
index d8424bfe4c..80c0bc5b53 100644
--- a/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy
@@ -603,6 +603,22 @@ class ConstructorsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-11600
+    void testInnerRecordConstructorCall() {
+        assertScript '''
+            class C {
+                record R(int i, Number n) {
+                }
+                void test() {
+                    def r = new C.R(1,2)
+                    assert r.i() == 1
+                    assert r.n() == 2
+                }
+            }
+            new C().test()
+        '''
+    }
+
     // GROOVY-11274
     void testPrivateDefaultConstructor() {
         shouldFailWithMessages '''


(groovy) 01/02: GROOVY-11600: inner enum, trait, record, interface or annotation: static

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c33c9c98b0ac71d9b8c7e28c6685f98821953f89
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Apr 4 20:02:22 2025 -0500

    GROOVY-11600: inner enum, trait, record, interface or annotation: static
---
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 11 ++++------
 .../java/org/codehaus/groovy/antlr/EnumHelper.java |  2 +-
 .../org/codehaus/groovy/ast/InnerClassNode.java    |  8 ++++---
 .../org/codehaus/groovy/classgen/EnumVisitor.java  |  2 --
 .../transform/trait/TraitASTTransformation.java    |  3 ++-
 src/test/gls/innerClass/InnerClassTest.groovy      | 25 ++++++++++++++++++++++
 6 files changed, 37 insertions(+), 14 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 2bef2bb19e..b3065ed17c 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -1255,8 +1255,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
                     null,
                     outerClass
             );
-        } else if (asBoolean(outerClass)) {
-            if (outerClass.isInterface()) modifiers |= Opcodes.ACC_STATIC;
+        } else if (outerClass != null) {
             classNode = new InnerClassNode(
                     outerClass,
                     outerClass.getName() + "$" + className,
@@ -1317,20 +1316,18 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> {
             this.checkUsingGenerics(classNode);
 
         } else if (isInterface) {
-            classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT);
+            classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | (outerClass != null ? Opcodes.ACC_STATIC : 0));
             classNode.setInterfaces(this.visitTypeList(ctx.scs));
             this.checkUsingGenerics(classNode);
             this.hackMixins(classNode);
 
         } else if (isEnum || isRecord) {
+            if (isRecord) this.transformRecordHeaderToProperties(ctx, classNode);
             classNode.setInterfaces(this.visitTypeList(ctx.is));
             this.checkUsingGenerics(classNode);
-            if (isRecord) {
-                this.transformRecordHeaderToProperties(ctx, classNode);
-            }
 
         } else if (isAnnotation) {
-            classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_ANNOTATION);
+            classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_ANNOTATION | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | (outerClass != null ? Opcodes.ACC_STATIC : 0));
             classNode.addInterface(ClassHelper.Annotation_TYPE);
             this.hackMixins(classNode);
 
diff --git a/src/main/java/org/codehaus/groovy/antlr/EnumHelper.java b/src/main/java/org/codehaus/groovy/antlr/EnumHelper.java
index 9299a98df3..5c17078b93 100644
--- a/src/main/java/org/codehaus/groovy/antlr/EnumHelper.java
+++ b/src/main/java/org/codehaus/groovy/antlr/EnumHelper.java
@@ -35,7 +35,7 @@ public class EnumHelper {
         if (outerClass == null) {
             enumClass = new ClassNode(name, modifiers | Opcodes.ACC_ENUM, null, interfaces, MixinNode.EMPTY_ARRAY);
         } else {
-            enumClass = new InnerClassNode(outerClass, outerClass.getName() + "$" + name, modifiers | Opcodes.ACC_ENUM, null, interfaces, MixinNode.EMPTY_ARRAY);
+            enumClass = new InnerClassNode(outerClass, outerClass.getName() + "$" + name, modifiers | Opcodes.ACC_ENUM | Opcodes.ACC_STATIC, null, interfaces, MixinNode.EMPTY_ARRAY);
         }
 
         // enum E extends java.lang.Enum<E>
diff --git a/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java b/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java
index 8c1019cb2c..f8649503fc 100644
--- a/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/InnerClassNode.java
@@ -18,6 +18,8 @@
  */
 package org.codehaus.groovy.ast;
 
+import org.objectweb.asm.Opcodes;
+
 /**
  * Represents an inner class definition.
  */
@@ -30,7 +32,7 @@ public class InnerClassNode extends ClassNode {
     /**
      * @param name is the full name of the class
      * @param modifiers the modifiers, @see org.objectweb.asm.Opcodes
-     * @param superClass the base class name - use "java.lang.Object" if no direct base class
+     * @param superClass the base class name; use "java.lang.Object" if no direct base class
      */
     public InnerClassNode(ClassNode outerClass, String name, int modifiers, ClassNode superClass) {
         this(outerClass, name, modifiers, superClass, ClassNode.EMPTY_ARRAY, MixinNode.EMPTY_ARRAY);
@@ -39,10 +41,10 @@ public class InnerClassNode extends ClassNode {
     /**
      * @param name is the full name of the class
      * @param modifiers the modifiers, @see org.objectweb.asm.Opcodes
-     * @param superClass the base class name - use "java.lang.Object" if no direct base class
+     * @param superClass the base class name; use "java.lang.Object" if no direct base class
      */
     public InnerClassNode(ClassNode outerClass, String name, int modifiers, ClassNode superClass, ClassNode[] interfaces, MixinNode[] mixins) {
-        super(name, modifiers, superClass, interfaces, mixins);
+        super(name, modifiers | (outerClass != null && outerClass.isInterface() ? Opcodes.ACC_STATIC : 0), superClass, interfaces, mixins);
         if (outerClass != null) outerClass.addInnerClass(this);
         this.outerClass = outerClass;
     }
diff --git a/src/main/java/org/codehaus/groovy/classgen/EnumVisitor.java b/src/main/java/org/codehaus/groovy/classgen/EnumVisitor.java
index ab22c7ca25..95d82d0c7d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/EnumVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/EnumVisitor.java
@@ -141,8 +141,6 @@ public class EnumVisitor extends ClassCodeVisitorSupport {
 
             addMethods(enumClass, values, minValue, maxValue);
 
-            // for now, inner enum is always static
-            if (isInnerClass) enumClass.setModifiers(enumClass.getModifiers() | ACC_STATIC);
             if (isAnyAbstract(enumClass)) enumClass.setModifiers(enumClass.getModifiers() | ACC_ABSTRACT);
             else if (isNotExtended(enumClass)) enumClass.setModifiers(enumClass.getModifiers() | ACC_FINAL);
         }
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
index dde69b9efe..addd4c5f14 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -184,7 +184,8 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
     }
 
     private ClassNode createHelperClass(final ClassNode cNode) {
-        cNode.setModifiers(ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE);
+        cNode.setModifiers(ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE
+                | (cNode.getOuterClass() != null ? ACC_STATIC : 0)); // GROOVY-11600
 
         ClassNode helper = new InnerClassNode(
                 cNode,
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index e36c5f42d7..f28d8d747a 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -341,6 +341,31 @@ final class InnerClassTest {
         '''
     }
 
+    // GROOVY-11600
+    @Test
+    void testInnerEnumOrRecordOrInterfaceHasStaticModifier() {
+        assertScript '''
+            import static java.lang.reflect.Modifier.*
+
+            class C {
+                enum E {}
+                class C {}
+                trait T {}
+                record R() {}
+                interface I {}
+                @interface A {}
+            }
+
+            assert  isStatic(C.E.modifiers)
+            assert !isStatic(C.C.modifiers)
+            assert  isStatic(C.T.modifiers)
+            assert  isStatic(C.R.modifiers)
+            assert  isFinal (C.R.modifiers)
+            assert  isStatic(C.I.modifiers)
+            assert  isStatic(C.A.modifiers)
+        '''
+    }
+
     @Test
     void testStaticInnerClass() {
         assertScript '''