< prev index next >

src/java.base/share/classes/sun/reflect/annotation/AnnotationSupport.java

Print this page

        

@@ -32,10 +32,11 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.function.IntFunction;
 
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.JavaLangAccess;
 import jdk.internal.reflect.ReflectionFactory;
 

@@ -176,10 +177,69 @@
 
         return result;
     }
 
 
+    /**
+     * There are cases where the number of parameters present for a constructor
+     * in source code and the number of parameters present for that constructor
+     * in the class file differ. Constructors of enum classes, anonymous classes,
+     * local classes and member classes may have additional parameters generated
+     * by compiler. This method fixes an array of "annotations collections"
+     * by prefixing and/or suffixing it with "empty collection" elements
+     * for parameters added by compiler.
+     *
+     * @param constructor the constructor
+     * @param annColls an array of annotation collections for parameters in source code
+     * @param emptyColl an empty collection replicated for compiler generated parameters
+     * @param arrayFactory a factory for arrays of collections
+     * @param <A> the type of annotation collection
+     * @return new array of annotation collections for parameters in class file
+     */
+    public static <A> A[] fixConstructorParameterAnnotations(
+        Constructor<?> constructor, A[] annColls, A emptyColl, IntFunction<A[]> arrayFactory)
+    {
+        int prefixLength = 0;
+        boolean mayHaveSuffix = false;
+        Class<?> declaringClass = constructor.getDeclaringClass();
+        if (declaringClass.isEnum() ||
+            (declaringClass.isAnonymousClass() && declaringClass.getSuperclass().isEnum())) {
+            // enum class or enum constant anonymous subclass
+            prefixLength = 2;
+            mayHaveSuffix = true;
+        } else if (declaringClass.isLocalClass() || declaringClass.isAnonymousClass()) {
+            // local or anonymous class
+            if (!Modifier.isStatic(declaringClass.getModifiers())) {
+                prefixLength = 1;
+            }
+            mayHaveSuffix = true;
+        } else if (declaringClass.isMemberClass()) {
+            // member class
+            if (!Modifier.isStatic(declaringClass.getModifiers())) {
+                prefixLength = 1;
+            }
+        }
+        // compute total length of array of arrays
+        int len = annColls.length + prefixLength;
+        if (len < constructor.getParameterCount() && mayHaveSuffix) {
+            len = constructor.getParameterCount();
+        }
+        // prepend empty annotations prefix and/or append suffix if needed
+        if (len > annColls.length) {
+            A[] newAnnColls = arrayFactory.apply(len);
+            Arrays.fill(newAnnColls, 0, prefixLength, emptyColl);
+            System.arraycopy(annColls, 0,
+                             newAnnColls, prefixLength,
+                             annColls.length);
+            Arrays.fill(newAnnColls,
+                        prefixLength + annColls.length, newAnnColls.length,
+                        emptyColl);
+            annColls = newAnnColls;
+        }
+        return annColls;
+    }
+
     /* Reflectively invoke the values-method of the given annotation
      * (container), cast it to an array of annotations and return the result.
      */
     private static <A extends Annotation> A[] getValueArray(Annotation container) {
         try {
< prev index next >