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 2022/11/03 18:44:46 UTC

[groovy] branch GROOVY_2_5_X updated: GROOVY-7025: cannot refer to non-constant static field in `enum` init

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

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


The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
     new 9e62ab73ee GROOVY-7025: cannot refer to non-constant static field in `enum` init
9e62ab73ee is described below

commit 9e62ab73ee36110745a5f76b066fe5d4eedeedd0
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 3 12:12:40 2022 -0500

    GROOVY-7025: cannot refer to non-constant static field in `enum` init
---
 .../groovy/classgen/VariableScopeVisitor.java      | 23 +++++++----
 src/test/gls/CompilableTestSupport.groovy          | 31 +++++++++-----
 src/test/gls/enums/EnumTest.groovy                 | 47 +++++++++++++++++++++-
 3 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 5c8a0b774a..f66d3535aa 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -296,17 +296,24 @@ public class VariableScopeVisitor extends ClassCodeVisitorSupport {
         checkVariableContextAccess(member, pe);
     }
 
-    private void checkVariableContextAccess(Variable v, Expression expr) {
-        if (v.isInStaticContext() || !currentScope.isInStaticContext()) return;
+    private void checkVariableContextAccess(final Variable variable, final Expression expression) {
+        if (variable.isInStaticContext()) {
+            if (inConstructor && currentClass.isEnum() && variable instanceof FieldNode
+                    && currentClass.equals(((FieldNode) variable).getDeclaringClass())) { // GROOVY-7025
+                if (!isFinal(variable.getModifiers()) || !(ClassHelper.isStaticConstantInitializerType(variable.getOriginType())
+                        || "String".equals(variable.getOriginType().getName()))) { // TODO: String requires constant initializer
+                    addError("Cannot refer to the static enum field '" + variable.getName() + "' within an initializer", expression);
+                }
+            }
+            return;
+        }
+
+        if (!currentScope.isInStaticContext()) return;
 
-        String msg = v.getName() +
-                " is declared in a dynamic context, but you tried to" +
-                " access it from a static context.";
-        addError(msg, expr);
+        addError(variable.getName() + " is declared in a dynamic context, but you tried to access it from a static context.", expression);
 
         // declare a static variable to be able to continue the check
-        DynamicVariable v2 = new DynamicVariable(v.getName(), currentScope.isInStaticContext());
-        currentScope.putDeclaredVariable(v2);
+        currentScope.putDeclaredVariable(new DynamicVariable(variable.getName(), currentScope.isInStaticContext()));
     }
 
     // ------------------------------
diff --git a/src/test/gls/CompilableTestSupport.groovy b/src/test/gls/CompilableTestSupport.groovy
index eed62a5190..de6eaa93f9 100644
--- a/src/test/gls/CompilableTestSupport.groovy
+++ b/src/test/gls/CompilableTestSupport.groovy
@@ -18,24 +18,33 @@
  */
 package gls
 
+import groovy.transform.AutoFinal
 import groovy.transform.CompileStatic
 import org.codehaus.groovy.control.CompilationFailedException
 
-@CompileStatic
+import static org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport.closeQuietly
+
+@AutoFinal @CompileStatic
 abstract class CompilableTestSupport extends GroovyTestCase {
-    protected shouldNotCompile(String script) {
+
+    protected String shouldNotCompile(String script) {
+        def gcl = new GroovyClassLoader()
         try {
-            GroovyClassLoader gcl = new GroovyClassLoader()
-            gcl.parseClass(script, getTestClassName())
-        } catch (CompilationFailedException cfe) {
-            return cfe.message
+            gcl.parseClass(script, testClassName)
+        } catch (CompilationFailedException ex) {
+            return ex.message
+        } finally {
+            closeQuietly(gcl)
         }
-        fail("the compilation succeeded but should have failed")
+        fail('the compilation succeeded but should have failed')
     }
 
     protected void shouldCompile(String script) {
-        GroovyClassLoader gcl = new GroovyClassLoader()
-        gcl.parseClass(script, getTestClassName())
-        assert true
+        def gcl = new GroovyClassLoader()
+        try {
+            gcl.parseClass(script, testClassName)
+        } finally {
+            closeQuietly(gcl)
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/gls/enums/EnumTest.groovy b/src/test/gls/enums/EnumTest.groovy
index 79da52fa0f..30965021fe 100644
--- a/src/test/gls/enums/EnumTest.groovy
+++ b/src/test/gls/enums/EnumTest.groovy
@@ -187,7 +187,52 @@ class EnumTest extends CompilableTestSupport {
         assert allColors[2] == GroovyColors3161.green
     }
 
-    // the fix for GROOVY-3283
+    // GROOVY-7025
+    void testStaticEnumFieldFromInit() {
+        def err = shouldNotCompile '''
+            enum E {
+                FOO('bar');
+                private static final Set<String> names = []
+                E(String name) {
+                    names.add(name)
+                }
+            }
+        '''
+        assert err =~ /Cannot refer to the static enum field 'names' within an initializer/
+
+        shouldCompile '''
+            enum E {
+                FOO;
+                private static final String ONE = 1
+                private final value
+                E() {
+                    value = 1 + ONE
+                }
+            }
+        '''
+        shouldCompile '''
+            enum E {
+                FOO;
+                private static final int ONE = 1
+                private final value
+                E() {
+                    value = 1 + ONE
+                }
+            }
+        '''
+        shouldNotCompile '''
+            enum E {
+                FOO;
+                private static int ONE = 1
+                private final value
+                E() {
+                    value = 1 + ONE
+                }
+            }
+        '''
+    }
+
+    // GROOVY-3283
     void testImportStaticMoreThanOneEnum() {
         assertScript """
             enum Foo3283 { A,B }