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

sunlan 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 54b5244dd6 GROOVY-11614: Enums in switch/case statements that are not 
fully qualified will cause a groovy compile error for switch expressions even 
with type checking enabled
54b5244dd6 is described below

commit 54b5244dd6a63fbaaeb949446757deb77943480f
Author: Paul King <[email protected]>
AuthorDate: Thu Apr 17 15:14:34 2025 +0900

    GROOVY-11614: Enums in switch/case statements that are not fully qualified 
will cause a groovy compile error for switch expressions even with type 
checking enabled
    
    (cherry picked from commit d77d909df28896a21fe4958a201f98c891d5cb51)
---
 .../codehaus/groovy/control/CompilationUnit.java   |   9 +
 src/test/groovy/bugs/Groovy8444.groovy             | 206 +++++++++++++++++++++
 2 files changed, 215 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java 
b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 4df0164d70..ba51d0bf74 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -30,7 +30,9 @@ 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.ClosureExpression;
 import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.ClassCompletionVerifier;
@@ -366,6 +368,13 @@ public class CompilationUnit extends ProcessingUnit {
                             setSourcePosition(propertyExpression, expression);
                             return propertyExpression;
                         }
+                    } else if (expression instanceof MethodCallExpression) {
+                        // we wrap SwitchExpressions into a method call on a 
ClosureExpression
+                        MethodCallExpression mce = (MethodCallExpression) 
expression;
+                        if (mce.getObjectExpression() instanceof 
ClosureExpression) {
+                            expression.visit(this);
+                            return expression;
+                        }
                     }
                     return expression;
                 }
diff --git a/src/test/groovy/bugs/Groovy8444.groovy 
b/src/test/groovy/bugs/Groovy8444.groovy
index ff22c19def..350b401915 100644
--- a/src/test/groovy/bugs/Groovy8444.groovy
+++ b/src/test/groovy/bugs/Groovy8444.groovy
@@ -226,5 +226,211 @@ final class Groovy8444 {
         '''
     }
 
+    @Test
+    // GROOVY-11614
+    void testAccessingEnumConstantInSwitchExprCase() {
+        assertScript '''\
+            enum SomeEnum {
+                A, B
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch (e) {
+                    case A -> 1
+                    case B -> 2
+                }
+            }
+            assert 1 == meth(SomeEnum.A)
+            assert 2 == meth(SomeEnum.B)
+        '''
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingEnumConstantInSwitchExprCase2() {
+        assertScript '''\
+            enum SomeEnum {
+                A, B
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch (same(e)) {
+                    case A -> 1
+                    case B -> 2
+                }
+            }
+            @groovy.transform.CompileStatic
+            SomeEnum same(SomeEnum e) {
+                return e
+            }
+            assert 1 == meth(SomeEnum.A)
+            assert 2 == meth(SomeEnum.B)
+        '''
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingEnumConstantInSwitchExprCase3() {
+        assertScript '''\
+            enum SomeEnum {
+                A, B
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch ([e][0]) {
+                    case A -> 1
+                    case B -> 2
+                }
+            }
+            assert 1 == meth(SomeEnum.A)
+            assert 2 == meth(SomeEnum.B)
+        '''
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingNonEnumConstantInSwitchExprCase() {
+        def err = shouldFail '''\
+            enum SomeEnum {
+                A, B
+
+                static final String C = 'C'
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch (e) {
+                    case C -> 3
+                }
+            }
+            meth(SomeEnum.C)
+        '''
+
+        assert err.message.contains('[Static type checking] - The variable [C] 
is undeclared')
+        assert err.message.contains('@ line 9, column 26.')
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingNonEnumConstantInSwitchExprCase2() {
+        def err = shouldFail '''\
+            enum SomeEnum {
+                A, B
+
+                SomeEnum C = A
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch (e) {
+                    case C -> 3
+                }
+            }
+            meth(SomeEnum.C)
+        '''
+
+        assert err.message.contains('[Static type checking] - The variable [C] 
is undeclared')
+        assert err.message.contains('@ line 9, column 26.')
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingNonEnumConstantInSwitchExprCase3() {
+        def err = shouldFail '''\
+            enum SomeEnum {
+                A, B
+
+                static SomeEnum C = A
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch (e) {
+                    case C -> 3
+                }
+            }
+            meth(SomeEnum.C)
+        '''
+
+        assert err.message.contains('[Static type checking] - The variable [C] 
is undeclared')
+        assert err.message.contains('@ line 9, column 26.')
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingNonEnumConstantInSwitchExprCase4() {
+        def err = shouldFail '''\
+            enum SomeEnum {
+                A, B
 
+                static final SomeEnum C = A
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch (e) {
+                    case C -> 3
+                }
+            }
+            meth(SomeEnum.C)
+        '''
+
+        assert err.message.contains('[Static type checking] - The variable [C] 
is undeclared')
+        assert err.message.contains('@ line 9, column 26.')
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingEnumConstantInNestedSwitchExprCase() {
+        assertScript '''\
+            enum SomeEnum {
+                A, B
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e) {
+                switch (e) {
+                    case A ->
+                        switch(e) {
+                            case A -> 1.1
+                            case B -> 1.2
+                        }
+                    case B ->
+                        switch(e) {
+                            case A -> 2.1
+                            case B -> 2.2
+                        }
+                }
+            }
+            assert 1.1 == meth(SomeEnum.A)
+            assert 2.2 == meth(SomeEnum.B)
+        '''
+    }
+
+    @Test
+    // GROOVY-11614
+    void testAccessingEnumConstantInNestedSwitchExprCase2() {
+        assertScript '''\
+            enum SomeEnum {
+                A, B
+            }
+            enum OtherEnum {
+                C, D
+            }
+            @groovy.transform.CompileStatic
+            def meth(SomeEnum e, OtherEnum e2) {
+                switch (e) {
+                    case A ->
+                        switch(e2) {
+                            case C -> 1.1
+                            case D -> 1.2
+                        }
+                    case B ->
+                        switch(e2) {
+                            case C -> 2.1
+                            case D -> 2.2
+                        }
+                }
+            }
+            assert 1.1 == meth(SomeEnum.A, OtherEnum.C)
+            assert 1.2 == meth(SomeEnum.A, OtherEnum.D)
+            assert 2.1 == meth(SomeEnum.B, OtherEnum.C)
+            assert 2.2 == meth(SomeEnum.B, OtherEnum.D)
+        '''
+    }
 }

Reply via email to