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

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

commit 35e4f871ef1efb7b8b9eafd8c79cc702f70a69d0
Author: Eric Milles <[email protected]>
AuthorDate: Sat Apr 19 10:53:25 2025 -0500

    GROOVY-9530: use parsed static field value for constant inlining
---
 .../apache/groovy/ast/tools/ExpressionUtils.java   | 39 ++++++++++---------
 .../ast/decompiled/MemberSignatureParser.java      |  2 +-
 src/test/groovy/bugs/Groovy9530.groovy             | 45 ++++++++++++++++++++++
 3 files changed, 66 insertions(+), 20 deletions(-)

diff --git a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java 
b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
index 178a96e5b6..1731dcbd7d 100644
--- a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
@@ -32,8 +32,6 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.codehaus.groovy.runtime.typehandling.NumberMath;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
 import java.math.BigDecimal;
 import java.util.List;
 import java.util.ListIterator;
@@ -258,6 +256,7 @@ public final class ExpressionUtils {
      *     <li>Binary expressions - string concatenation and numeric +, -, /, 
*</li>
      *     <li>List expressions - list of constants</li>
      * </ul>
+     *
      * @param exp the original expression
      * @param attrType the type that the final constant should be
      * @return the transformed type or the original if no transformation was 
possible
@@ -265,26 +264,28 @@ public final class ExpressionUtils {
     public static Expression transformInlineConstants(final Expression exp, 
final ClassNode attrType) {
         if (exp instanceof PropertyExpression) {
             PropertyExpression pe = (PropertyExpression) exp;
-            ClassNode type = pe.getObjectExpression().getType();
-            if (pe.getObjectExpression() instanceof ClassExpression && 
!type.isEnum()) {
-                if (type.isPrimaryClassNode()) {
-                    FieldNode fn = type.getField(pe.getPropertyAsString());
-                    if (fn != null && fn.isStatic() && fn.isFinal()) {
-                        Expression e = 
transformInlineConstants(fn.getInitialValueExpression(), attrType);
-                        if (e != null) {
-                            return e;
-                        }
+            Expression e = pe.getObjectExpression();
+            ClassNode cn;
+            FieldNode fn;
+            if (e instanceof ClassExpression
+                    && !(cn = e.getType().redirect()).isEnum()
+                    && (cn.isPrimaryClassNode() || cn.isResolved())
+                    && (fn = ClassNodeUtils.getField(cn, 
pe.getPropertyAsString())) != null
+                    && fn.isStatic()
+                    && fn.isFinal()) {
+                if (fn.hasInitialExpression()) {
+                    e = 
transformInlineConstants(fn.getInitialValueExpression(), attrType);
+                    if (e instanceof ConstantExpression) {
+                        return e;
                     }
-                } else if (type.isResolved()) {
+                } else if (cn.isResolved()) {
                     try {
-                        Field field = 
type.redirect().getTypeClass().getField(pe.getPropertyAsString());
-                        if (field != null && 
Modifier.isStatic(field.getModifiers()) && 
Modifier.isFinal(field.getModifiers())) {
-                            ConstantExpression ce = new 
ConstantExpression(field.get(null), true);
-                            configure(exp, ce);
-                            return ce;
+                        var field = 
cn.getTypeClass().getField(pe.getPropertyAsString());
+                        if (field != null) {
+                            return configure(exp, new 
ConstantExpression(field.get(null), true));
                         }
-                    } catch (Exception | LinkageError e) {
-                        // ignore, leave property expression in place and 
we'll report later
+                    } catch (Exception | LinkageError ignore) {
+                        // leave property expression and we will report later
                     }
                 }
             }
diff --git 
a/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java 
b/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
index 6e25c3f9ae..48426dedbc 100644
--- 
a/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
+++ 
b/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
@@ -53,7 +53,7 @@ class MemberSignatureParser {
             // ex: java.util.Collections#EMPTY_LIST/EMPTY_MAP/EMPTY_SET
             type[0] = GenericsUtils.nonGeneric(type[0]);
         }
-        return new FieldNode(field.fieldName, field.accessModifiers, type[0], 
owner, field.value != null ? new ConstantExpression(field.value) : null);
+        return new FieldNode(field.fieldName, field.accessModifiers, type[0], 
owner, field.value != null ? new ConstantExpression(field.value, true) : null);
     }
 
     static MethodNode createMethodNode(final AsmReferenceResolver resolver, 
final MethodStub method) {
diff --git a/src/test/groovy/bugs/Groovy9530.groovy 
b/src/test/groovy/bugs/Groovy9530.groovy
new file mode 100644
index 0000000000..20f985a96c
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9530.groovy
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package bugs
+
+import org.junit.jupiter.api.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy9530 {
+
+    static class StaticClass {
+        public static final int STATIC_VALUE = getStaticValue()
+
+        private static int getStaticValue() {
+            return 'resource from classpath'.length()
+        }
+    }
+
+    @Test
+    void testConstantInlining() {
+        assertScript """import bugs.Groovy9530.StaticClass
+            class C {
+                public static final int VALUE = StaticClass.STATIC_VALUE
+            }
+
+            assert C.VALUE == 23
+        """
+    }
+}

Reply via email to