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

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

commit 0a7dbd4e4fac4e085a15178ae45e67219c15b66c
Author: Eric Milles <[email protected]>
AuthorDate: Fri Apr 18 14:01:14 2025 -0500

    GROOVY-11624: SC: post-ResolveVisitor, pre-Verifier constant inlining
---
 .../transformers/StaticCompilationTransformer.java | 11 +++
 src/test/groovy/bugs/Groovy11624.groovy            | 88 ++++++++++++++++++++++
 src/test/groovy/bugs/Groovy11624Support.java       | 23 ++++++
 3 files changed, 122 insertions(+)

diff --git 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java
 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java
index 03a16ad207..bf77f612c5 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java
@@ -18,10 +18,12 @@
  */
 package org.codehaus.groovy.transform.sc.transformers;
 
+import org.apache.groovy.ast.tools.ExpressionUtils;
 import org.apache.groovy.util.Maps;
 import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
 import org.codehaus.groovy.ast.expr.BooleanExpression;
@@ -159,6 +161,15 @@ public class StaticCompilationTransformer extends 
ClassCodeExpressionTransformer
         node.getInnerClasses().forEachRemaining(this::visitClass);
     }
 
+    @Override
+    public void visitField(final FieldNode node) {
+        // GROOVY-11624: post-ResolveVisitor, pre-Verifier constant inlining; 
do not replace initializer expression "x"+WHY with "x".plus(WHY)
+        if (node.hasInitialExpression() && node.isStatic() && node.isFinal() 
&& ClassHelper.isStaticConstantInitializerType(node.getType())) {
+            
node.setInitialValueExpression(ExpressionUtils.transformInlineConstants(node.getInitialExpression(),
 node.getType()));
+        }
+        super.visitField(node);
+    }
+
     @Override
     protected void visitConstructorOrMethod(final MethodNode node, final 
boolean isConstructor) {
         if (staticCompilationVisitor.isSkipMode(node)) {
diff --git a/src/test/groovy/bugs/Groovy11624.groovy 
b/src/test/groovy/bugs/Groovy11624.groovy
new file mode 100644
index 0000000000..d3cc540fc5
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy11624.groovy
@@ -0,0 +1,88 @@
+/*
+ *  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 groovy.test.NotYetImplemented
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy11624 {
+
+    @ParameterizedTest
+    @ValueSource(strings=['CompileDynamic','TypeChecked','CompileStatic'])
+    void testConstantInlining1(String mode) {
+        assertScript """import static bugs.Groovy11624Support.CONST
+            @groovy.transform.${mode}
+            interface I {
+                String SINCE = CONST + '12345'
+                @Deprecated(since = SINCE)
+                interface J {
+                }
+            }
+
+            assert I.J.getAnnotation(Deprecated).since() == 'value12345'
+        """
+    }
+
+    @NotYetImplemented @Test
+    void testConstantInlining2() {
+        def config = new CompilerConfiguration().tap {
+            jointCompilationOptions = [memStub: true]
+            targetDirectory = File.createTempDir()
+        }
+        File parentDir = File.createTempDir()
+        try {
+            new File(parentDir, 'p').mkdir()
+
+            def a = new File(parentDir, 'p/A.java')
+            a.write '''package p;
+                public class A {
+                    public static final String CONST = "value";
+                }
+            '''
+
+            def b = new File(parentDir, 'B.groovy')
+            b.write '''
+                interface I {
+                    String SINCE = p.A.CONST + '12345'
+                    @Deprecated(since = SINCE)
+                    interface J {
+                    }
+                }
+
+                assert I.J.getAnnotation(Deprecated).since() == 'value12345'
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b)
+            cu.compile()
+
+            loader.loadClass('B').main()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+        }
+    }
+}
diff --git a/src/test/groovy/bugs/Groovy11624Support.java 
b/src/test/groovy/bugs/Groovy11624Support.java
new file mode 100644
index 0000000000..e826fa813e
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy11624Support.java
@@ -0,0 +1,23 @@
+/*
+ *  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;
+
+public class Groovy11624Support {
+    public static final String CONST = "value";
+}

Reply via email to