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

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


The following commit(s) were added to refs/heads/GROOVY_5_0_X by this push:
     new 2e03004d8a GROOVY-11865: collect array or list elements using 
expression conversion
2e03004d8a is described below

commit 2e03004d8af99e9662ddcdafd064e5f236315556
Author: Eric Milles <[email protected]>
AuthorDate: Fri Feb 27 10:33:13 2026 -0600

    GROOVY-11865: collect array or list elements using expression conversion
---
 .../customizers/ASTTransformationCustomizer.groovy | 92 ++++++++++++----------
 .../ASTTransformationCustomizerTest.groovy         | 38 ++++++++-
 2 files changed, 85 insertions(+), 45 deletions(-)

diff --git 
a/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy
 
b/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy
index 2d43061410..7160440fae 100644
--- 
a/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy
+++ 
b/src/main/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizer.groovy
@@ -20,7 +20,6 @@ package org.codehaus.groovy.control.customizers
 
 import groovy.transform.AutoFinal
 import groovy.transform.CompilationUnitAware
-import groovy.transform.CompileDynamic
 import groovy.transform.CompileStatic
 import org.codehaus.groovy.ast.ASTNode
 import org.codehaus.groovy.ast.AnnotationNode
@@ -49,7 +48,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
  * Creating a customizer with the {@link 
ASTTransformationCustomizer#ASTTransformationCustomizer(Class)
  * class constructor} will trigger an AST transformation for
  * each class node of a source unit. However, you cannot pass parameters to 
the annotation so the default values
- * will be used. Writing :
+ * will be used. Writing:
  * <pre>
  *     def configuration = new CompilerConfiguration()
  *     configuration.addCompilationCustomizers(new 
ASTTransformationCustomizer(Log))
@@ -60,8 +59,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
  *        }""")
  * </pre>
  *
- * is equivalent to :
- *
+ * is equivalent to:
  * <pre>
  *     def shell = new GroovyShell()
  *     shell.evaluate("""
@@ -195,10 +193,6 @@ class ASTTransformationCustomizer extends 
CompilationCustomizer implements Compi
         this.annotationParameters = annotationParams
     }
 
-    void setCompilationUnit(CompilationUnit unit) {
-        compilationUnit = unit
-    }
-
     @SuppressWarnings('ClassForName')
     private static Class<ASTTransformation> findASTTransformationClass(Class<? 
extends Annotation> anAnnotationClass, ClassLoader transformationClassLoader) {
         GroovyASTTransformationClass annotation = 
anAnnotationClass.getAnnotation(GroovyASTTransformationClass)
@@ -257,53 +251,69 @@ class ASTTransformationCustomizer extends 
CompilationCustomizer implements Compi
      * }.expression[0]
      * customizer.annotationParameters = [value: expression]</pre>
      *
-     * @param params the annotation parameters
-     *
      * @since 1.8.1
      */
