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

emilles 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 57a5bdfc3c GROOVY-11793: use parsed static field value for constant 
inlining
57a5bdfc3c is described below

commit 57a5bdfc3ce479e3c0611d05c042f8c769fcff6b
Author: Eric Milles <[email protected]>
AuthorDate: Fri Oct 31 16:56:11 2025 -0500

    GROOVY-11793: use parsed static field value for constant inlining
---
 .../apache/groovy/ast/tools/ExpressionUtils.java   | 38 +++++++++---------
 .../ast/decompiled/MemberSignatureParser.java      |  2 +-
 src/test/groovy/bugs/Groovy11793.groovy            | 45 ++++++++++++++++++++++
 src/test/groovy/bugs/Groovy9530.groovy             | 43 +++++++++++++++++++++
 4 files changed, 109 insertions(+), 19 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 3a8622d5f5..0dbf87c64b 100644
--- a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
@@ -33,7 +33,6 @@ 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.Arrays;
 import java.util.List;
@@ -282,6 +281,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
@@ -289,26 +289,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;
+                        Field 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 1eb702bfdd..4c8ef6defe 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/Groovy11793.groovy 
b/src/test/groovy/bugs/Groovy11793.groovy
new file mode 100644
index 0000000000..9b92f77f63
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy11793.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.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy11793 {
+
+    @Test
+    void testConstantInlining() {
+        assertScript '''
+            @interface A {
+                int value()
+            }
+
+            class B {
+                public static final int VALUE = 
java.lang.StringUTF16.MAX_LENGTH
+            }
+
+            @A(value=B.VALUE)
+            class C {
+            }
+
+            new C()
+        '''
+    }
+}
diff --git a/src/test/groovy/bugs/Groovy9530.groovy 
b/src/test/groovy/bugs/Groovy9530.groovy
new file mode 100644
index 0000000000..103e5b8be3
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9530.groovy
@@ -0,0 +1,43 @@
+/*
+ *  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.codehaus.groovy.classgen.asm.AbstractBytecodeTestCase
+
+final class Groovy9530 extends AbstractBytecodeTestCase {
+
+    static class StaticClass {
+        public static final int STATIC_VALUE = getStaticValue()
+
+        private static int getStaticValue() {
+            getClassLoader().getResources('absent thingy').toList().size()
+        }
+    }
+
+    void testConstantInlining() {
+        def bytecode = compile '''import bugs.Groovy9530.StaticClass
+            class C {
+                public static final int VALUE = StaticClass.STATIC_VALUE
+            }
+        '''
+        assert bytecode.hasSequence([
+            'public final static I VALUE = 0' // TODO: initializer shouldn't 
exist!
+        ])
+    }
+}

Reply via email to