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 922b949c8aa2f18d0ccab222fc28e52d2e5c4117 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..17a018a28a 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"+"y" with "x".plus("y") + 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"; +}
