You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/07/05 16:35:47 UTC

[groovy] 02/02: GROOVY-9871: class model: populate `AnnotationConstantExpression` values

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

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

commit 842687fa68ade49549fd8c076eca4ffec4c93d70
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Jul 5 11:17:08 2022 -0500

    GROOVY-9871: class model: populate `AnnotationConstantExpression` values
---
 .../org/codehaus/groovy/vmplugin/v8/Java8.java     | 99 ++++++++++++----------
 .../ast/{Groovy7826Bug.java => Groovy7826.java}    | 28 +++---
 src/test/org/codehaus/groovy/ast/Groovy9871.groovy | 46 ++++++++++
 3 files changed, 116 insertions(+), 57 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
index 51a6c3538c..81b060ebfe 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
@@ -35,6 +35,7 @@ import org.codehaus.groovy.ast.GenericsType;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.PackageNode;
 import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
 import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
@@ -291,40 +292,7 @@ public class Java8 implements VMPlugin {
         return gts;
     }
 
-    private void setAnnotationMetaData(final Annotation[] annotations, final AnnotatedNode an) {
-        for (Annotation annotation : annotations) {
-            AnnotationNode node = new AnnotationNode(ClassHelper.make(annotation.annotationType()));
-            configureAnnotation(node, annotation);
-            an.addAnnotation(node);
-        }
-    }
-
-    @Override
-    public void configureAnnotationNodeFromDefinition(final AnnotationNode definition, final AnnotationNode root) {
-        ClassNode type = definition.getClassNode();
-        final String typeName = type.getName();
-        if ("java.lang.annotation.Retention".equals(typeName)) {
-            Expression exp = definition.getMember("value");
-            if (!(exp instanceof PropertyExpression)) return;
-            PropertyExpression pe = (PropertyExpression) exp;
-            String name = pe.getPropertyAsString();
-            RetentionPolicy policy = RetentionPolicy.valueOf(name);
-            setRetentionPolicy(policy, root);
-        } else if ("java.lang.annotation.Target".equals(typeName)) {
-            Expression exp = definition.getMember("value");
-            if (!(exp instanceof ListExpression)) return;
-            ListExpression le = (ListExpression) exp;
-            int bitmap = 0;
-            for (Expression e : le.getExpressions()) {
-                if (!(e instanceof PropertyExpression)) return;
-                PropertyExpression element = (PropertyExpression) e;
-                String name = element.getPropertyAsString();
-                ElementType value = ElementType.valueOf(name);
-                bitmap |= getElementCode(value);
-            }
-            root.setAllowedTargets(bitmap);
-        }
-    }
+    //
 
     @Override
     public void configureAnnotation(final AnnotationNode node) {
@@ -367,37 +335,80 @@ public class Java8 implements VMPlugin {
             for (Method declaredMethod : declaredMethods) {
                 try {
                     Object value = declaredMethod.invoke(annotation);
-                    Expression valueExpression = annotationValueToExpression(value);
-                    if (valueExpression == null)
-                        continue;
-                    node.setMember(declaredMethod.getName(), valueExpression);
+                    Expression valueExpression = toAnnotationValueExpression(value);
+                    if (valueExpression != null) node.setMember(declaredMethod.getName(), valueExpression);
+
                 } catch (IllegalAccessException | InvocationTargetException ignore) {
                 }
             }
         }
     }
 