-    @CompileDynamic
-    void setAnnotationParameters(Map<String, Object> params) {
-        if (annotationNode == null || params == null || params.isEmpty()) 
return
-        params.each { name, value ->
-            if (!annotationNode.classNode.getMethod(name)) {
+    void setAnnotationParameters(Map<String, Object> parameters) {
+        if (!annotationNode) return
+        for (entry in parameters) {
+            String name = entry.getKey()
+            if (annotationNode.classNode.getMethod(name) == null) {
                 throw new 
IllegalArgumentException("${annotationNode.classNode.name} does not accept any 
[$name] parameter")
             }
-            if (value instanceof Closure) {
-                throw new IllegalArgumentException('Direct usage of closure is 
not supported by the AST compilation customizer. Please use ClosureExpression 
instead.')
-            }
+            annotationNode.addMember(name, toExpression(entry.getValue()))
+        }
+    }
 
-            Expression valueExpression
-
-            if (value instanceof Expression) {
-                valueExpression = value
-                // avoid NPEs due to missing source code
-                value.lineNumber = 0; value.lastLineNumber = 0
-            } else if (value instanceof Class) {
-                valueExpression = classX(value)
-            } else if (value instanceof Enum) {
-                valueExpression = 
propX(classX(ClassHelper.make(value.getClass())), value.toString())
-            } else if (value instanceof List || value.getClass().isArray()) {
-                valueExpression = listX(value.collect { it instanceof Class ? 
classX(it) : constX(it) })
-            } else {
-                valueExpression = constX(value)
-            }
+    private static Expression toExpression(Object value) {
+        if (value instanceof Expression) {
+            // avoid exceptions due to missing source code
+            value.lineNumber = 0; value.lastLineNumber = 0
+            return value
+        }
+
+        if (value instanceof Closure) {
+            throw new IllegalArgumentException('Direct usage of closure is not 
supported by the AST compilation customizer. Please use ClosureExpression 
instead.')
+        }
+
+        if (value instanceof Class) {
+            return classX(value)
+        }
+
+        if (value instanceof Enum) {
+            return propX(classX(value.getClass()), value.toString())
+        }
 
-            annotationNode.addMember(name, valueExpression)
+        if (value instanceof List) {
+            return listX(value.collect(this.&toExpression)) // GROOVY-11865
         }
+
+        if (value.getClass().isArray()) {
+            def array = value as Object[]
+            return listX(array.collect(this.&toExpression)) // GROOVY-11865
+        }
+
+        return constX(value, true)
+    }
+
+    
//--------------------------------------------------------------------------
+
+    @Override
+    void setCompilationUnit(CompilationUnit compilationUnit) {
+        this.compilationUnit = compilationUnit
     }
 
     @Override
-    void call(SourceUnit source, GeneratorContext context, ClassNode 
classNode) {
-        if (transformation instanceof CompilationUnitAware) {
-            ((CompilationUnitAware) transformation).compilationUnit = 
compilationUnit
+    void call(SourceUnit sourceUnit, GeneratorContext context, ClassNode 
classNode) {
+        if (transformation instanceof CompilationUnitAware unitAware) {
+            unitAware.compilationUnit = compilationUnit
         }
         if (annotationNode != null) {
-            // this is a local ast transformation which is applied on every 
class node
             annotationNode.sourcePosition = classNode
-            transformation.visit([annotationNode, classNode] as ASTNode[], 
source)
-        } else {
+            // this is a local ast transformation which is applied on every 
class node
+            transformation.visit(new ASTNode[]{annotationNode, classNode}, 
sourceUnit)
+        } else if (!applied) {
             // this is a global AST transformation
-            if (!applied) transformation.visit(null, source)
+            transformation.visit(null, sourceUnit)
         }
         applied = true
     }
diff --git 
a/src/test/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizerTest.groovy
 
b/src/test/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizerTest.groovy
index 0d15d1263c..deb60aa235 100644
--- 
a/src/test/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizerTest.groovy
+++ 
b/src/test/groovy/org/codehaus/groovy/control/customizers/ASTTransformationCustomizerTest.groovy
@@ -18,10 +18,9 @@
  */
 package org.codehaus.groovy.control.customizers
 
-import groovy.transform.TimedInterrupt
+import groovy.transform.*
 import groovy.util.logging.Log
 import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.ClassHelper
 import org.codehaus.groovy.control.CompilePhase
 import org.codehaus.groovy.control.CompilerConfiguration
 import org.codehaus.groovy.control.SourceUnit
@@ -33,6 +32,7 @@ import java.util.concurrent.TimeUnit
 import java.util.concurrent.atomic.AtomicBoolean
 
 import static groovy.test.GroovyAssert.shouldFail
+import static groovy.transform.PackageScopeTarget.METHODS
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
 import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
 
@@ -110,7 +110,7 @@ final class ASTTransformationCustomizerTest {
     @Test
     void testLocalTransformationPropertyExpressionParameter() {
         def shell = GroovyShell.withConfig {
-            ast(TimedInterrupt, value:300, 
unit:propX(classX(ClassHelper.make(TimeUnit)),'MILLISECONDS'))
+            ast(TimedInterrupt, value:300, 
unit:propX(classX(TimeUnit),'MILLISECONDS'))
             imports { normal 'java.util.concurrent.TimeoutException' }
         }
         assert shell.evaluate('''
@@ -127,7 +127,8 @@ final class ASTTransformationCustomizerTest {
         ''')
     }
 
-    @Test // GROOVY-10654
+    // GROOVY-10654
+    @Test
     void testLocalTransformationEnumerationConstantParameter() {
         def shell = GroovyShell.withConfig {
             ast(TimedInterrupt, value:300, unit:TimeUnit.MILLISECONDS)
@@ -147,6 +148,35 @@ final class ASTTransformationCustomizerTest {
         ''')
     }
 
+    // GROOVY-11865
+    @Test
+    void testLocalTransformationListOfEnumerationConstantParameter() {
+        def shell = GroovyShell.withConfig {
+            ast(PackageScope, value: [PackageScopeTarget.CONSTRUCTORS, 
METHODS])
+            imports { staticStar 'java.lang.reflect.Modifier' }
+        }
+        shell.evaluate '''
+            class C {
+                C() {
+                }
+                def m() {
+                }
+            }
+
+            int mods = C.getModifiers()
+
+            assert isPublic(mods)
+
+            mods = C.getDeclaredConstructors().first().getModifiers()
+
+            assert !isPublic(mods) && !isPrivate(mods) && !isProtected(mods)
+
+            mods = C.getDeclaredMethod('m').getModifiers()
+
+            assert !isPublic(mods) && !isPrivate(mods) && !isProtected(mods)
+        '''
+    }
+
     
//--------------------------------------------------------------------------
 
     @Test

Reply via email to