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!
+ ])
+ }
+}