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

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


The following commit(s) were added to refs/heads/master by this push:
     new d77d909df2 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
d77d909df2 is described below

commit d77d909df28896a21fe4958a201f98c891d5cb51
Author: Paul King <[email protected]>
AuthorDate: Thu Apr 17 16:14:34 2025 +1000

    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
---
 .../codehaus/groovy/control/CompilationUnit.java   |   9 +
 src/test/groovy/bugs/Groovy8444.groovy             | 208 +++++++++++++++++++++
 2 files changed, 217 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java 
b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 23d97ca6ce..5665a6d8d4 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;
@@ -372,6 +374,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 26b411d26e..dedd9823ff 100644
--- a/src/test/groovy/bugs/Groovy8444.groovy
+++ b/src/test/groovy/bugs/Groovy8444.groovy
@@ -223,4 +223,212 @@ final class Groovy8444 {
             assert 2.2 == meth(SomeEnum.B, OtherEnum.D)
         '''
     }
+
+    @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