-    private Expression annotationValueToExpression(final Object value) {
+    private void setAnnotationMetaData(final Annotation[] annotations, final AnnotatedNode target) {
+        for (Annotation annotation : annotations) {
+            target.addAnnotation(toAnnotationNode(annotation));
+        }
+    }
+
+    private AnnotationNode toAnnotationNode(final Annotation annotation) {
+        ClassNode type = ClassHelper.make(annotation.annotationType());
+        AnnotationNode node = new AnnotationNode(type);
+        configureAnnotation(node, annotation);
+        return node;
+    }
+
+    private Expression toAnnotationValueExpression(final Object value) {
         if (value == null || value instanceof String || value instanceof Number || value instanceof Character || value instanceof Boolean)
             return new ConstantExpression(value);
 
         if (value instanceof Class)
             return new ClassExpression(ClassHelper.makeWithoutCaching((Class<?>)value));
 
+        if (value instanceof Annotation)
+            return new AnnotationConstantExpression(toAnnotationNode((Annotation)value));
+
         if (value instanceof Enum)
             return new PropertyExpression(new ClassExpression(ClassHelper.makeWithoutCaching(value.getClass())), value.toString());
 
         if (value.getClass().isArray()) {
-            ListExpression elementExprs = new ListExpression();
-            int len = Array.getLength(value);
-            for (int i = 0; i != len; i += 1)
-                elementExprs.addExpression(annotationValueToExpression(Array.get(value, i)));
-            return elementExprs;
+            ListExpression list = new ListExpression();
+            for (int i = 0, n = Array.getLength(value); i < n; i += 1)
+                list.addExpression(toAnnotationValueExpression(Array.get(value, i)));
+            return list;
         }
 
         return null;
     }
 
+    //
+
+    @Override
+    public void configureAnnotationNodeFromDefinition(final AnnotationNode definition, final AnnotationNode root) {
+        ClassNode type = definition.getClassNode();
+        final String typeName = type.getName();
+        if ("java.lang.annotation.Retention".equals(typeName)) {
+            Expression exp = definition.getMember("value");
+            if (!(exp instanceof PropertyExpression)) return;
+            PropertyExpression pe = (PropertyExpression) exp;
+            String name = pe.getPropertyAsString();
+            RetentionPolicy policy = RetentionPolicy.valueOf(name);
+            setRetentionPolicy(policy, root);
+        } else if ("java.lang.annotation.Target".equals(typeName)) {
+            Expression exp = definition.getMember("value");
+            if (!(exp instanceof ListExpression)) return;
+            ListExpression le = (ListExpression) exp;
+            int bitmap = 0;
+            for (Expression e : le.getExpressions()) {
+                if (!(e instanceof PropertyExpression)) return;
+                PropertyExpression element = (PropertyExpression) e;
+                String name = element.getPropertyAsString();
+                ElementType value = ElementType.valueOf(name);
+                bitmap |= getElementCode(value);
+            }
+            root.setAllowedTargets(bitmap);
+        }
+    }
+
     @Override
     public void configureClassNode(final CompileUnit compileUnit, final ClassNode classNode) {
         try {
diff --git a/src/test/org/codehaus/groovy/ast/Groovy7826Bug.java b/src/test/org/codehaus/groovy/ast/Groovy7826.java
similarity index 61%
rename from src/test/org/codehaus/groovy/ast/Groovy7826Bug.java
rename to src/test/org/codehaus/groovy/ast/Groovy7826.java
index ed6b4ab596..fb8745c52a 100644
--- a/src/test/org/codehaus/groovy/ast/Groovy7826Bug.java
+++ b/src/test/org/codehaus/groovy/ast/Groovy7826.java
@@ -19,23 +19,25 @@
 package org.codehaus.groovy.ast;
 
 import groovy.lang.GroovyShell;
-import groovy.test.GroovyTestCase;
 import org.codehaus.groovy.control.CompilerConfiguration;
+import org.junit.Test;
 
-public class Groovy7826Bug extends GroovyTestCase {
-  public void testComplexTypeArguments() throws Exception {
-    String script = "def f(org.codehaus.groovy.ast.Groovy7826Bug.C1 c1) { }";
+public final class Groovy7826 {
 
-    CompilerConfiguration config = new CompilerConfiguration();
-    config.getOptimizationOptions().put("asmResolving", false);
+    @Test
+    public void testComplexTypeArguments() throws Exception {
+        String script = "def f(" + getClass().getName() + ".C1 c1) { }";
 
-    GroovyShell shell = new GroovyShell(config);
-    shell.evaluate(script, "bug7826.groovy");
-  }
+        CompilerConfiguration config = new CompilerConfiguration();
+        config.getOptimizationOptions().put("asmResolving", false);
 
-  public static class C1<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
-  }
+        GroovyShell shell = new GroovyShell(config);
+        shell.evaluate(script, "bug7826.groovy");
+    }
 
-  public static class C2<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
-  }
+    public static class C1<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
+    }
+
+    public static class C2<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
+    }
 }
diff --git a/src/test/org/codehaus/groovy/ast/Groovy9871.groovy b/src/test/org/codehaus/groovy/ast/Groovy9871.groovy
new file mode 100644
index 0000000000..8ff8d14fc5
--- /dev/null
+++ b/src/test/org/codehaus/groovy/ast/Groovy9871.groovy
@@ -0,0 +1,46 @@
+/*
+ *  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 org.codehaus.groovy.ast
+
+import org.codehaus.groovy.ast.expr.AnnotationConstantExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.ListExpression
+import org.junit.Test
+
+final class Groovy9871 {
+
+    @Test
+    void testAnnotationConstantExpression() {
+        ClassNode cn = new ClassNode(org.codehaus.groovy.runtime.ResourceGroovyMethods)
+        // method with @NamedParam annotations that should be wrapped in @NamedParams container
+        MethodNode mn = cn.getMethod('getText', new Parameter(ClassHelper.make(URL), 'url'), new Parameter(ClassHelper.MAP_TYPE, 'map'))
+
+        List<AnnotationNode> annotations = mn.parameters[1].annotations
+
+        assert annotations.size() == 1
+        assert annotations[0].classNode.name == 'groovy.transform.NamedParams'
+        assert annotations[0].members.value instanceof ListExpression
+
+        List<Expression> expressions = annotations[0].members.value.expressions
+
+        assert expressions.size() > 1 // 5 currently
+        assert expressions[0] instanceof AnnotationConstantExpression
+        assert expressions[0].type.name == 'groovy.transform.NamedParam'
+    }
+}