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


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 386177e4a4 GROOVY-11614: SC: apply enum-case transformation after STC 
visitation
386177e4a4 is described below

commit 386177e4a461854823971e78dbd0524904681d1d
Author: Eric Milles <[email protected]>
AuthorDate: Tue Jul 8 14:41:52 2025 -0500

    GROOVY-11614: SC: apply enum-case transformation after STC visitation
    
    3_0_X backport
---
 .../codehaus/groovy/control/CompilationUnit.java   | 32 --------------------
 .../VariableExpressionTransformer.java             | 16 ++++++++++
 .../transform/stc/EnumTypeCheckingExtension.java   | 35 ++++++++--------------
 src/test/groovy/bugs/Groovy8444.groovy             | 22 +++++++-------
 4 files changed, 40 insertions(+), 65 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java 
b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 39d1882392..7d708b3678 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -22,15 +22,12 @@ import groovy.lang.GroovyClassLoader;
 import groovy.lang.GroovyRuntimeException;
 import groovy.transform.CompilationUnitAware;
 import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.CompileUnit;
 import org.codehaus.groovy.ast.GroovyClassVisitor;
 import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.ModuleNode;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.ClassCompletionVerifier;
 import org.codehaus.groovy.classgen.EnumCompletionVisitor;
@@ -77,11 +74,8 @@ import java.util.Set;
 import java.util.stream.Stream;
 
 import static java.util.stream.Collectors.toList;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
 import static org.codehaus.groovy.runtime.StringGroovyMethods.isAtLeast;
 import static 
