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


The following commit(s) were added to refs/heads/master by this push:
     new e16c9fb618 GROOVY-6526: compute annotation targets and retention 
lazily (#2388)
e16c9fb618 is described below

commit e16c9fb618f08b5f8cb0cac152d526d1bffadc04
Author: Eric Milles <[email protected]>
AuthorDate: Sat Mar 7 16:04:26 2026 -0600

    GROOVY-6526: compute annotation targets and retention lazily (#2388)
---
 .../org/codehaus/groovy/ast/AnnotationNode.java    | 134 +++++++++++++--------
 .../groovy/ast/decompiled/Annotations.java         |   3 +-
 .../codehaus/groovy/classgen/ExtendedVerifier.java |  31 +----
 .../org/codehaus/groovy/vmplugin/VMPlugin.java     |  14 ++-
 .../org/codehaus/groovy/vmplugin/v16/Java16.java   |   6 -
 .../org/codehaus/groovy/vmplugin/v8/Java8.java     |  85 ++-----------
 .../org/codehaus/groovy/vmplugin/v9/Java9.java     |   7 --
 .../codehaus/groovy/ast/AnnotationNodeTest.groovy  |  81 +++++++++++--
 .../ast/visitor/AnnotationProcessorVisitor.java    |   2 -
 9 files changed, 185 insertions(+), 178 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java 
b/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java
index b39906a136..94b772f615 100644
--- a/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java
@@ -22,7 +22,12 @@ import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.ListExpression;
+import org.codehaus.groovy.ast.expr.PropertyExpression;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -49,8 +54,6 @@ public class AnnotationNode extends ASTNode {
 
     private final ClassNode classNode;
     private Map<String, Expression> members;
-    private int allowedTargets = 0x4FF; // GROOVY-11838: JLS 9.6.4.1
-    private boolean runtimeRetention = false, sourceRetention = false, 
/*explicit*/ classRetention = false;
 
     public AnnotationNode(final ClassNode type) {
         classNode = requireNonNull(type);
@@ -77,38 +80,20 @@ public class AnnotationNode extends ASTNode {
         }
     }
 
-    public void setAllowedTargets(final int bitmap) {
-        allowedTargets = bitmap;
+    @Deprecated(since = "6.0.0")
+    public void setAllowedTargets(final int ignored) {
     }
 
-    /**
-     * Sets the internal flag if the current annotation has 
<code>RetentionPolicy.RUNTIME</code>.
-     *
-     * @param value if <tt>true</tt> then current annotation is marked as 
having
-     *     <code>RetentionPolicy.RUNTIME</code>.
-     */
-    public void setRuntimeRetention(final boolean value) {
-        runtimeRetention = value;
+    @Deprecated(since = "6.0.0")
+    public void setClassRetention(final boolean ignored) {
     }
 
-    /**
-     * Sets the internal flag if the current annotation has 
<code>RetentionPolicy.SOURCE</code>.
-     *
-     * @param value if <tt>true</tt> then current annotation is marked as 
having
-     *     <code>RetentionPolicy.SOURCE</code>.
-     */
-    public void setSourceRetention(final boolean value) {
-        sourceRetention = value;
+    @Deprecated(since = "6.0.0")
+    public void setSourceRetention(final boolean ignored) {
     }
 
-    /**
-     * Sets the internal flag if the current annotation has an explicit 
<code>RetentionPolicy.CLASS</code>.
-     *
-     * @param value if <tt>true</tt> then current annotation is marked as 
having
-     *     <code>RetentionPolicy.CLASS</code>.
-     */
-    public void setClassRetention(final boolean value) {
-        classRetention = value;
+    @Deprecated(since = "6.0.0")
+    public void setRuntimeRetention(final boolean ignored) {
     }
 
     
//--------------------------------------------------------------------------
@@ -137,37 +122,92 @@ public class AnnotationNode extends ASTNode {
     }
 
     public boolean isTargetAllowed(final int target) {
-        return (this.allowedTargets & target) == target;
+        if (!(classNode.isPrimaryClassNode() || classNode.isResolved()))
+            throw new IllegalStateException("cannot check target at this 
time");
+
+        // GROOVY-6526: check class for @Target
+        int allowedTargets = 
classNode.redirect().getNodeMetaData(Target.class, (k) -> {
+            for (AnnotationNode an : classNode.getAnnotations()) {
+                if 
("java.lang.annotation.Target".equals(an.getClassNode().getName())
+                        && an.getMember("value") instanceof ListExpression 
list) {
+                    int bits = 0;
+                    for (Expression e : list.getExpressions()) {
+                        if (e instanceof PropertyExpression item) {
+                            String name = item.getPropertyAsString();
+                            bits |= switch (ElementType.valueOf(name)) {
+                                case TYPE             -> TYPE_TARGET;
+                                case FIELD            -> FIELD_TARGET;
+                                case METHOD           -> METHOD_TARGET;
+                                case PARAMETER        -> PARAMETER_TARGET;
+                                case CONSTRUCTOR      -> CONSTRUCTOR_TARGET;
+                                case LOCAL_VARIABLE   -> LOCAL_VARIABLE_TARGET;
+                                case ANNOTATION_TYPE  -> ANNOTATION_TARGET;
+                                case PACKAGE          -> PACKAGE_TARGET;
+                                case TYPE_PARAMETER   -> TYPE_PARAMETER_TARGET;
+                                case TYPE_USE         -> TYPE_USE_TARGET;
+                                case MODULE           -> TYPE_TARGET; //TODO
+                                case RECORD_COMPONENT -> 
RECORD_COMPONENT_TARGET;
+                                default -> throw new 
GroovyBugError("unsupported Target " + name);
+                            };
+                        }
+                    }
+                    return bits;
+                }
+            }
+            return 0x4FF; // GROOVY-11838: JLS 9.6.4.1
+        });
+
+        return (target & allowedTargets) == target;
+    }
+
+    private RetentionPolicy getRetentionPolicy() {
+        if (!(classNode.isPrimaryClassNode() || classNode.isResolved()))
+            throw new IllegalStateException("cannot check retention at this 
time");
+
+        // GROOVY-6526: check class for @Retention
+        return classNode.redirect().getNodeMetaData(Retention.class, (k) -> {
+            for (AnnotationNode an : classNode.getAnnotations()) {
+                if 
("java.lang.annotation.Retention".equals(an.getClassNode().getName())) {
+                    if (an.getMember("value") instanceof PropertyExpression 
pe) {
+                        return 
RetentionPolicy.valueOf(pe.getPropertyAsString());
+                    }
+                    break;
+                }
+            }
+            return null;
+        });
     }
 
     /**
      * Flag corresponding to <code>RetentionPolicy.RUNTIME</code>.
-     * @return <tt>true</tt> if the annotation should be visible at runtime,
+     *
+     * @return <tt>true</tt> if the annotation should be visible at runtime;
      *         <tt>false</tt> otherwise
      */
     public boolean hasRuntimeRetention() {
-        return this.runtimeRetention;
+        return RetentionPolicy.RUNTIME.equals(getRetentionPolicy());
     }
 
     /**
      * Flag corresponding to <code>RetentionPolicy.SOURCE</code>.
-     * @return <tt>true</tt> if the annotation is only allowed in sources
+     *
+     * @return <tt>true</tt> if the annotation is only allowed in sources;
      *         <tt>false</tt> otherwise
      */
     public boolean hasSourceRetention() {
-        return this.sourceRetention;
+        return RetentionPolicy.SOURCE.equals(getRetentionPolicy());
     }
 
     /**
      * Flag corresponding to <code>RetentionPolicy.CLASS</code>.
-     * This is the default when no <code>RetentionPolicy</code> annotations 
are present.
+     * This is the default when no <code>Retention</code> annotation is 
present.
      *
-     * @return <tt>true</tt> if the annotation is written in the bytecode, but 
not visible at runtime
+     * @return <tt>true</tt> if the annotation is written in the bytecode but 
not visible at runtime;
      *         <tt>false</tt> otherwise
      */
     public boolean hasClassRetention() {
-        if (!runtimeRetention && !sourceRetention) return true;
-        return this.classRetention;
+        RetentionPolicy retentionPolicy = getRetentionPolicy();
+        return retentionPolicy == null || 
retentionPolicy.equals(RetentionPolicy.CLASS);
     }
 
     @Override
@@ -205,17 +245,17 @@ public class AnnotationNode extends ASTNode {
     }
 
     public static String targetToName(final int target) {
+        if ((target & 1) == 1) return "TYPE"; // GROOVY-7151
         return switch (target) {
-            case TYPE_TARGET -> "TYPE";
-            case CONSTRUCTOR_TARGET -> "CONSTRUCTOR";
-            case METHOD_TARGET -> "METHOD";
-            case FIELD_TARGET -> "FIELD";
-            case PARAMETER_TARGET -> "PARAMETER";
-            case LOCAL_VARIABLE_TARGET -> "LOCAL_VARIABLE";
-            case ANNOTATION_TARGET -> "ANNOTATION";
-            case PACKAGE_TARGET -> "PACKAGE";
-            case TYPE_PARAMETER_TARGET -> "TYPE_PARAMETER";
-            case TYPE_USE_TARGET -> "TYPE_USE";
+            case CONSTRUCTOR_TARGET      -> "CONSTRUCTOR";
+            case METHOD_TARGET           -> "METHOD";
+            case FIELD_TARGET            -> "FIELD";
+            case PARAMETER_TARGET        -> "PARAMETER";
+            case LOCAL_VARIABLE_TARGET   -> "LOCAL_VARIABLE";
+            case ANNOTATION_TARGET       -> "ANNOTATION";
+            case PACKAGE_TARGET          -> "PACKAGE";
+            case TYPE_PARAMETER_TARGET   -> "TYPE_PARAMETER";
+            case TYPE_USE_TARGET         -> "TYPE_USE";
             case RECORD_COMPONENT_TARGET -> "RECORD_COMPONENT";
             default -> "unknown target";
         };
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/Annotations.java 
b/src/main/java/org/codehaus/groovy/ast/decompiled/Annotations.java
index dbd671d7e9..713c75c398 100644
--- a/src/main/java/org/codehaus/groovy/ast/decompiled/Annotations.java
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/Annotations.java
@@ -143,8 +143,7 @@ class Annotations {
         }
 
         @Override
-        public boolean isTargetAllowed(int target) {
-            lazyInit();
+        public boolean isTargetAllowed(final int target) {
             return super.isTargetAllowed(target);
         }
 
diff --git a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java 
b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
index 9649ab87c4..7093788260 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -35,7 +35,6 @@ import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.DeclarationExpression;
 import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
 import org.codehaus.groovy.ast.stmt.ReturnStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
 import org.codehaus.groovy.control.AnnotationConstantsVisitor;
@@ -43,7 +42,6 @@ import org.codehaus.groovy.control.ErrorCollector;
 import org.codehaus.groovy.control.SourceUnit;
 import org.objectweb.asm.Opcodes;
 
-import java.lang.annotation.Retention;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -67,13 +65,11 @@ import static 
org.codehaus.groovy.ast.AnnotationNode.TYPE_TARGET;
 import static org.codehaus.groovy.ast.AnnotationNode.TYPE_USE_TARGET;
 import static org.codehaus.groovy.ast.ClassHelper.DEPRECATED_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
-import static org.codehaus.groovy.ast.ClassHelper.makeCached;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.listX;
 import static 
org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpec;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.parameterizeType;
 import static org.codehaus.groovy.ast.tools.ParameterUtils.parametersEqual;
-import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.evaluateExpression;
 
 /**
  * A specialized Groovy AST visitor meant to perform additional verifications 
upon the
@@ -376,29 +372,12 @@ public class ExtendedVerifier extends 
ClassCodeVisitorSupport {
                     if 
(nonSourceAnnotations.containsKey(repeatable.getName())) {
                         addError("Cannot specify duplicate annotation on the 
same member. Explicit " + repeatable.getName() + " found when creating implicit 
container for " + entry.getKey(), node);
                     }
-                    AnnotationNode collector = new AnnotationNode(repeatable);
-                    if (repeatee.hasClassRetention()) {
-                        collector.setClassRetention(true);
-                    } else if (repeatee.hasRuntimeRetention()) {
-                        collector.setRuntimeRetention(true);
-                    } else { // load retention policy from annotation 
definition
-                        List<AnnotationNode> retention = 
repeatable.getAnnotations(makeCached(Retention.class));
-                        if (!retention.isEmpty()) {
-                            Object policy;
-                            Expression value = 
retention.get(0).getMember("value");
-                            if (value instanceof PropertyExpression) {
-                                policy = ((PropertyExpression) 
value).getPropertyAsString();
-                            } else { // NOTE: it is risky to evaluate the 
expression from repeatable's source this way:
-                                policy = evaluateExpression(value, 
source.getConfiguration(), source.getClassLoader());
-                            }
-                            if ("CLASS".equals(policy)) {
-                                collector.setClassRetention(true);
-                            } else if ("RUNTIME".equals(policy)) {
-                                collector.setRuntimeRetention(true);
-                            }
-                        }
-                    }
+                    var collector = new AnnotationNode(repeatable);
+                    assert collector.hasClassRetention() == 
repeatee.hasClassRetention();
+                    assert collector.hasSourceRetention() == 
repeatee.hasSourceRetention();
+                    assert collector.hasRuntimeRetention() == 
repeatee.hasRuntimeRetention();
                     collector.addMember("value", 
listX(entry.getValue().stream().map(AnnotationConstantExpression::new).collect(toList())));
+
                     node.getAnnotations().removeAll(entry.getValue());
                     node.addAnnotation(collector);
                 }
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/VMPlugin.java 
b/src/main/java/org/codehaus/groovy/vmplugin/VMPlugin.java
index 602b452bf6..17e7e21686 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/VMPlugin.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/VMPlugin.java
@@ -40,13 +40,19 @@ import java.util.Set;
  * This interface is for internal use only!
  */
 public interface VMPlugin {
-    void setAdditionalClassInformation(ClassNode c);
+
     Class[] getPluginDefaultGroovyMethods();
     Class[] getPluginStaticGroovyMethods();
-    void configureAnnotationNodeFromDefinition(AnnotationNode definition, 
AnnotationNode root);
-    void configureAnnotation(AnnotationNode an);
-    void configureClassNode(CompileUnit compileUnit, ClassNode classNode);
+
+    void setAdditionalClassInformation(ClassNode node);
+    void configureClassNode(CompileUnit unit, ClassNode node);
+
+    void configureAnnotation(AnnotationNode node);
+    default void configureAnnotationNodeFromDefinition(AnnotationNode 
definition, AnnotationNode node) {
+    }
+
     void invalidateCallSites();
+
     /**
      * Returns a handle with bound receiver to invokeSpecial the given method.
      * This method will require at least Java 7, but since the source has to 
compile
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java 
b/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java
index f8169a73af..46bbcd5f45 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v16/Java16.java
@@ -20,13 +20,11 @@ package org.codehaus.groovy.vmplugin.v16;
 
 import groovy.lang.GroovyRuntimeException;
 import org.apache.groovy.lang.annotation.Incubating;
-import org.codehaus.groovy.ast.AnnotationNode;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.CompileUnit;
 import org.codehaus.groovy.ast.RecordComponentNode;
 import org.codehaus.groovy.vmplugin.v10.Java10;
 
-import java.lang.annotation.ElementType;
 import java.lang.invoke.MethodHandle;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
@@ -37,10 +35,6 @@ import java.util.stream.Collectors;
 
 public class Java16 extends Java10 {
 
-    {
-        elementTypeToTarget.put(ElementType.RECORD_COMPONENT, 
AnnotationNode.RECORD_COMPONENT_TARGET);
-    }
-
     @Override
     public int getVersion() {
         return 16;
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 67860da52a..826a177b86 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
@@ -20,7 +20,6 @@ package org.codehaus.groovy.vmplugin.v8;
 
 import groovy.lang.MetaClass;
 import groovy.lang.MetaMethod;
-import org.apache.groovy.util.Maps;
 import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.AnnotatedNode;
 import org.codehaus.groovy.ast.AnnotationNode;
@@ -70,9 +69,7 @@ import java.lang.reflect.TypeVariable;
 import java.lang.reflect.WildcardType;
 import java.security.Permission;
 import java.util.Arrays;
-import java.util.EnumMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * Java 8 based functions.
@@ -121,22 +118,6 @@ public class Java8 implements VMPlugin {
         }
     }
 
-    private static void setRetentionPolicy(final RetentionPolicy value, final 
AnnotationNode node) {
-        switch (value) {
-          case RUNTIME:
-            node.setRuntimeRetention(true);
-            break;
-          case SOURCE:
-            node.setSourceRetention(true);
-            break;
-          case CLASS:
-            node.setClassRetention(true);
-            break;
-          default:
-            throw new GroovyBugError("unsupported Retention " + value);
-        }
-    }
-
     
//--------------------------------------------------------------------------
 
     @Override
@@ -272,27 +253,19 @@ public class Java8 implements VMPlugin {
     }
 
     private void configureAnnotation(final AnnotationNode node, final 
Annotation annotation) {
-        Class<?> type = annotation.annotationType();
-        if (type == Retention.class) {
-            Retention r = (Retention) annotation;
-            RetentionPolicy value = r.value();
-            setRetentionPolicy(value, node);
-            node.setMember("value", new PropertyExpression(
-                    new 
ClassExpression(ClassHelper.makeWithoutCaching(RetentionPolicy.class, false)),
-                    value.toString()));
-        } else if (type == Target.class) {
-            Target t = (Target) annotation;
-            ElementType[] elements = t.value();
-            ListExpression elementExprs = new ListExpression();
-            for (ElementType element : elements) {
-                elementExprs.addExpression(new PropertyExpression(
-                        new ClassExpression(ClassHelper.ELEMENT_TYPE_TYPE), 
element.name()));
+        if (annotation instanceof Retention r) {
+            final ClassNode retentionPolicy = 
ClassHelper.makeWithoutCaching(RetentionPolicy.class, false);
+            node.setMember("value", new PropertyExpression(new 
ClassExpression(retentionPolicy), r.value().toString()));
+        } else if (annotation instanceof Target t) {
+            var elementExprs = new ListExpression();
+            for (ElementType elementTypes : t.value()) {
+                elementExprs.addExpression(new PropertyExpression(new 
ClassExpression(ClassHelper.ELEMENT_TYPE_TYPE), elementTypes.name()));
             }
             node.setMember("value", elementExprs);
         } else {
             Method[] declaredMethods;
             try {
-                declaredMethods = type.getDeclaredMethods();
+                declaredMethods = 
annotation.annotationType().getDeclaredMethods();
             } catch (SecurityException se) {
                 declaredMethods = EMPTY_METHOD_ARRAY;
             }
@@ -301,7 +274,6 @@ public class Java8 implements VMPlugin {
                     Object value = declaredMethod.invoke(annotation);
                     Expression valueExpression = 
toAnnotationValueExpression(value);
                     if (valueExpression != null) 
node.setMember(declaredMethod.getName(), valueExpression);
-
                 } catch (IllegalAccessException | InvocationTargetException 
ignore) {
                 }
             }
@@ -344,47 +316,6 @@ public class Java8 implements VMPlugin {
         return null;
     }
 
-    //
-
-    protected final Map<ElementType, Integer> elementTypeToTarget = new 
EnumMap<>(Maps.of(
-        ElementType.TYPE,            AnnotationNode.TYPE_TARGET,
-        ElementType.FIELD,           AnnotationNode.FIELD_TARGET,
-        ElementType.METHOD,          AnnotationNode.METHOD_TARGET,
-        ElementType.PARAMETER,       AnnotationNode.PARAMETER_TARGET,
-        ElementType.CONSTRUCTOR,     AnnotationNode.CONSTRUCTOR_TARGET,
-        ElementType.LOCAL_VARIABLE,  AnnotationNode.LOCAL_VARIABLE_TARGET,
-        ElementType.ANNOTATION_TYPE, AnnotationNode.ANNOTATION_TARGET,
-        ElementType.PACKAGE,         AnnotationNode.PACKAGE_TARGET,
-        ElementType.TYPE_PARAMETER,  AnnotationNode.TYPE_PARAMETER_TARGET,
-        ElementType.TYPE_USE,        AnnotationNode.TYPE_USE_TARGET
-    ));
-
-    @Override
-    public void configureAnnotationNodeFromDefinition(final AnnotationNode 
definition, final AnnotationNode node) {
-        switch (definition.getClassNode().getName()) {
-          case "java.lang.annotation.Retention":
-            if (definition.getMember("value") instanceof PropertyExpression 
value) {
-                var policy = 
RetentionPolicy.valueOf(value.getPropertyAsString());
-                setRetentionPolicy(policy, node);
-            }
-            break;
-          case "java.lang.annotation.Target":
-            if (definition.getMember("value") instanceof ListExpression list) {
-                int targets = 0;
-                for (Expression e : list.getExpressions()) {
-                    if (e instanceof PropertyExpression item) {
-                        String name = item.getPropertyAsString();
-                        ElementType type = ElementType.valueOf(name);
-                        Integer target = elementTypeToTarget.get(type);
-                        if (target == null) throw new 
GroovyBugError("unsupported Target " + type);
-                        targets |= target;
-                    }
-                }
-                node.setAllowedTargets(targets);
-            }
-        }
-    }
-
     @Override
     public void configureClassNode(final CompileUnit compileUnit, final 
ClassNode classNode) {
         try {
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java 
b/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java
index 6981ee17a2..2f0af57de4 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v9/Java9.java
@@ -56,15 +56,8 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
-import static java.lang.annotation.ElementType.MODULE;
-import static org.codehaus.groovy.ast.AnnotationNode.TYPE_TARGET;
-
 public class Java9 extends Java8 {
 
-    {
-        elementTypeToTarget.put(MODULE, TYPE_TARGET); // TODO Add 
MODULE_TARGET?
-    }
-
     @Override
     public int getVersion() {
         return 9;
diff --git a/src/test/groovy/org/codehaus/groovy/ast/AnnotationNodeTest.groovy 
b/src/test/groovy/org/codehaus/groovy/ast/AnnotationNodeTest.groovy
index aa33bcdcc7..c52c0531d6 100644
--- a/src/test/groovy/org/codehaus/groovy/ast/AnnotationNodeTest.groovy
+++ b/src/test/groovy/org/codehaus/groovy/ast/AnnotationNodeTest.groovy
@@ -21,21 +21,88 @@ package org.codehaus.groovy.ast
 import org.codehaus.groovy.ast.expr.ConstantExpression
 import org.junit.jupiter.api.Test
 
+import static org.codehaus.groovy.ast.AnnotationNode.*
 import static org.junit.jupiter.api.Assertions.*
 
 final class AnnotationNodeTest {
 
+    // GROOVY-6526
+    @Test
+    void testIsTargetAllowed1() {
+        def node = new AnnotationNode(ClassHelper.OVERRIDE_TYPE)
+
+        assertTrue(node.isTargetAllowed(METHOD_TARGET))
+
+        for (target in [TYPE_TARGET, CONSTRUCTOR_TARGET, FIELD_TARGET, 
PARAMETER_TARGET,
+                        LOCAL_VARIABLE_TARGET, ANNOTATION_TARGET, 
PACKAGE_TARGET,
+                        TYPE_PARAMETER_TARGET, TYPE_USE_TARGET, 
RECORD_COMPONENT_TARGET]) {
+            assertFalse(node.isTargetAllowed(target))
+        }
+    }
+
+    // GROOVY-6526
+    @Test
+    void testIsTargetAllowed2() {
+        def node = new AnnotationNode(ClassHelper.DEPRECATED_TYPE)
+
+        for (target in [TYPE_TARGET, CONSTRUCTOR_TARGET, METHOD_TARGET, 
FIELD_TARGET,
+                        LOCAL_VARIABLE_TARGET, PARAMETER_TARGET, 
PACKAGE_TARGET]) {
+            assertTrue(node.isTargetAllowed(target))
+        }
+
+        for (target in [TYPE_PARAMETER_TARGET, TYPE_USE_TARGET, 
RECORD_COMPONENT_TARGET]) {
+            assertFalse(node.isTargetAllowed(target))
+        }
+    }
+
     // GROOVY-11838
     @Test
-    void testIsTargetAllowed() {
+    void testIsTargetAllowed3() {
+        def node = new AnnotationNode(new ClassNode("A", 0x2000, 
ClassHelper.Annotation_TYPE))
+
+        for (target in [TYPE_TARGET, CONSTRUCTOR_TARGET, METHOD_TARGET, 
FIELD_TARGET,
+                        PARAMETER_TARGET, LOCAL_VARIABLE_TARGET, 
ANNOTATION_TARGET,
+                        PACKAGE_TARGET, RECORD_COMPONENT_TARGET]) {
+            assertTrue(node.isTargetAllowed(target))
+        }
+        assertFalse(node.isTargetAllowed(TYPE_USE_TARGET))
+        assertFalse(node.isTargetAllowed(TYPE_PARAMETER_TARGET))
+    }
+
+    @Test
+    void testRetentionPolicy1() {
+        def node = new 
AnnotationNode(ClassHelper.make(gls.annotations.HasExplicitClassRetention))
+
+        assertTrue (node.hasClassRetention())
+        assertFalse(node.hasSourceRetention())
+        assertFalse(node.hasRuntimeRetention())
+    }
+
+    @Test
+    void testRetentionPolicy2() {
         def node = new AnnotationNode(ClassHelper.OVERRIDE_TYPE)
 
-        assertTrue(node.isTargetAllowed(AnnotationNode.TYPE_TARGET))
-        assertTrue(node.isTargetAllowed(AnnotationNode.FIELD_TARGET))
-        assertTrue(node.isTargetAllowed(AnnotationNode.METHOD_TARGET))
+            assertFalse(node.hasClassRetention())
+            assertTrue (node.hasSourceRetention())
+            assertFalse(node.hasRuntimeRetention())
+    }
+
+    @Test
+    void testRetentionPolicy3() {
+        def node = new AnnotationNode(ClassHelper.DEPRECATED_TYPE)
+
+        assertFalse(node.hasClassRetention())
+        assertFalse(node.hasSourceRetention())
+        assertTrue (node.hasRuntimeRetention())
+    }
+
+    @Test
+    void testRetentionPolicy4() {
+        def node = new AnnotationNode(new ClassNode("A", 0x2000, 
ClassHelper.Annotation_TYPE))
 
-        assertFalse(node.isTargetAllowed(AnnotationNode.TYPE_USE_TARGET))
-        assertFalse(node.isTargetAllowed(AnnotationNode.TYPE_PARAMETER_TARGET))
+        assertTrue (node.hasClassRetention())
+        assertFalse(node.hasSourceRetention())
+        assertFalse(node.hasRuntimeRetention())
     }
 
     @Test
@@ -47,7 +114,7 @@ final class AnnotationNodeTest {
 
     @Test
     void testGetText2() {
-        def node = new AnnotationNode(ClassHelper.make(Deprecated))
+        def node = new AnnotationNode(ClassHelper.DEPRECATED_TYPE)
         node.addMember('since', new ConstantExpression('1.2.3'))
 
         assertEquals('@java.lang.Deprecated(since="1.2.3")', node.getText())
diff --git 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
index 56d59233df..bcdd4ab96e 100644
--- 
a/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
+++ 
b/subprojects/groovy-contracts/src/main/java/org/apache/groovy/contracts/ast/visitor/AnnotationProcessorVisitor.java
@@ -199,8 +199,6 @@ public class AnnotationProcessorVisitor extends BaseVisitor 
{
         if (!AnnotationUtils.hasAnnotationOfType(methodNode, 
annotationNode.getClassNode().getName())) {
             AnnotationNode markerAnnotation = new 
AnnotationNode(annotationNode.getClassNode());
             replaceCondition(markerAnnotation, valueExpression);
-            markerAnnotation.setRuntimeRetention(true);
-            markerAnnotation.setSourceRetention(false);
             methodNode.addAnnotation(markerAnnotation);
         }
     }

Reply via email to