This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY-11600 in repository https://gitbox.apache.org/repos/asf/groovy.git
commit f915b7bd0e4f26f04993810f0aba5c1e0ea45c6e Author: Eric Milles <[email protected]> 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 '''