org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK;
-import static 
org.codehaus.groovy.transform.stc.StaticTypesMarker.SWITCH_CONDITION_EXPRESSION_TYPE;
 
 /**
  * The CompilationUnit collects all compilation data as it is generated by the 
compiler system.
@@ -310,32 +304,6 @@ public class CompilationUnit extends ProcessingUnit {
                 classNode.removeNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK);
             }
         }, Phases.INSTRUCTION_SELECTION);
-
-        addPhaseOperation((final SourceUnit source, final GeneratorContext 
context, final ClassNode classNode) -> {
-            // TODO: Can this be moved into 
org.codehaus.groovy.transform.sc.transformers.VariableExpressionTransformer?
-            GroovyClassVisitor visitor = new ClassCodeExpressionTransformer() {
-                @Override
-                protected SourceUnit getSourceUnit() {
-                    return source;
-                }
-
-                @Override
-                public Expression transform(final Expression expression) {
-                    if (expression instanceof VariableExpression) {
-                        // check for "switch(enumType) { case CONST: ... }"
-                        ClassNode enumType = 
expression.getNodeMetaData(SWITCH_CONDITION_EXPRESSION_TYPE);
-                        if (enumType != null) {
-                            // replace "CONST" variable expression with 
"EnumType.CONST" property expression
-                            Expression propertyExpression = 
propX(classX(enumType), expression.getText());
-                            setSourcePosition(propertyExpression, expression);
-                            return propertyExpression;
-                        }
-                    }
-                    return expression;
-                }
-            };
-            visitor.visitClass(classNode);
-        }, Phases.INSTRUCTION_SELECTION);
     }
 
     private void applyCompilationCustomizers() {
diff --git 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java
 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java
index cd90269c40..fb41d33248 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java
@@ -41,6 +41,9 @@ public class VariableExpressionTransformer {
 
     public Expression transformVariableExpression(final VariableExpression ve) 
{
         Expression xe = tryTransformImplicitReceiver(ve);
+        if (xe == null) {
+            xe = tryTransformEnumConstantAccess(ve);
+        }
         if (xe == null) {
             xe = tryTransformPrivateFieldAccess(ve);
         }
@@ -81,6 +84,19 @@ public class VariableExpressionTransformer {
         return pe;
     }
 
+    private static Expression tryTransformEnumConstantAccess(final 
VariableExpression ve) {
+        ClassNode enumType = 
ve.getNodeMetaData(StaticTypesMarker.SWITCH_CONDITION_EXPRESSION_TYPE);
+        if (enumType == null) {
+            return null;
+        }
+
+        // GROOVY-8444, GROOVY-11614: replace "CONST" expression with an 
"EnumType.CONST" expression
+        PropertyExpression pe = propX(classX(enumType), ve.getText());
+        pe.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, enumType);
+        pe.getProperty().setSourcePosition(ve);
+        return pe;
+    }
+
     private static Expression tryTransformPrivateFieldAccess(final 
VariableExpression ve) {
         FieldNode field = 
ve.getNodeMetaData(StaticTypesMarker.PV_FIELDS_ACCESS);
         if (field == null) {
diff --git 
a/src/main/java/org/codehaus/groovy/transform/stc/EnumTypeCheckingExtension.java
 
b/src/main/java/org/codehaus/groovy/transform/stc/EnumTypeCheckingExtension.java
index e798f27ea2..d1e5b241b9 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/EnumTypeCheckingExtension.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/EnumTypeCheckingExtension.java
@@ -23,43 +23,32 @@ import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.SwitchStatement;
 
-import java.lang.reflect.Modifier;
-
-import static 
org.codehaus.groovy.transform.stc.StaticTypesMarker.SWITCH_CONDITION_EXPRESSION_TYPE;
-
 /**
- * A type checking extension that will take care of handling errors which are 
specific to enums. In particular, it will
- * handle the enum constants within switch-case statement.
+ * A type checking extension that will take care of handling errors which are
+ * specific to enums. In particular, it will handle the enum constants within
+ * a switch's case statements.
  *
  * @since 3.0.0
  */
 public class EnumTypeCheckingExtension extends TypeCheckingExtension {
-    public EnumTypeCheckingExtension(StaticTypeCheckingVisitor 
staticTypeCheckingVisitor) {
+
+    public EnumTypeCheckingExtension(final StaticTypeCheckingVisitor 
staticTypeCheckingVisitor) {
         super(staticTypeCheckingVisitor);
     }
 
     @Override
-    public boolean handleUnresolvedVariableExpression(VariableExpression vexp) 
{
+    public boolean handleUnresolvedVariableExpression(final VariableExpression 
vexp) {
         SwitchStatement switchStatement = 
this.typeCheckingVisitor.typeCheckingContext.getEnclosingSwitchStatement();
-
-        if (null == switchStatement) return false;
-
-        ClassNode type = 
switchStatement.getExpression().getNodeMetaData(StaticTypesMarker.TYPE);
-
-        if (null == type) return false;
-
-        if (type.isEnum()) {
-            FieldNode fieldNode = type.redirect().getField(vexp.getName());
-            if (null != fieldNode) {
-                int modifiers = fieldNode.getModifiers();
-                if (Modifier.isPublic(modifiers) && 
Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)
-                        && type.equals(fieldNode.getType())) {
-                    vexp.putNodeMetaData(SWITCH_CONDITION_EXPRESSION_TYPE, 
type);
+        if (switchStatement != null) {
+            ClassNode type = 
switchStatement.getExpression().getNodeMetaData(StaticTypesMarker.TYPE);
+            if (type != null && type.isEnum()) {
+                FieldNode fieldNode = type.redirect().getField(vexp.getName());
+                if (fieldNode != null && fieldNode.isEnum()) {
+                    
vexp.putNodeMetaData(StaticTypesMarker.SWITCH_CONDITION_EXPRESSION_TYPE, type);
                     return true;
                 }
             }
         }
-
         return false;
     }
 }
diff --git a/src/test/groovy/bugs/Groovy8444.groovy 
b/src/test/groovy/bugs/Groovy8444.groovy
index bb104e177e..e73fc98634 100644
--- a/src/test/groovy/bugs/Groovy8444.groovy
+++ b/src/test/groovy/bugs/Groovy8444.groovy
@@ -19,6 +19,8 @@
 package groovy.bugs
 
 import groovy.transform.CompileStatic
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
 import org.junit.Test
 
 import static groovy.test.GroovyAssert.assertScript
@@ -29,11 +31,13 @@ final class Groovy8444 {
 
     @Test
     void testAccessingEnumConstantInSwitchCase() {
-        assertScript '''\
+        def shell = new GroovyShell(new CompilerConfiguration().tap {
+            addCompilationCustomizers(new 
ASTTransformationCustomizer(CompileStatic))
+        })
+        shell.evaluate '''\
             enum SomeEnum {
                 A, B
             }
-            @groovy.transform.CompileStatic
             def meth(SomeEnum e) {
                 switch (e) {
                     case A: return 1
@@ -90,7 +94,7 @@ final class Groovy8444 {
         def err = shouldFail '''\
             enum SomeEnum {
                 A, B
-                
+
                 static final String C = 'C'
             }
             @groovy.transform.CompileStatic
@@ -111,7 +115,7 @@ final class Groovy8444 {
         def err = shouldFail '''\
             enum SomeEnum {
                 A, B
-                
+
                 SomeEnum C = A
             }
             @groovy.transform.CompileStatic
@@ -132,7 +136,7 @@ final class Groovy8444 {
         def err = shouldFail '''\
             enum SomeEnum {
                 A, B
-                
+
                 static SomeEnum C = A
             }
             @groovy.transform.CompileStatic
@@ -153,7 +157,7 @@ final class Groovy8444 {
         def err = shouldFail '''\
             enum SomeEnum {
                 A, B
-                
+
                 static final SomeEnum C = A
             }
             @groovy.transform.CompileStatic
@@ -178,7 +182,7 @@ final class Groovy8444 {
             @groovy.transform.CompileStatic
             def meth(SomeEnum e) {
                 switch (e) {
-                    case A: 
+                    case A:
                         switch(e) {
                             case A: return 1.1
                             case B: return 1.2
@@ -207,7 +211,7 @@ final class Groovy8444 {
             @groovy.transform.CompileStatic
             def meth(SomeEnum e, OtherEnum e2) {
                 switch (e) {
-                    case A: 
+                    case A:
                         switch(e2) {
                             case C: return 1.1
                             case D: return 1.2
@@ -225,6 +229,4 @@ final class Groovy8444 {
             assert 2.2 == meth(SomeEnum.B, OtherEnum.D)
         '''
     }
-
-
 }

Reply via email to