1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.description.type;
17
18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 import net.bytebuddy.ClassFileVersion;
20 import net.bytebuddy.build.CachedReturnPlugin;
21 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
22 import net.bytebuddy.description.ByteCodeElement;
23 import net.bytebuddy.description.ModifierReviewable;
24 import net.bytebuddy.description.TypeVariableSource;
25 import net.bytebuddy.description.annotation.AnnotationDescription;
26 import net.bytebuddy.description.annotation.AnnotationList;
27 import net.bytebuddy.description.annotation.AnnotationSource;
28 import net.bytebuddy.description.enumeration.EnumerationDescription;
29 import net.bytebuddy.description.field.FieldDescription;
30 import net.bytebuddy.description.field.FieldList;
31 import net.bytebuddy.description.method.MethodDescription;
32 import net.bytebuddy.description.method.MethodList;
33 import net.bytebuddy.description.method.ParameterDescription;
34 import net.bytebuddy.dynamic.TargetType;
35 import net.bytebuddy.implementation.bytecode.StackSize;
36 import net.bytebuddy.matcher.ElementMatcher;
37 import net.bytebuddy.utility.CompoundList;
38 import net.bytebuddy.utility.JavaType;
39 import net.bytebuddy.utility.privilege.GetSystemPropertyAction;
40 import net.bytebuddy.jar.asm.Opcodes;
41 import net.bytebuddy.jar.asm.Type;
42 import net.bytebuddy.jar.asm.signature.SignatureVisitor;
43 import net.bytebuddy.jar.asm.signature.SignatureWriter;
44
45 import java.io.Serializable;
46 import java.lang.annotation.Annotation;
47 import java.lang.annotation.ElementType;
48 import java.lang.reflect.*;
49 import java.security.AccessController;
50 import java.security.PrivilegedAction;
51 import java.util.*;
52
53 import static net.bytebuddy.matcher.ElementMatchers.is;
54
55 /**
56  * Implementations of this interface represent a Java type, i.e. a class or interface. Instances of this interface always
57  * represent non-generic types of sort {@link Generic.Sort#NON_GENERIC}.
58  */

59 public interface TypeDescription extends TypeDefinition, ByteCodeElement, TypeVariableSource {
60
61     /**
62      * A representation of the {@link java.lang.Object} type.
63      */

64     TypeDescription OBJECT = new ForLoadedType(Object.class);
65
66     /**
67      * A representation of the {@link java.lang.String} type.
68      */

69     TypeDescription STRING = new ForLoadedType(String.class);
70
71     /**
72      * A representation of the {@link java.lang.Class} type.
73      */

74     TypeDescription CLASS = new ForLoadedType(Class.class);
75
76     /**
77      * A representation of the {@link java.lang.Throwable} type.
78      */

79     TypeDescription THROWABLE = new ForLoadedType(Throwable.class);
80
81     /**
82      * A representation of the {@code void} non-type.
83      */

84     TypeDescription VOID = new ForLoadedType(void.class);
85
86     /**
87      * A list of interfaces that are implicitly implemented by any array type.
88      */

89     TypeList.Generic ARRAY_INTERFACES = new TypeList.Generic.ForLoadedTypes(Cloneable.class, Serializable.class);
90
91     /**
92      * Represents any undefined property representing a type description that is instead represented as {@code null} in order
93      * to resemble the Java reflection API which returns {@code null} and is intuitive to many Java developers.
94      */

95     TypeDescription UNDEFINED = null;
96
97     /**
98      * {@inheritDoc}
99      */

100     FieldList<FieldDescription.InDefinedShape> getDeclaredFields();
101
102     /**
103      * {@inheritDoc}
104      */

105     MethodList<MethodDescription.InDefinedShape> getDeclaredMethods();
106
107     /**
108      * {@inheritDoc}
109      */

110     RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents();
111
112     /**
113      * Checks if {@code value} is an instance of the type represented by this instance.
114      *
115      * @param value The object of interest.
116      * @return {@code trueif the object is an instance of the type described by this instance.
117      */

118     boolean isInstance(Object value);
119
120     /**
121      * Checks if this type is assignable from the type described by this instance, for example for
122      * {@code class Foo} and {@code class Bar extends Foo}, this method would return {@code truefor
123      * {@code Foo.class.isAssignableFrom(Bar.class)}.
124      *
125      * @param type The type of interest.
126      * @return {@code trueif this type is assignable from {@code type}.
127      */

128     boolean isAssignableFrom(Class<?> type);
129
130     /**
131      * Checks if this type is assignable from the type described by this instance, for example for
132      * {@code class Foo} and {@code class Bar extends Foo}, this method would return {@code truefor
133      * {@code Foo.class.isAssignableFrom(Bar.class)}.
134      * <p>&nbsp;</p>
135      * Implementations of this methods are allowed to delegate to
136      * {@link TypeDescription#isAssignableFrom(Class)}
137      *
138      * @param typeDescription The type of interest.
139      * @return {@code trueif this type is assignable from {@code type}.
140      */

141     boolean isAssignableFrom(TypeDescription typeDescription);
142
143     /**
144      * Checks if this type is assignable from the type described by this instance, for example for
145      * {@code class Foo} and {@code class Bar extends Foo}, this method would return {@code truefor
146      * {@code Bar.class.isAssignableTo(Foo.class)}.
147      *
148      * @param type The type of interest.
149      * @return {@code trueif this type is assignable to {@code type}.
150      */

151     boolean isAssignableTo(Class<?> type);
152
153     /**
154      * Checks if this type is assignable from the type described by this instance, for example for
155      * {@code class Foo} and {@code class Bar extends Foo}, this method would return {@code truefor
156      * {@code Bar.class.isAssignableFrom(Foo.class)}.
157      * <p>&nbsp;</p>
158      * Implementations of this methods are allowed to delegate to
159      * {@link TypeDescription#isAssignableTo(Class)}
160      *
161      * @param typeDescription The type of interest.
162      * @return {@code trueif this type is assignable to {@code type}.
163      */

164     boolean isAssignableTo(TypeDescription typeDescription);
165
166     /**
167      * Returns {@code trueif this type and the supplied type are in a type hierarchy with each other, i.e. if this type is assignable
168      * to the supplied type or the other way around.
169      *
170      * @param type The type of interest.
171      * @return {@code trueif this type and the supplied type are in a type hierarchy with each other.
172      */

173     boolean isInHierarchyWith(Class<?> type);
174
175     /**
176      * Returns {@code trueif this type and the supplied type are in a type hierarchy with each other, i.e. if this type is assignable
177      * to the supplied type or the other way around.
178      *
179      * @param typeDescription The type of interest.
180      * @return {@code trueif this type and the supplied type are in a type hierarchy with each other.
181      */

182     boolean isInHierarchyWith(TypeDescription typeDescription);
183
184     /**
185      * {@inheritDoc}
186      */

187     TypeDescription getComponentType();
188
189     /**
190      * {@inheritDoc}
191      */

192     TypeDescription getDeclaringType();
193
194     /**
195      * Returns a list of types that are declared by this type. This list does not normally include anonymous types but might
196      * include additional types if they are explicitly added to an instrumented type.
197      *
198      * @return A list of types that are declared within this type.
199      */

200     TypeList getDeclaredTypes();
201
202     /**
203      * Returns a description of the method that encloses this type. If this method is not enclosed by any type or is
204      * enclosed by the type initializer, {@code null} is returned by this method.
205      *
206      * @return A description of the enclosing method of this type or {@code nullif there is no such method.
207      */

208     MethodDescription.InDefinedShape getEnclosingMethod();
209
210     /**
211      * Returns a description of this type's enclosing type if any.
212      *
213      * @return A description of the enclosing type of this type or {@code nullif there is no such type.
214      */

215     TypeDescription getEnclosingType();
216
217     /**
218      * Returns the type's actual modifiers as present in the class file. For example, a type cannot be {@code private}.
219      * but it modifiers might reflect this property nevertheless if a class was defined as a private inner class. The
220      * returned modifiers take also into account if the type is marked as {@link Deprecated}. Anonymous classes that are
221      * enclosed in a static method or the type initializer are additionally marked as {@code final} as it is also done
222      * by the Java compiler.
223      *
224      * @param superFlag {@code trueif the modifier's super flag should be set.
225      * @return The type's actual modifiers.
226      */

227     int getActualModifiers(boolean superFlag);
228
229     /**
230      * Returns the simple internalName of this type.
231      *
232      * @return The simple internalName of this type.
233      */

234     String getSimpleName();
235
236     /**
237      * Returns the canonical name of this type if it exists.
238      *
239      * @return The canonical name of this type. Might be {@code null}.
240      */

241     String getCanonicalName();
242
243     /**
244      * Checks if this type description represents an anonymous type.
245      *
246      * @return {@code trueif this type description represents an anonymous type.
247      */

248     boolean isAnonymousType();
249
250     /**
251      * Checks if this type description represents a local type.
252      *
253      * @return {@code trueif this type description represents a local type.
254      */

255     boolean isLocalType();
256
257     /**
258      * Checks if this type description represents a member type.
259      *
260      * @return {@code trueif this type description represents a member type.
261      */

262     boolean isMemberType();
263
264     /**
265      * Returns the package of the type described by this instance or {@code nullif the described type does not imply a package.
266      *
267      * @return The package of the type described by this instance or {@code nullif the described type does not imply a package.
268      */

269     PackageDescription getPackage();
270
271     /**
272      * Returns the annotations that this type declares or inherits from super types.
273      *
274      * @return A list of all inherited annotations.
275      */

276     AnnotationList getInheritedAnnotations();
277
278     /**
279      * Checks if two types are defined in the same package.
280      *
281      * @param typeDescription The type of interest.
282      * @return {@code trueif this type and the given type are in the same package.
283      */

284     boolean isSamePackage(TypeDescription typeDescription);
285
286     /**
287      * Checks if this type represents a wrapper type for a primitive type. The {@link java.lang.Void} type is
288      * not considered to be a wrapper type.
289      *
290      * @return {@code trueif this type represents a wrapper type.
291      */

292     boolean isPrimitiveWrapper();
293
294     /**
295      * Checks if instances of this type can be returned from an annotation method.
296      *
297      * @return {@code trueif instances of this type can be returned from an annotation method.
298      */

299     boolean isAnnotationReturnType();
300
301     /**
302      * Checks if instances of this type can be used for describing an annotation value.
303      *
304      * @return {@code trueif instances of this type can be used for describing an annotation value.
305      */

306     boolean isAnnotationValue();
307
308     /**
309      * Checks if instances of this type can be used for describing the given annotation value.
310      *
311      * @param value The value that is supposed to describe the annotation value for this instance.
312      * @return {@code trueif instances of this type can be used for describing the given annotation value..
313      */

314     boolean isAnnotationValue(Object value);
315
316     /**
317      * Checks if this type represents a class that is a place holder for a package description.
318      *
319      * @return {@code trueif this type represents a package description.
320      */

321     boolean isPackageType();
322
323     /**
324      * Returns the amount of outer classes this type defines. If this type is not an inner type of another class, {@code 0} is returned.
325      *
326      * @return The number of outer classes relatively to this type.
327      */

328     int getInnerClassCount();
329
330     /**
331      * Indicates if this class is an inner class.
332      *
333      * @return {@code trueif this class is an inner class.
334      */

335     boolean isInnerClass();
336
337     /**
338      * Indicates if this class is a nested class.
339      *
340      * @return {@code trueif this class is a nested class.
341      */

342     boolean isNestedClass();
343
344     /**
345      * Returns a description of this type that represents this type as a boxed type for primitive types, unless its {@code void}.
346      *
347      * @return A description of this type in its boxed form.
348      */

349     TypeDescription asBoxed();
350
351     /**
352      * Returns a description of this type that represents this type as an unboxed type for boxing types, unless its {@link Void}.
353      *
354      * @return A description of this type in its unboxed form.
355      */

356     TypeDescription asUnboxed();
357
358     /**
359      * Returns the default value for this type, i.e. the zero value for a primitive type and {@code nullfor a reference type.
360      * For {@code void}, {@code null} is returned.
361      *
362      * @return This types default value.
363      */

364     Object getDefaultValue();
365
366     /**
367      * Returns the nest host of this type. For types prior to Java 11, this type is returned which is the default nest host.
368      *
369      * @return The nest host of this type.
370      */

371     TypeDescription getNestHost();
372
373     /**
374      * Returns a list of members that are part of a nesting group. Prior to Java 11, a list that only contains this type is returned which is
375      * the default nest group.
376      *
377      * @return A list of members of this nest group.
378      */

379     TypeList getNestMembers();
380
381     /**
382      * Checks if this class is the host of a nest group.
383      *
384      * @return {@code trueif this class is a nest group's host.
385      */

386     boolean isNestHost();
387
388     /**
389      * Checks if this type and the supplied type are members of the same nest group.
390      *
391      * @param type The type for which to check if it is a member of the same nest group.
392      * @return {@code trueif this type and the supplied type are members of the same nest group.
393      */

394     boolean isNestMateOf(Class<?> type);
395
396     /**
397      * Checks if this type and the supplied type are members of the same nest group.
398      *
399      * @param typeDescription The type for which to check if it is a member of the same nest group.
400      * @return {@code trueif this type and the supplied type are members of the same nest group.
401      */

402     boolean isNestMateOf(TypeDescription typeDescription);
403
404     /**
405      * Indicates if this type represents a compile-time constant, i.e. {@code int}, {@code long}, {@code float}, {@code double},
406      * {@link String}, {@link Class} or {@code java.lang.invoke.MethodHandle} or {@code java.lang.invoke.MethodType}.
407      *
408      * @return {@code trueif this type represents a compile-time constant.
409      */

410     boolean isCompileTimeConstant();
411
412     /**
413      * Returns the list of permitted subclasses if this class is a sealed class or an empty list if this class is not sealed.
414      *
415      * @return The list of permitted subclasses if this class is a sealed class or an empty list if this class is not sealed.
416      */

417     TypeList getPermittedSubclasses();
418
419     /**
420      * Returns {@code trueif this class is a sealed class that only permitts a specified range of subclasses.
421      *
422      * @return {@code trueif this class is a sealed class that only permitts a specified range of subclasses.
423      */

424     boolean isSealed();
425
426     /**
427      * <p>
428      * Represents a generic type of the Java programming language. A non-generic {@link TypeDescription} is considered to be
429      * a specialization of a generic type.
430      * </p>
431      * <p>
432      * Note that annotations that are declared on an annotated type refer to any type annotations that are declared by this
433      * generic type. For reading annotations of the erasure type, {@link TypeDefinition#asErasure()} must be called before.
434      * </p>
435      */

436     interface Generic extends TypeDefinition, AnnotationSource {
437
438         /**
439          * A representation of the {@link Object} type.
440          */

441         Generic OBJECT = new OfNonGenericType.ForLoadedType(Object.class);
442
443         /**
444          * A representation of the {@link Class} non-type.
445          */

446         Generic CLASS = new OfNonGenericType.ForLoadedType(Class.class);
447
448         /**
449          * A representation of the {@code void} non-type.
450          */

451         Generic VOID = new OfNonGenericType.ForLoadedType(void.class);
452
453         /**
454          * A representation of the {@link Annotation} type.
455          */

456         Generic ANNOTATION = new OfNonGenericType.ForLoadedType(Annotation.class);
457
458         /**
459          * Represents any undefined property representing a generic type description that is instead represented as {@code null} in order
460          * to resemble the Java reflection API which returns {@code null} and is intuitive to many Java developers.
461          */

462         Generic UNDEFINED = null;
463
464         /**
465          * Returns this type as a raw type. This resembles calling {@code asErasure().asGenericType()}.
466          *
467          * @return This type as a raw type.
468          */

469         Generic asRawType();
470
471         /**
472          * <p>
473          * Returns the upper bounds of this type. Any type with a well-defined upper bound is bound by at least one type. If no such
474          * type is defined, the bound is implicitly {@link Object}.
475          * </p>
476          * <p>
477          * Only non-symbolic type variables ({@link net.bytebuddy.description.type.TypeDefinition.Sort#VARIABLE}, and wildcard types
478          * ({@link net.bytebuddy.description.type.TypeDefinition.Sort#WILDCARD}) have well-defined upper bounds. For other
479          * types, an {@link IllegalStateException} is thrown.
480          * </p>
481          *
482          * @return The upper bounds of this type.
483          */

484         TypeList.Generic getUpperBounds();
485
486         /**
487          * <p>
488          * Returns the lower bounds of this type.
489          * </p>
490          * <p>
491          * Only wildcard types ({@link Sort#WILDCARD}) define a lower bound. For other
492          * types, an {@link IllegalStateException} is thrown.
493          * </p>
494          *
495          * @return The lower bounds of this type.
496          */

497         TypeList.Generic getLowerBounds();
498
499         /**
500          * <p>
501          * Returns the type arguments of this type.
502          * </p>
503          * <p>
504          * Parameters are only well-defined for parameterized types ({@link Sort#PARAMETERIZED}).
505          * For all other types, this method throws an {@link IllegalStateException}.
506          * </p>
507          *
508          * @return A list of this type's type parameters.
509          */

510         TypeList.Generic getTypeArguments();
511
512         /**
513          * <p>
514          * Returns the owner type of this type. A type's owner type describes a nested type's declaring type.
515          * If it exists, the returned type can be a non-generic or parameterized type. If a class has no
516          * declaring type, {@code null} is returned.
517          * </p>
518          * <p>
519          * An owner type is only well-defined for parameterized types ({@link Sort#PARAMETERIZED}),
520          * for non-generic types ({@link Sort#NON_GENERIC}) and for generic arrays ({@link Sort#GENERIC_ARRAY}).
521          * For all other types, this method throws an {@link IllegalStateException}.
522          * </p>
523          *
524          * @return This type's owner type or {@code nullif no owner type exists.
525          */

526         Generic getOwnerType();
527
528         /**
529          * <p>
530          * Returns the parameter binding of the supplied type variable.
531          * </p>
532          * <p>
533          * This method must only be called for parameterized types ({@link Sort#PARAMETERIZED}). For all other types,
534          * this method throws an {@link IllegalStateException}.
535          * </p>
536          *
537          * @param typeVariable The type variable for which a value should be located.
538          * @return The value that is bound to the supplied type variable or {@code nullif the type variable
539          * is not bound by this parameterized type.
540          */

541         Generic findBindingOf(Generic typeVariable);
542
543         /**
544          * Returns the source of this type variable. A type variable source is only well-defined for an attached type variable
545          * ({@link Sort#VARIABLE}. For other types, this method
546          * throws an {@link IllegalStateException}.
547          *
548          * @return This type's type variable source.
549          */

550         TypeVariableSource getTypeVariableSource();
551
552         /**
553          * Returns the symbol of this type variable. A symbol is only well-defined for type variables
554          * ({@link Sort#VARIABLE}, {@link Sort#VARIABLE_SYMBOLIC}). For other types, this method
555          * throws an {@link IllegalStateException}.
556          *
557          * @return This type's type variable symbol.
558          */

559         String getSymbol();
560
561         /**
562          * {@inheritDoc}
563          */

564         Generic getComponentType();
565
566         /**
567          * {@inheritDoc}
568          */

569         FieldList<FieldDescription.InGenericShape> getDeclaredFields();
570
571         /**
572          * {@inheritDoc}
573          */

574         MethodList<MethodDescription.InGenericShape> getDeclaredMethods();
575
576         /**
577          * {@inheritDoc}
578          */

579         RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents();
580
581         /**
582          * Applies a visitor to this generic type description.
583          *
584          * @param visitor The visitor to apply.
585          * @param <T>     The value that this visitor yields.
586          * @return The visitor's return value.
587          */

588         <T> T accept(Visitor<T> visitor);
589
590         /**
591          * A visitor that can be applied to a {@link Generic} for differentiating on the sort of the visited type.
592          *
593          * @param <T> The visitor's return value's type.
594          */

595         interface Visitor<T> {
596
597             /**
598              * Visits a generic array type ({@link Sort#GENERIC_ARRAY}).
599              *
600              * @param genericArray The generic array type.
601              * @return The visitor's return value.
602              */

603             T onGenericArray(Generic genericArray);
604
605             /**
606              * Visits a wildcard ({@link Sort#WILDCARD}).
607              *
608              * @param wildcard The wildcard.
609              * @return The visitor's return value.
610              */

611             T onWildcard(Generic wildcard);
612
613             /**
614              * Visits a parameterized type ({@link Sort#PARAMETERIZED}).
615              *
616              * @param parameterizedType The generic array type.
617              * @return The visitor's return value.
618              */

619             T onParameterizedType(Generic parameterizedType);
620
621             /**
622              * Visits a type variable ({@link Sort#VARIABLE}, {@link Sort#VARIABLE_SYMBOLIC}).
623              *
624              * @param typeVariable The generic array type.
625              * @return The visitor's return value.
626              */

627             T onTypeVariable(Generic typeVariable);
628
629             /**
630              * Visits a non-generic type ({@link Sort#NON_GENERIC}).
631              *
632              * @param typeDescription The non-generic type.
633              * @return The visitor's return value.
634              */

635             T onNonGenericType(Generic typeDescription);
636
637             /**
638              * A non-operational generic type visitor. Any visited type is returned in its existing form.
639              */

640             enum NoOp implements Visitor<Generic> {
641
642                 /**
643                  * The singleton instance.
644                  */

645                 INSTANCE;
646
647                 /**
648                  * {@inheritDoc}
649                  */

650                 public Generic onGenericArray(Generic genericArray) {
651                     return genericArray;
652                 }
653
654                 /**
655                  * {@inheritDoc}
656                  */

657                 public Generic onWildcard(Generic wildcard) {
658                     return wildcard;
659                 }
660
661                 /**
662                  * {@inheritDoc}
663                  */

664                 public Generic onParameterizedType(Generic parameterizedType) {
665                     return parameterizedType;
666                 }
667
668                 /**
669                  * {@inheritDoc}
670                  */

671                 public Generic onTypeVariable(Generic typeVariable) {
672                     return typeVariable;
673                 }
674
675                 /**
676                  * {@inheritDoc}
677                  */

678                 public Generic onNonGenericType(Generic typeDescription) {
679                     return typeDescription;
680                 }
681             }
682
683             /**
684              * A visitor that returns the erasure of any visited type. For wildcard types, an exception is thrown.
685              */

686             enum TypeErasing implements Visitor<Generic> {
687
688                 /**
689                  * The singleton instance.
690                  */

691                 INSTANCE;
692
693                 /**
694                  * {@inheritDoc}
695                  */

696                 public Generic onGenericArray(Generic genericArray) {
697                     return genericArray.asRawType();
698                 }
699
700                 /**
701                  * {@inheritDoc}
702                  */

703                 public Generic onWildcard(Generic wildcard) {
704                     throw new IllegalArgumentException("Cannot erase a wildcard type: " + wildcard);
705                 }
706
707                 /**
708                  * {@inheritDoc}
709                  */

710                 public Generic onParameterizedType(Generic parameterizedType) {
711                     return parameterizedType.asRawType();
712                 }
713
714                 /**
715                  * {@inheritDoc}
716                  */

717                 public Generic onTypeVariable(Generic typeVariable) {
718                     return typeVariable.asRawType();
719                 }
720
721                 /**
722                  * {@inheritDoc}
723                  */

724                 public Generic onNonGenericType(Generic typeDescription) {
725                     return typeDescription.asRawType();
726                 }
727             }
728
729             /**
730              * A visitor that strips all type annotations of all types.
731              */

732             enum AnnotationStripper implements Visitor<Generic> {
733
734                 /**
735                  * The singleton instance.
736                  */

737                 INSTANCE;
738
739                 /**
740                  * {@inheritDoc}
741                  */

742                 public Generic onGenericArray(Generic genericArray) {
743                     return new OfGenericArray.Latent(genericArray.getComponentType().accept(this), Empty.INSTANCE);
744                 }
745
746                 /**
747                  * {@inheritDoc}
748                  */

749                 public Generic onWildcard(Generic wildcard) {
750                     return new OfWildcardType.Latent(wildcard.getUpperBounds().accept(this), wildcard.getLowerBounds().accept(this), Empty.INSTANCE);
751                 }
752
753                 /**
754                  * {@inheritDoc}
755                  */

756                 public Generic onParameterizedType(Generic parameterizedType) {
757                     Generic ownerType = parameterizedType.getOwnerType();
758                     return new OfParameterizedType.Latent(parameterizedType.asErasure(),
759                             ownerType == null
760                                     ? UNDEFINED
761                                     : ownerType.accept(this),
762                             parameterizedType.getTypeArguments().accept(this),
763                             Empty.INSTANCE);
764                 }
765
766                 /**
767                  * {@inheritDoc}
768                  */

769                 public Generic onTypeVariable(Generic typeVariable) {
770                     return new NonAnnotatedTypeVariable(typeVariable);
771                 }
772
773                 /**
774                  * {@inheritDoc}
775                  */

776                 public Generic onNonGenericType(Generic typeDescription) {
777                     return typeDescription.isArray()
778                             ? new OfGenericArray.Latent(onNonGenericType(typeDescription.getComponentType()), Empty.INSTANCE)
779                             : new OfNonGenericType.Latent(typeDescription.asErasure(), Empty.INSTANCE);
780                 }
781
782                 /**
783                  * Representation of a type variable without annotations.
784                  */

785                 protected static class NonAnnotatedTypeVariable extends OfTypeVariable {
786
787                     /**
788                      * The represented type variable.
789                      */

790                     private final Generic typeVariable;
791
792                     /**
793                      * Creates a new non-annotated type variable.
794                      *
795                      * @param typeVariable The represented type variable.
796                      */

797                     protected NonAnnotatedTypeVariable(Generic typeVariable) {
798                         this.typeVariable = typeVariable;
799                     }
800
801                     /**
802                      * {@inheritDoc}
803                      */

804                     public TypeList.Generic getUpperBounds() {
805                         return typeVariable.getUpperBounds();
806                     }
807
808                     /**
809                      * {@inheritDoc}
810                      */

811                     public TypeVariableSource getTypeVariableSource() {
812                         return typeVariable.getTypeVariableSource();
813                     }
814
815                     /**
816                      * {@inheritDoc}
817                      */

818                     public String getSymbol() {
819                         return typeVariable.getSymbol();
820                     }
821
822                     /**
823                      * {@inheritDoc}
824                      */

825                     public AnnotationList getDeclaredAnnotations() {
826                         return new AnnotationList.Empty();
827                     }
828                 }
829             }
830
831             /**
832              * A visitor that determines the direct assignability of a type to another generic type. This visitor only checks
833              * for strict assignability and does not perform any form of boxing or primitive type widening that are allowed
834              * in the Java language.
835              */

836             enum Assigner implements Visitor<Assigner.Dispatcher> {
837
838                 /**
839                  * The singleton instance.
840                  */

841                 INSTANCE;
842
843                 /**
844                  * {@inheritDoc}
845                  */

846                 public Dispatcher onGenericArray(Generic genericArray) {
847                     return new Dispatcher.ForGenericArray(genericArray);
848                 }
849
850                 /**
851                  * {@inheritDoc}
852                  */

853                 public Dispatcher onWildcard(Generic wildcard) {
854                     throw new IllegalArgumentException("A wildcard is not a first level type: " + this);
855                 }
856
857                 /**
858                  * {@inheritDoc}
859                  */

860                 public Dispatcher onParameterizedType(Generic parameterizedType) {
861                     return new Dispatcher.ForParameterizedType(parameterizedType);
862                 }
863
864                 /**
865                  * {@inheritDoc}
866                  */

867                 public Dispatcher onTypeVariable(Generic typeVariable) {
868                     return new Dispatcher.ForTypeVariable(typeVariable);
869                 }
870
871                 /**
872                  * {@inheritDoc}
873                  */

874                 public Dispatcher onNonGenericType(Generic typeDescription) {
875                     return new Dispatcher.ForNonGenericType(typeDescription.asErasure());
876                 }
877
878                 /**
879                  * A dispatcher that allows to check if the visited generic type is assignable to the supplied type.
880                  */

881                 public interface Dispatcher {
882
883                     /**
884                      * Checks if the represented type is a super type of the type that is supplied as an argument.
885                      *
886                      * @param typeDescription The type to check for being assignable to the represented type.
887                      * @return {@code trueif the represented type is assignable to the supplied type.
888                      */

889                     boolean isAssignableFrom(Generic typeDescription);
890
891                     /**
892                      * An abstract base implementation of a dispatcher that forwards the decision to a visitor implementation.
893                      */

894                     abstract class AbstractBase implements Dispatcher, Visitor<Boolean> {
895
896                         /**
897                          * {@inheritDoc}
898                          */

899                         public boolean isAssignableFrom(Generic typeDescription) {
900                             return typeDescription.accept(this);
901                         }
902                     }
903
904                     /**
905                      * A dispatcher for checking the assignability of a non-generic type.
906                      */

907                     @HashCodeAndEqualsPlugin.Enhance
908                     class ForNonGenericType extends AbstractBase {
909
910                         /**
911                          * The description of the type to which another type is assigned.
912                          */

913                         private final TypeDescription typeDescription;
914
915                         /**
916                          * Creates a new dispatcher of a non-generic type.
917                          *
918                          * @param typeDescription The description of the type to which another type is assigned.
919                          */

920                         protected ForNonGenericType(TypeDescription typeDescription) {
921                             this.typeDescription = typeDescription;
922                         }
923
924                         /**
925                          * {@inheritDoc}
926                          */

927                         public Boolean onGenericArray(Generic genericArray) {
928                             return typeDescription.isArray()
929                                     ? genericArray.getComponentType().accept(new ForNonGenericType(typeDescription.getComponentType()))
930                                     : typeDescription.represents(Object.class) || TypeDescription.ARRAY_INTERFACES.contains(typeDescription.asGenericType());
931                         }
932
933                         /**
934                          * {@inheritDoc}
935                          */

936                         public Boolean onWildcard(Generic wildcard) {
937                             throw new IllegalArgumentException("A wildcard is not a first-level type: " + wildcard);
938                         }
939
940                         /**
941                          * {@inheritDoc}
942                          */

943                         public Boolean onParameterizedType(Generic parameterizedType) {
944                             if (typeDescription.equals(parameterizedType.asErasure())) {
945                                 return true;
946                             }
947                             Generic superClass = parameterizedType.getSuperClass();
948                             if (superClass != null && isAssignableFrom(superClass)) {
949                                 return true;
950                             }
951                             for (Generic interfaceType : parameterizedType.getInterfaces()) {
952                                 if (isAssignableFrom(interfaceType)) {
953                                     return true;
954                                 }
955                             }
956                             return typeDescription.represents(Object.class);
957                         }
958
959                         /**
960                          * {@inheritDoc}
961                          */

962                         public Boolean onTypeVariable(Generic typeVariable) {
963                             for (Generic upperBound : typeVariable.getUpperBounds()) {
964                                 if (isAssignableFrom(upperBound)) {
965                                     return true;
966                                 }
967                             }
968                             return false;
969                         }
970
971                         /**
972                          * {@inheritDoc}
973                          */

974                         public Boolean onNonGenericType(Generic typeDescription) {
975                             return this.typeDescription.isAssignableFrom(typeDescription.asErasure());
976                         }
977                     }
978
979                     /**
980                      * A dispatcher for checking the assignability of a type variable.
981                      */

982                     @HashCodeAndEqualsPlugin.Enhance
983                     class ForTypeVariable extends AbstractBase {
984
985                         /**
986                          * The description of the type variable to which another type is assigned.
987                          */

988                         private final Generic typeVariable;
989
990                         /**
991                          * Creates a new dispatcher of a type variable.
992                          *
993                          * @param typeVariable The description of the type variable to which another type is assigned.
994                          */

995                         protected ForTypeVariable(Generic typeVariable) {
996                             this.typeVariable = typeVariable;
997                         }
998
999                         /**
1000                          * {@inheritDoc}
1001                          */

1002                         public Boolean onGenericArray(Generic genericArray) {
1003                             return false;
1004                         }
1005
1006                         /**
1007                          * {@inheritDoc}
1008                          */

1009                         public Boolean onWildcard(Generic wildcard) {
1010                             throw new IllegalArgumentException("A wildcard is not a first-level type: " + wildcard);
1011                         }
1012
1013                         /**
1014                          * {@inheritDoc}
1015                          */

1016                         public Boolean onParameterizedType(Generic parameterizedType) {
1017                             return false;
1018                         }
1019
1020                         /**
1021                          * {@inheritDoc}
1022                          */

1023                         public Boolean onTypeVariable(Generic typeVariable) {
1024                             if (typeVariable.equals(this.typeVariable)) {
1025                                 return true;
1026                             }
1027                             for (Generic upperBound : typeVariable.getUpperBounds()) {
1028                                 if (isAssignableFrom(upperBound)) {
1029                                     return true;
1030                                 }
1031                             }
1032                             return false;
1033                         }
1034
1035                         /**
1036                          * {@inheritDoc}
1037                          */

1038                         public Boolean onNonGenericType(Generic typeDescription) {
1039                             return false;
1040                         }
1041                     }
1042
1043                     /**
1044                      * A dispatcher for checking the assignability of a parameterized type.
1045                      */

1046                     @HashCodeAndEqualsPlugin.Enhance
1047                     class ForParameterizedType extends AbstractBase {
1048
1049                         /**
1050                          * The parameterized type to which another type is assigned.
1051                          */

1052                         private final Generic parameterizedType;
1053
1054                         /**
1055                          * Creates a new dispatcher for checking the assignability of a parameterized type.
1056                          *
1057                          * @param parameterizedType The parameterized type to which another type is assigned.
1058                          */

1059                         protected ForParameterizedType(Generic parameterizedType) {
1060                             this.parameterizedType = parameterizedType;
1061                         }
1062
1063                         /**
1064                          * {@inheritDoc}
1065                          */

1066                         public Boolean onGenericArray(Generic genericArray) {
1067                             return false;
1068                         }
1069
1070                         /**
1071                          * {@inheritDoc}
1072                          */

1073                         public Boolean onWildcard(Generic wildcard) {
1074                             throw new IllegalArgumentException("A wildcard is not a first-level type: " + wildcard);
1075                         }
1076
1077                         /**
1078                          * {@inheritDoc}
1079                          */

1080                         public Boolean onParameterizedType(Generic parameterizedType) {
1081                             if (this.parameterizedType.asErasure().equals(parameterizedType.asErasure())) {
1082                                 Generic fromOwner = this.parameterizedType.getOwnerType(), toOwner = parameterizedType.getOwnerType();
1083                                 if (fromOwner != null && toOwner != null && !fromOwner.accept(Assigner.INSTANCE).isAssignableFrom(toOwner)) {
1084                                     return false;
1085                                 }
1086                                 TypeList.Generic fromArguments = this.parameterizedType.getTypeArguments(), toArguments = parameterizedType.getTypeArguments();
1087                                 if (fromArguments.size() == toArguments.size()) {
1088                                     for (int index = 0; index < fromArguments.size(); index++) {
1089                                         if (!fromArguments.get(index).accept(ParameterAssigner.INSTANCE).isAssignableFrom(toArguments.get(index))) {
1090                                             return false;
1091                                         }
1092                                     }
1093                                     return true;
1094                                 } else {
1095                                     throw new IllegalArgumentException("Incompatible generic types: " + parameterizedType + " and " + this.parameterizedType);
1096                                 }
1097                             }
1098                             Generic superClass = parameterizedType.getSuperClass();
1099                             if (superClass != null && isAssignableFrom(superClass)) {
1100                                 return true;
1101                             }
1102                             for (Generic interfaceType : parameterizedType.getInterfaces()) {
1103                                 if (isAssignableFrom(interfaceType)) {
1104                                     return true;
1105                                 }
1106                             }
1107                             return false;
1108                         }
1109
1110                         /**
1111                          * {@inheritDoc}
1112                          */

1113                         public Boolean onTypeVariable(Generic typeVariable) {
1114                             for (Generic upperBound : typeVariable.getUpperBounds()) {
1115                                 if (isAssignableFrom(upperBound)) {
1116                                     return true;
1117                                 }
1118                             }
1119                             return false;
1120                         }
1121
1122                         /**
1123                          * {@inheritDoc}
1124                          */

1125                         public Boolean onNonGenericType(Generic typeDescription) {
1126                             if (parameterizedType.asErasure().equals(typeDescription.asErasure())) {
1127                                 return true;
1128                             }
1129                             Generic superClass = typeDescription.getSuperClass();
1130                             if (superClass != null && isAssignableFrom(superClass)) {
1131                                 return true;
1132                             }
1133                             for (Generic interfaceType : typeDescription.getInterfaces()) {
1134                                 if (isAssignableFrom(interfaceType)) {
1135                                     return true;
1136                                 }
1137                             }
1138                             return false;
1139                         }
1140
1141                         /**
1142                          * An assigner for a parameter of a parameterized type.
1143                          */

1144                         protected enum ParameterAssigner implements Visitor<Dispatcher> {
1145
1146                             /**
1147                              * The singleton instance.
1148                              */

1149                             INSTANCE;
1150
1151                             /**
1152                              * {@inheritDoc}
1153                              */

1154                             public Dispatcher onGenericArray(Generic genericArray) {
1155                                 return new InvariantBinding(genericArray);
1156                             }
1157
1158                             /**
1159                              * {@inheritDoc}
1160                              */

1161                             public Dispatcher onWildcard(Generic wildcard) {
1162                                 TypeList.Generic lowerBounds = wildcard.getLowerBounds();
1163                                 return lowerBounds.isEmpty()
1164                                         ? new CovariantBinding(wildcard.getUpperBounds().getOnly())
1165                                         : new ContravariantBinding(lowerBounds.getOnly());
1166                             }
1167
1168                             /**
1169                              * {@inheritDoc}
1170                              */

1171                             public Dispatcher onParameterizedType(Generic parameterizedType) {
1172                                 return new InvariantBinding(parameterizedType);
1173                             }
1174
1175                             /**
1176                              * {@inheritDoc}
1177                              */

1178                             public Dispatcher onTypeVariable(Generic typeVariable) {
1179                                 return new InvariantBinding(typeVariable);
1180                             }
1181
1182                             /**
1183                              * {@inheritDoc}
1184                              */

1185                             public Dispatcher onNonGenericType(Generic typeDescription) {
1186                                 return new InvariantBinding(typeDescription);
1187                             }
1188
1189                             /**
1190                              * A dispatcher for an invariant parameter of a parameterized type, i.e. a type without a wildcard.
1191                              */

1192                             @HashCodeAndEqualsPlugin.Enhance
1193                             protected static class InvariantBinding implements Dispatcher {
1194
1195                                 /**
1196                                  * The invariant type of the parameter.
1197                                  */

1198                                 private final Generic typeDescription;
1199
1200                                 /**
1201                                  * Creates a new dispatcher for an invariant parameter of a parameterized type.
1202                                  *
1203                                  * @param typeDescription The invariant type of the parameter.
1204                                  */

1205                                 protected InvariantBinding(Generic typeDescription) {
1206                                     this.typeDescription = typeDescription;
1207                                 }
1208
1209                                 /**
1210                                  * {@inheritDoc}
1211                                  */

1212                                 public boolean isAssignableFrom(Generic typeDescription) {
1213                                     return typeDescription.equals(this.typeDescription);
1214                                 }
1215                             }
1216
1217                             /**
1218                              * A dispatcher for an covariant parameter of a parameterized type, i.e. a type that is the lower bound of a wildcard.
1219                              */

1220                             @HashCodeAndEqualsPlugin.Enhance
1221                             protected static class CovariantBinding implements Dispatcher {
1222
1223                                 /**
1224                                  * The lower bound type of a covariant parameter.
1225                                  */

1226                                 private final Generic upperBound;
1227
1228                                 /**
1229                                  * Creates a new dispatcher for covariant parameter of a parameterized type.
1230                                  *
1231                                  * @param upperBound The upper bound type of a covariant parameter.
1232                                  */

1233                                 protected CovariantBinding(Generic upperBound) {
1234                                     this.upperBound = upperBound;
1235                                 }
1236
1237                                 /**
1238                                  * {@inheritDoc}
1239                                  */

1240                                 public boolean isAssignableFrom(Generic typeDescription) {
1241                                     if (typeDescription.getSort().isWildcard()) {
1242                                         return typeDescription.getLowerBounds().isEmpty() && upperBound.accept(Assigner.INSTANCE)
1243                                                 .isAssignableFrom(typeDescription.getUpperBounds().getOnly());
1244                                     } else {
1245                                         return upperBound.accept(Assigner.INSTANCE).isAssignableFrom(typeDescription);
1246                                     }
1247                                 }
1248                             }
1249
1250                             /**
1251                              * A dispatcher for an contravariant parameter of a parameterized type, i.e. a type that is the lower bound of a wildcard.
1252                              */

1253                             @HashCodeAndEqualsPlugin.Enhance
1254                             protected static class ContravariantBinding implements Dispatcher {
1255
1256                                 /**
1257                                  * The lower bound type of a contravariant parameter.
1258                                  */

1259                                 private final Generic lowerBound;
1260
1261                                 /**
1262                                  * Creates a new dispatcher for contravariant parameter of a parameterized type.
1263                                  *
1264                                  * @param lowerBound The lower bound type of a contravariant parameter.
1265                                  */

1266                                 protected ContravariantBinding(Generic lowerBound) {
1267                                     this.lowerBound = lowerBound;
1268                                 }
1269
1270                                 /**
1271                                  * {@inheritDoc}
1272                                  */

1273                                 public boolean isAssignableFrom(Generic typeDescription) {
1274                                     if (typeDescription.getSort().isWildcard()) {
1275                                         TypeList.Generic lowerBounds = typeDescription.getLowerBounds();
1276                                         return !lowerBounds.isEmpty() && lowerBounds.getOnly().accept(Assigner.INSTANCE).isAssignableFrom(lowerBound);
1277                                     } else {
1278                                         return typeDescription.getSort().isWildcard() || typeDescription.accept(Assigner.INSTANCE).isAssignableFrom(lowerBound);
1279                                     }
1280                                 }
1281                             }
1282                         }
1283                     }
1284
1285                     /**
1286                      * A dispatcher for checking the assignability of a generic array type.
1287                      */

1288                     @HashCodeAndEqualsPlugin.Enhance
1289                     class ForGenericArray extends AbstractBase {
1290
1291                         /**
1292                          * The generic array type to which another type is assigned.
1293                          */

1294                         private final Generic genericArray;
1295
1296                         /**
1297                          * Creates a new dispatcher for checking the assignability of a generic array type.
1298                          *
1299                          * @param genericArray The generic array type to which another type is assigned.
1300                          */

1301                         protected ForGenericArray(Generic genericArray) {
1302                             this.genericArray = genericArray;
1303                         }
1304
1305                         /**
1306                          * {@inheritDoc}
1307                          */

1308                         public Boolean onGenericArray(Generic genericArray) {
1309                             return this.genericArray.getComponentType().accept(Assigner.INSTANCE).isAssignableFrom(genericArray.getComponentType());
1310                         }
1311
1312                         /**
1313                          * {@inheritDoc}
1314                          */

1315                         public Boolean onWildcard(Generic wildcard) {
1316                             throw new IllegalArgumentException("A wildcard is not a first-level type: " + wildcard);
1317                         }
1318
1319                         /**
1320                          * {@inheritDoc}
1321                          */

1322                         public Boolean onParameterizedType(Generic parameterizedType) {
1323                             return false;
1324                         }
1325
1326                         /**
1327                          * {@inheritDoc}
1328                          */

1329                         public Boolean onTypeVariable(Generic typeVariable) {
1330                             return false;
1331                         }
1332
1333                         /**
1334                          * {@inheritDoc}
1335                          */

1336                         public Boolean onNonGenericType(Generic typeDescription) {
1337                             return typeDescription.isArray()
1338                                     && genericArray.getComponentType().accept(Assigner.INSTANCE).isAssignableFrom(typeDescription.getComponentType());
1339                         }
1340                     }
1341                 }
1342             }
1343
1344             /**
1345              * A validator for Java types that are defined for a specified type use within a Java class file.
1346              */

1347             enum Validator implements Visitor<Boolean> {
1348
1349                 /**
1350                  * A validator for checking a type's non-null super class.
1351                  */

1352                 SUPER_CLASS(falsefalsefalsefalse) {
1353                     /** {@inheritDoc} */
1354                     public Boolean onNonGenericType(Generic typeDescription) {
1355                         return super.onNonGenericType(typeDescription) && !typeDescription.isInterface();
1356                     }
1357
1358                     /** {@inheritDoc} */
1359                     public Boolean onParameterizedType(Generic parameterizedType) {
1360                         return !parameterizedType.isInterface();
1361                     }
1362                 },
1363
1364                 /**
1365                  * A validator for an interface type.
1366                  */

1367                 INTERFACE(falsefalsefalsefalse) {
1368                     /** {@inheritDoc} */
1369                     public Boolean onNonGenericType(Generic typeDescription) {
1370                         return super.onNonGenericType(typeDescription) && typeDescription.isInterface();
1371                     }
1372
1373                     /** {@inheritDoc} */
1374                     public Boolean onParameterizedType(Generic parameterizedType) {
1375                         return parameterizedType.isInterface();
1376                     }
1377                 },
1378
1379                 /**
1380                  * A validator for a type variable.
1381                  */

1382                 TYPE_VARIABLE(falsefalsetruefalse),
1383
1384                 /**
1385                  * A validator for a field type.
1386                  */

1387                 FIELD(truetruetruefalse),
1388
1389                 /**
1390                  * A validator for a method return type.
1391                  */

1392                 METHOD_RETURN(truetruetruetrue),
1393
1394                 /**
1395                  * A validator for a method parameter type.
1396                  */

1397                 METHOD_PARAMETER(truetruetruefalse),
1398
1399                 /**
1400                  * A validator for a method exception type.
1401                  */

1402                 EXCEPTION(falsefalsetruefalse) {
1403                     /** {@inheritDoc} */
1404                     public Boolean onParameterizedType(Generic parameterizedType) {
1405                         return false;
1406                     }
1407
1408                     /** {@inheritDoc} */
1409                     public Boolean onTypeVariable(Generic typeVariable) {
1410                         for (TypeDescription.Generic bound : typeVariable.getUpperBounds()) {
1411                             if (bound.accept(this)) {
1412                                 return true;
1413                             }
1414                         }
1415                         return false;
1416                     }
1417
1418                     /** {@inheritDoc} */
1419                     public Boolean onNonGenericType(Generic typeDescription) {
1420                         return typeDescription.asErasure().isAssignableTo(Throwable.class);
1421                     }
1422                 },
1423
1424                 /**
1425                  * A validator for a method receiver type.
1426                  */

1427                 RECEIVER(falsefalsefalsefalse);
1428
1429                 /**
1430                  * {@code trueif this validator accepts array types.
1431                  */

1432                 private final boolean acceptsArray;
1433
1434                 /**
1435                  * {@code trueif this validator accepts primitive types.
1436                  */

1437                 private final boolean acceptsPrimitive;
1438
1439                 /**
1440                  * {@code trueif this validator accepts type variables.
1441                  */

1442                 private final boolean acceptsVariable;
1443
1444                 /**
1445                  * {@code trueif this validator accepts the {@code void} type.
1446                  */

1447                 private final boolean acceptsVoid;
1448
1449                 /**
1450                  * Creates a new validator.
1451                  *
1452                  * @param acceptsArray     {@code trueif this validator accepts array types.
1453                  * @param acceptsPrimitive {@code trueif this validator accepts primitive types.
1454                  * @param acceptsVariable  {@code trueif this validator accepts type variables.
1455                  * @param acceptsVoid      {@code trueif this validator accepts the {@code void} type.
1456                  */

1457                 Validator(boolean acceptsArray, boolean acceptsPrimitive, boolean acceptsVariable, boolean acceptsVoid) {
1458                     this.acceptsArray = acceptsArray;
1459                     this.acceptsPrimitive = acceptsPrimitive;
1460                     this.acceptsVariable = acceptsVariable;
1461                     this.acceptsVoid = acceptsVoid;
1462                 }
1463
1464                 /**
1465                  * {@inheritDoc}
1466                  */

1467                 public Boolean onGenericArray(Generic genericArray) {
1468                     return acceptsArray;
1469                 }
1470
1471                 /**
1472                  * {@inheritDoc}
1473                  */

1474                 public Boolean onWildcard(Generic wildcard) {
1475                     return false;
1476                 }
1477
1478                 /**
1479                  * {@inheritDoc}
1480                  */

1481                 public Boolean onParameterizedType(Generic parameterizedType) {
1482                     return true;
1483                 }
1484
1485                 /**
1486                  * {@inheritDoc}
1487                  */

1488                 public Boolean onTypeVariable(Generic typeVariable) {
1489                     return acceptsVariable;
1490                 }
1491
1492                 /**
1493                  * {@inheritDoc}
1494                  */

1495                 public Boolean onNonGenericType(Generic typeDescription) {
1496                     return (acceptsArray || !typeDescription.isArray())
1497                             && (acceptsPrimitive || !typeDescription.isPrimitive())
1498                             && (acceptsVoid || !typeDescription.represents(void.class));
1499                 }
1500
1501                 /**
1502                  * A type validator for checking type annotations.
1503                  */

1504                 public enum ForTypeAnnotations implements Visitor<Boolean> {
1505
1506                     /**
1507                      * The singleton instance.
1508                      */

1509                     INSTANCE;
1510
1511                     /**
1512                      * The {@link ElementType}'s {@code TYPE_USE} constant.
1513                      */

1514                     private final ElementType typeUse;
1515
1516                     /**
1517                      * The {@link ElementType}'s {@code TYPE_PARAMETER} constant.
1518                      */

1519                     private final ElementType typeParameter;
1520
1521                     /**
1522                      * Creates a new type annotation validator.
1523                      */

1524                     ForTypeAnnotations() {
1525                         ElementType typeUse, typeParameter;
1526                         try {
1527                             typeUse = Enum.valueOf(ElementType.class"TYPE_USE");
1528                             typeParameter = Enum.valueOf(ElementType.class"TYPE_PARAMETER");
1529                         } catch (IllegalArgumentException ignored) {
1530                             // Setting these values null results in this validator always failing for pre Java-8 VMs.
1531                             typeUse = null;
1532                             typeParameter = null;
1533                         }
1534                         this.typeUse = typeUse;
1535                         this.typeParameter = typeParameter;
1536                     }
1537
1538                     /**
1539                      * Validates the type annotations on a formal type variable but not on its bounds..
1540                      *
1541                      * @param typeVariable The type variable to validate.
1542                      * @return {@code trueif the formal type variable declares invalid type annotations.
1543                      */

1544                     public static boolean ofFormalTypeVariable(Generic typeVariable) {
1545                         Set<TypeDescription> annotationTypes = new HashSet<TypeDescription>();
1546                         for (AnnotationDescription annotationDescription : typeVariable.getDeclaredAnnotations()) {
1547                             if (!annotationDescription.getElementTypes().contains(INSTANCE.typeParameter) || !annotationTypes.add(annotationDescription.getAnnotationType())) {
1548                                 return false;
1549                             }
1550                         }
1551                         return true;
1552                     }
1553
1554                     /**
1555                      * {@inheritDoc}
1556                      */

1557                     public Boolean onGenericArray(Generic genericArray) {
1558                         return isValid(genericArray) && genericArray.getComponentType().accept(this);
1559                     }
1560
1561                     /**
1562                      * {@inheritDoc}
1563                      */

1564                     public Boolean onWildcard(Generic wildcard) {
1565                         if (!isValid(wildcard)) {
1566                             return false;
1567                         }
1568                         TypeList.Generic lowerBounds = wildcard.getLowerBounds();
1569                         return (lowerBounds.isEmpty()
1570                                 ? wildcard.getUpperBounds()
1571                                 : lowerBounds).getOnly().accept(this);
1572                     }
1573
1574                     /**
1575                      * {@inheritDoc}
1576                      */

1577                     public Boolean onParameterizedType(Generic parameterizedType) {
1578                         if (!isValid(parameterizedType)) {
1579                             return false;
1580                         }
1581                         Generic ownerType = parameterizedType.getOwnerType();
1582                         if (ownerType != null && !ownerType.accept(this)) {
1583                             return false;
1584                         }
1585                         for (Generic typeArgument : parameterizedType.getTypeArguments()) {
1586                             if (!typeArgument.accept(this)) {
1587                                 return false;
1588                             }
1589                         }
1590                         return true;
1591                     }
1592
1593                     /**
1594                      * {@inheritDoc}
1595                      */

1596                     public Boolean onTypeVariable(Generic typeVariable) {
1597                         return isValid(typeVariable);
1598                     }
1599
1600                     /**
1601                      * {@inheritDoc}
1602                      */

1603                     public Boolean onNonGenericType(Generic typeDescription) {
1604                         return isValid(typeDescription) && (!typeDescription.isArray() || typeDescription.getComponentType().accept(this));
1605                     }
1606
1607                     /**
1608                      * Checks if the supplied type's type annotations are valid.
1609                      *
1610                      * @param typeDescription The type to validate.
1611                      * @return {@code trueif the supplied type's type annotations are valid.
1612                      */

1613                     private boolean isValid(Generic typeDescription) {
1614                         Set<TypeDescription> annotationTypes = new HashSet<TypeDescription>();
1615                         for (AnnotationDescription annotationDescription : typeDescription.getDeclaredAnnotations()) {
1616                             if (!annotationDescription.getElementTypes().contains(typeUse) || !annotationTypes.add(annotationDescription.getAnnotationType())) {
1617                                 return false;
1618                             }
1619                         }
1620                         return true;
1621                     }
1622                 }
1623             }
1624
1625             /**
1626              * A visitor that reifies type descriptions if they represent raw types.
1627              */

1628             enum Reifying implements Visitor<Generic> {
1629
1630                 /**
1631                  * A visitor that reifies non-generic types if they represent raw types. This visitor should be applied when
1632                  * visiting a potential raw type.
1633                  */

1634                 INITIATING {
1635                     /** {@inheritDoc} */
1636                     public Generic onParameterizedType(Generic parameterizedType) {
1637                         return parameterizedType;
1638                     }
1639                 },
1640
1641                 /**
1642                  * A visitor that reifies non-generic types if they represent raw types or are parameterized types. This visitor
1643                  * should only be applied when a type was inherited from a reified type.
1644                  */

1645                 INHERITING {
1646                     /** {@inheritDoc} */
1647                     public Generic onParameterizedType(Generic parameterizedType) {
1648                         return new OfParameterizedType.ForReifiedType(parameterizedType);
1649                     }
1650                 };
1651
1652                 /**
1653                  * {@inheritDoc}
1654                  */

1655                 public Generic onGenericArray(Generic genericArray) {
1656                     throw new IllegalArgumentException("Cannot reify a generic array: " + genericArray);
1657                 }
1658
1659                 /**
1660                  * {@inheritDoc}
1661                  */

1662                 public Generic onWildcard(Generic wildcard) {
1663                     throw new IllegalArgumentException("Cannot reify a wildcard: " + wildcard);
1664                 }
1665
1666                 /**
1667                  * {@inheritDoc}
1668                  */

1669                 public Generic onTypeVariable(Generic typeVariable) {
1670                     throw new IllegalArgumentException("Cannot reify a type variable: " + typeVariable);
1671                 }
1672
1673                 /**
1674                  * {@inheritDoc}
1675                  */

1676                 public Generic onNonGenericType(Generic typeDescription) {
1677                     TypeDescription erasure = typeDescription.asErasure();
1678                     return erasure.isGenerified()
1679                             ? new OfNonGenericType.ForReifiedErasure(erasure)
1680                             : typeDescription;
1681                 }
1682             }
1683
1684             /**
1685              * Visits a generic type and appends the discovered type to the supplied signature visitor.
1686              */

1687             @HashCodeAndEqualsPlugin.Enhance
1688             class ForSignatureVisitor implements Visitor<SignatureVisitor> {
1689
1690                 /**
1691                  * Index of a {@link String}'s only character to improve code readability.
1692                  */

1693                 private static final int ONLY_CHARACTER = 0;
1694
1695                 /**
1696                  * The signature visitor that receives the discovered generic type.
1697                  */

1698                 protected final SignatureVisitor signatureVisitor;
1699
1700                 /**
1701                  * Creates a new visitor for the given signature visitor.
1702                  *
1703                  * @param signatureVisitor The signature visitor that receives the discovered generic type.
1704                  */

1705                 public ForSignatureVisitor(SignatureVisitor signatureVisitor) {
1706                     this.signatureVisitor = signatureVisitor;
1707                 }
1708
1709                 /**
1710                  * {@inheritDoc}
1711                  */

1712                 public SignatureVisitor onGenericArray(Generic genericArray) {
1713                     genericArray.getComponentType().accept(new ForSignatureVisitor(signatureVisitor.visitArrayType()));
1714                     return signatureVisitor;
1715                 }
1716
1717                 /**
1718                  * {@inheritDoc}
1719                  */

1720                 public SignatureVisitor onWildcard(Generic wildcard) {
1721                     throw new IllegalStateException("Unexpected wildcard: " + wildcard);
1722                 }
1723
1724                 /**
1725                  * {@inheritDoc}
1726                  */

1727                 public SignatureVisitor onParameterizedType(Generic parameterizedType) {
1728                     onOwnableType(parameterizedType);
1729                     signatureVisitor.visitEnd();
1730                     return signatureVisitor;
1731                 }
1732
1733                 /**
1734                  * Visits a type which might define an owner type.
1735                  *
1736                  * @param ownableType The visited generic type.
1737                  */

1738                 private void onOwnableType(Generic ownableType) {
1739                     Generic ownerType = ownableType.getOwnerType();
1740                     if (ownerType != null && ownerType.getSort().isParameterized()) {
1741                         onOwnableType(ownerType);
1742                         signatureVisitor.visitInnerClassType(ownableType.asErasure().getSimpleName());
1743                     } else {
1744                         signatureVisitor.visitClassType(ownableType.asErasure().getInternalName());
1745                     }
1746                     for (Generic typeArgument : ownableType.getTypeArguments()) {
1747                         typeArgument.accept(new OfTypeArgument(signatureVisitor));
1748                     }
1749                 }
1750
1751                 /**
1752                  * {@inheritDoc}
1753                  */

1754                 public SignatureVisitor onTypeVariable(Generic typeVariable) {
1755                     signatureVisitor.visitTypeVariable(typeVariable.getSymbol());
1756                     return signatureVisitor;
1757                 }
1758
1759                 /**
1760                  * {@inheritDoc}
1761                  */

1762                 public SignatureVisitor onNonGenericType(Generic typeDescription) {
1763                     if (typeDescription.isArray()) {
1764                         typeDescription.getComponentType().accept(new ForSignatureVisitor(signatureVisitor.visitArrayType()));
1765                     } else if (typeDescription.isPrimitive()) {
1766                         signatureVisitor.visitBaseType(typeDescription.asErasure().getDescriptor().charAt(ONLY_CHARACTER));
1767                     } else {
1768                         signatureVisitor.visitClassType(typeDescription.asErasure().getInternalName());
1769                         signatureVisitor.visitEnd();
1770                     }
1771                     return signatureVisitor;
1772                 }
1773
1774                 /**
1775                  * Visits a parameter while visiting a generic type for delegating discoveries to a signature visitor.
1776                  */

1777                 protected static class OfTypeArgument extends ForSignatureVisitor {
1778
1779                     /**
1780                      * Creates a new parameter visitor.
1781                      *
1782                      * @param signatureVisitor The signature visitor which is notified over visited types.
1783                      */

1784                     protected OfTypeArgument(SignatureVisitor signatureVisitor) {
1785                         super(signatureVisitor);
1786                     }
1787
1788                     /**
1789                      * {@inheritDoc}
1790                      */

1791                     public SignatureVisitor onWildcard(Generic wildcard) {
1792                         TypeList.Generic upperBounds = wildcard.getUpperBounds(), lowerBounds = wildcard.getLowerBounds();
1793                         if (lowerBounds.isEmpty() && upperBounds.getOnly().represents(Object.class)) {
1794                             signatureVisitor.visitTypeArgument();
1795                         } else if (!lowerBounds.isEmpty() /* && upperBounds.isEmpty() */) {
1796                             lowerBounds.getOnly().accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.SUPER)));
1797                         } else /* if (!upperBounds.isEmpty() && lowerBounds.isEmpty()) */ {
1798                             upperBounds.getOnly().accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.EXTENDS)));
1799                         }
1800                         return signatureVisitor;
1801                     }
1802
1803                     /**
1804                      * {@inheritDoc}
1805                      */

1806                     public SignatureVisitor onGenericArray(Generic genericArray) {
1807                         genericArray.accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.INSTANCEOF)));
1808                         return signatureVisitor;
1809                     }
1810
1811                     /**
1812                      * {@inheritDoc}
1813                      */

1814                     public SignatureVisitor onParameterizedType(Generic parameterizedType) {
1815                         parameterizedType.accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.INSTANCEOF)));
1816                         return signatureVisitor;
1817                     }
1818
1819                     /**
1820                      * {@inheritDoc}
1821                      */

1822                     public SignatureVisitor onTypeVariable(Generic typeVariable) {
1823                         typeVariable.accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.INSTANCEOF)));
1824                         return signatureVisitor;
1825                     }
1826
1827                     /**
1828                      * {@inheritDoc}
1829                      */

1830                     public SignatureVisitor onNonGenericType(Generic typeDescription) {
1831                         typeDescription.accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.INSTANCEOF)));
1832                         return signatureVisitor;
1833                     }
1834                 }
1835             }
1836
1837             /**
1838              * An abstract implementation of a visitor that substitutes generic types by replacing (nested)
1839              * type variables and/or non-generic component types.
1840              */

1841             abstract class Substitutor implements Visitor<Generic> {
1842
1843                 /**
1844                  * {@inheritDoc}
1845                  */

1846                 public Generic onParameterizedType(Generic parameterizedType) {
1847                     Generic ownerType = parameterizedType.getOwnerType();
1848                     List<Generic> typeArguments = new ArrayList<Generic>(parameterizedType.getTypeArguments().size());
1849                     for (Generic typeArgument : parameterizedType.getTypeArguments()) {
1850                         typeArguments.add(typeArgument.accept(this));
1851                     }
1852                     return new OfParameterizedType.Latent(parameterizedType.asRawType().accept(this).asErasure(),
1853                             ownerType == null
1854                                     ? UNDEFINED
1855                                     : ownerType.accept(this),
1856                             typeArguments,
1857                             parameterizedType);
1858                 }
1859
1860                 /**
1861                  * {@inheritDoc}
1862                  */

1863                 public Generic onGenericArray(Generic genericArray) {
1864                     return new OfGenericArray.Latent(genericArray.getComponentType().accept(this), genericArray);
1865                 }
1866
1867                 /**
1868                  * {@inheritDoc}
1869                  */

1870                 public Generic onWildcard(Generic wildcard) {
1871                     return new OfWildcardType.Latent(wildcard.getUpperBounds().accept(this), wildcard.getLowerBounds().accept(this), wildcard);
1872                 }
1873
1874                 /**
1875                  * {@inheritDoc}
1876                  */

1877                 public Generic onNonGenericType(Generic typeDescription) {
1878                     return typeDescription.isArray()
1879                             ? new OfGenericArray.Latent(typeDescription.getComponentType().accept(this), typeDescription)
1880                             : onSimpleType(typeDescription);
1881                 }
1882
1883                 /**
1884                  * Visits a simple, non-generic type, i.e. either a component type of an array or a non-array type.
1885                  *
1886                  * @param typeDescription The type that is visited.
1887                  * @return The substituted type.
1888                  */

1889                 protected abstract Generic onSimpleType(Generic typeDescription);
1890
1891                 /**
1892                  * A {@link Substitutor} that only substitutes type variables but fully preserves non-generic type definitions.
1893                  */

1894                 public abstract static class WithoutTypeSubstitution extends Substitutor {
1895
1896                     /**
1897                      * {@inheritDoc}
1898                      */

1899                     public Generic onNonGenericType(Generic typeDescription) {
1900                         return typeDescription;
1901                     }
1902
1903                     @Override
1904                     protected Generic onSimpleType(Generic typeDescription) {
1905                         return typeDescription;
1906                     }
1907                 }
1908
1909                 /**
1910                  * A substitutor that attaches type variables to a type variable source and replaces representations of
1911                  * {@link TargetType} with a given declaring type.
1912                  */

1913                 @HashCodeAndEqualsPlugin.Enhance
1914                 public static class ForAttachment extends Substitutor {
1915
1916                     /**
1917                      * The declaring type which is filled in for {@link TargetType}.
1918                      */

1919                     private final TypeDescription declaringType;
1920
1921                     /**
1922                      * The source which is used for locating type variables.
1923                      */

1924                     private final TypeVariableSource typeVariableSource;
1925
1926                     /**
1927                      * Creates a visitor for attaching type variables.
1928                      *
1929                      * @param declaringType      The declaring type which is filled in for {@link TargetType} in its erased form.
1930                      * @param typeVariableSource The source which is used for locating type variables.
1931                      */

1932                     protected ForAttachment(TypeDefinition declaringType, TypeVariableSource typeVariableSource) {
1933                         this(declaringType.asErasure(), typeVariableSource);
1934                     }
1935
1936                     /**
1937                      * Creates a visitor for attaching type variables.
1938                      *
1939                      * @param declaringType      The declaring type which is filled in for {@link TargetType}.
1940                      * @param typeVariableSource The source which is used for locating type variables.
1941                      */

1942                     protected ForAttachment(TypeDescription declaringType, TypeVariableSource typeVariableSource) {
1943                         this.declaringType = declaringType;
1944                         this.typeVariableSource = typeVariableSource;
1945                     }
1946
1947                     /**
1948                      * Attaches all types to the given type description.
1949                      *
1950                      * @param typeDescription The type description to which visited types should be attached to.
1951                      * @return A substitutor that attaches visited types to the given type's type context.
1952                      */

1953                     public static ForAttachment of(TypeDescription typeDescription) {
1954                         return new ForAttachment(typeDescription, typeDescription);
1955                     }
1956
1957                     /**
1958                      * Attaches all types to the given field description.
1959                      *
1960                      * @param fieldDescription The field description to which visited types should be attached to.
1961                      * @return A substitutor that attaches visited types to the given field's type context.
1962                      */

1963                     public static ForAttachment of(FieldDescription fieldDescription) {
1964                         return new ForAttachment(fieldDescription.getDeclaringType(), fieldDescription.getDeclaringType().asErasure());
1965                     }
1966
1967                     /**
1968                      * Attaches all types to the given method description.
1969                      *
1970                      * @param methodDescription The method description to which visited types should be attached to.
1971                      * @return A substitutor that attaches visited types to the given method's type context.
1972                      */

1973                     public static ForAttachment of(MethodDescription methodDescription) {
1974                         return new ForAttachment(methodDescription.getDeclaringType(), methodDescription);
1975                     }
1976
1977                     /**
1978                      * Attaches all types to the given parameter description.
1979                      *
1980                      * @param parameterDescription The parameter description to which visited types should be attached to.
1981                      * @return A substitutor that attaches visited types to the given parameter's type context.
1982                      */

1983                     public static ForAttachment of(ParameterDescription parameterDescription) {
1984                         return new ForAttachment(parameterDescription.getDeclaringMethod().getDeclaringType(), parameterDescription.getDeclaringMethod());
1985                     }
1986
1987                     /**
1988                      * Attaches all types to the given record component description.
1989                      *
1990                      * @param recordComponentDescription The record component description to which visited types should be attached to.
1991                      * @return A substitutor that attaches visited types to the given record component's type context.
1992                      */

1993                     public static ForAttachment of(RecordComponentDescription recordComponentDescription) {
1994                         return new ForAttachment(recordComponentDescription.getDeclaringType(), recordComponentDescription.getDeclaringType().asErasure());
1995                     }
1996
1997                     /**
1998                      * {@inheritDoc}
1999                      */

2000                     public Generic onTypeVariable(Generic typeVariable) {
2001                         Generic attachedVariable = typeVariableSource.findVariable(typeVariable.getSymbol());
2002                         if (attachedVariable == null) {
2003                             throw new IllegalArgumentException("Cannot attach undefined variable: " + typeVariable);
2004                         } else {
2005                             return new OfTypeVariable.WithAnnotationOverlay(attachedVariable, typeVariable);
2006                         }
2007                     }
2008
2009                     @Override
2010                     protected Generic onSimpleType(Generic typeDescription) {
2011                         return typeDescription.represents(TargetType.class)
2012                                 ? new OfNonGenericType.Latent(declaringType, typeDescription)
2013                                 : typeDescription;
2014                     }
2015                 }
2016
2017                 /**
2018                  * A visitor for detaching a type from its declaration context by detaching type variables. This is achieved by
2019                  * detaching type variables and by replacing the declaring type which is identified by a provided {@link ElementMatcher}
2020                  * with {@link TargetType}.
2021                  */

2022                 @HashCodeAndEqualsPlugin.Enhance
2023                 public static class ForDetachment extends Substitutor {
2024
2025                     /**
2026                      * A type matcher for identifying the declaring type.
2027                      */

2028                     private final ElementMatcher<? super TypeDescription> typeMatcher;
2029
2030                     /**
2031                      * Creates a visitor for detaching a type.
2032                      *
2033                      * @param typeMatcher A type matcher for identifying the declaring type.
2034                      */

2035                     public ForDetachment(ElementMatcher<? super TypeDescription> typeMatcher) {
2036                         this.typeMatcher = typeMatcher;
2037                     }
2038
2039                     /**
2040                      * Returns a new detachment visitor that detaches any type matching the supplied type description.
2041                      *
2042                      * @param typeDefinition The type to detach.
2043                      * @return A detachment visitor for the supplied type description.
2044                      */

2045                     public static Visitor<Generic> of(TypeDefinition typeDefinition) {
2046                         return new ForDetachment(is(typeDefinition));
2047                     }
2048
2049                     /**
2050                      * {@inheritDoc}
2051                      */

2052                     public Generic onTypeVariable(Generic typeVariable) {
2053                         return new OfTypeVariable.Symbolic(typeVariable.getSymbol(), typeVariable);
2054                     }
2055
2056                     @Override
2057                     protected Generic onSimpleType(Generic typeDescription) {
2058                         return typeMatcher.matches(typeDescription.asErasure())
2059                                 ? new OfNonGenericType.Latent(TargetType.DESCRIPTION, typeDescription.getOwnerType(), typeDescription)
2060                                 : typeDescription;
2061                     }
2062                 }
2063
2064                 /**
2065                  * A visitor for binding type variables to their values.
2066                  */

2067                 @HashCodeAndEqualsPlugin.Enhance
2068                 public static class ForTypeVariableBinding extends WithoutTypeSubstitution {
2069
2070                     /**
2071                      * The parameterized type for which type variables are bound.
2072                      */

2073                     private final Generic parameterizedType;
2074
2075                     /**
2076                      * Creates a new visitor for binding a parameterized type's type arguments to its type variables.
2077                      *
2078                      * @param parameterizedType The parameterized type for which type variables are bound.
2079                      */

2080                     protected ForTypeVariableBinding(Generic parameterizedType) {
2081                         this.parameterizedType = parameterizedType;
2082                     }
2083
2084                     /**
2085                      * {@inheritDoc}
2086                      */

2087                     public Generic onTypeVariable(Generic typeVariable) {
2088                         return typeVariable.getTypeVariableSource().accept(new TypeVariableSubstitutor(typeVariable));
2089                     }
2090
2091                     /**
2092                      * Substitutes a type variable, either with a new binding if the variable is defined by a type or with a
2093                      * retained type variable if the variable is defined by a method.
2094                      */

2095                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2096                     protected class TypeVariableSubstitutor implements TypeVariableSource.Visitor<Generic> {
2097
2098                         /**
2099                          * The discovered type variable.
2100                          */

2101                         private final Generic typeVariable;
2102
2103                         /**
2104                          * Creates a new type variable substitutor.
2105                          *
2106                          * @param typeVariable The discovered type variable.
2107                          */

2108                         protected TypeVariableSubstitutor(Generic typeVariable) {
2109                             this.typeVariable = typeVariable;
2110                         }
2111
2112                         /**
2113                          * {@inheritDoc}
2114                          */

2115                         public Generic onType(TypeDescription typeDescription) {
2116                             // A type variable might be undeclared due to breaking inner class semantics or due to incorrect scoping by a compiler.
2117                             Generic typeArgument = parameterizedType.findBindingOf(typeVariable);
2118                             return typeArgument == null
2119                                     ? typeVariable.asRawType()
2120                                     : typeArgument;
2121                         }
2122
2123                         /**
2124                          * {@inheritDoc}
2125                          */

2126                         public Generic onMethod(MethodDescription.InDefinedShape methodDescription) {
2127                             return new RetainedMethodTypeVariable(typeVariable);
2128                         }
2129                     }
2130
2131                     /**
2132                      * Implementation of a type variable on a method that is not substituted.
2133                      */

2134                     protected class RetainedMethodTypeVariable extends OfTypeVariable {
2135
2136                         /**
2137                          * The discovered type variable.
2138                          */

2139                         private final Generic typeVariable;
2140
2141                         /**
2142                          * Creates a new retained type variable.
2143                          *
2144                          * @param typeVariable The discovered type variable.
2145                          */

2146                         protected RetainedMethodTypeVariable(Generic typeVariable) {
2147                             this.typeVariable = typeVariable;
2148                         }
2149
2150                         /**
2151                          * {@inheritDoc}
2152                          */

2153                         public TypeList.Generic getUpperBounds() {
2154                             return typeVariable.getUpperBounds().accept(ForTypeVariableBinding.this);
2155                         }
2156
2157                         /**
2158                          * {@inheritDoc}
2159                          */

2160                         public TypeVariableSource getTypeVariableSource() {
2161                             return typeVariable.getTypeVariableSource();
2162                         }
2163
2164                         /**
2165                          * {@inheritDoc}
2166                          */

2167                         public String getSymbol() {
2168                             return typeVariable.getSymbol();
2169                         }
2170
2171                         /**
2172                          * {@inheritDoc}
2173                          */

2174                         public AnnotationList getDeclaredAnnotations() {
2175                             return typeVariable.getDeclaredAnnotations();
2176                         }
2177                     }
2178                 }
2179
2180                 /**
2181                  * A substitutor that normalizes a token to represent all {@link TargetType} by a given type and that symbolizes all type variables.
2182                  */

2183                 @HashCodeAndEqualsPlugin.Enhance
2184                 public static class ForTokenNormalization extends Substitutor {
2185
2186                     /**
2187                      * The type description to substitute all {@link TargetType} representations with.
2188                      */

2189                     private final TypeDescription typeDescription;
2190
2191                     /**
2192                      * Creates a new token normalization visitor.
2193                      *
2194                      * @param typeDescription The type description to substitute all {@link TargetType}
2195                      */

2196                     public ForTokenNormalization(TypeDescription typeDescription) {
2197                         this.typeDescription = typeDescription;
2198                     }
2199
2200                     @Override
2201                     protected Generic onSimpleType(Generic typeDescription) {
2202                         return typeDescription.represents(TargetType.class)
2203                                 ? new OfNonGenericType.Latent(this.typeDescription, typeDescription)
2204                                 : typeDescription;
2205                     }
2206
2207                     /**
2208                      * {@inheritDoc}
2209                      */

2210                     public Generic onTypeVariable(Generic typeVariable) {
2211                         return new OfTypeVariable.Symbolic(typeVariable.getSymbol(), typeVariable);
2212                     }
2213                 }
2214             }
2215
2216             /**
2217              * A visitor that transforms any type into a raw type if declaring type is generified. If the declaring type is
2218              * not generified, the original type description is returned.
2219              */

2220             class ForRawType implements Visitor<Generic> {
2221
2222                 /**
2223                  * The type description that is potentially a raw type.
2224                  */

2225                 private final TypeDescription declaringType;
2226
2227                 /**
2228                  * Creates a visitor for representing declared types of a potentially raw type.
2229                  *
2230                  * @param declaringType The type description that is potentially a raw type.
2231                  */

2232                 public ForRawType(TypeDescription declaringType) {
2233                     this.declaringType = declaringType;
2234                 }
2235
2236                 /**
2237                  * {@inheritDoc}
2238                  */

2239                 public Generic onGenericArray(Generic genericArray) {
2240                     return declaringType.isGenerified()
2241                             ? new Generic.OfNonGenericType.Latent(genericArray.asErasure(), genericArray)
2242                             : genericArray;
2243                 }
2244
2245                 /**
2246                  * {@inheritDoc}
2247                  */

2248                 public Generic onWildcard(Generic wildcard) {
2249                     throw new IllegalStateException("Did not expect wildcard on top-level: " + wildcard);
2250                 }
2251
2252                 /**
2253                  * {@inheritDoc}
2254                  */

2255                 public Generic onParameterizedType(Generic parameterizedType) {
2256                     return declaringType.isGenerified()
2257                             ? new Generic.OfNonGenericType.Latent(parameterizedType.asErasure(), parameterizedType)
2258                             : parameterizedType;
2259                 }
2260
2261                 /**
2262                  * {@inheritDoc}
2263                  */

2264                 public Generic onTypeVariable(Generic typeVariable) {
2265                     return declaringType.isGenerified()
2266                             ? new Generic.OfNonGenericType.Latent(typeVariable.asErasure(), typeVariable)
2267                             : typeVariable;
2268                 }
2269
2270                 /**
2271                  * {@inheritDoc}
2272                  */

2273                 public Generic onNonGenericType(Generic typeDescription) {
2274                     return typeDescription;
2275                 }
2276             }
2277
2278             /**
2279              * A visitor that reduces a detached generic type to its erasure.
2280              */

2281             @HashCodeAndEqualsPlugin.Enhance
2282             class Reducing implements Visitor<TypeDescription> {
2283
2284                 /**
2285                  * The generic type's declaring type.
2286                  */

2287                 private final TypeDescription declaringType;
2288
2289                 /**
2290                  * Any type variables that are directly declared by the member that declares the type being reduced.
2291                  */

2292                 private final List<? extends TypeVariableToken> typeVariableTokens;
2293
2294                 /**
2295                  * Creates a new reducing type visitor.
2296                  *
2297                  * @param declaringType     The generic type's declaring type.
2298                  * @param typeVariableToken Any type variables that are directly declared by the member that declares the type being reduced.
2299                  */

2300                 public Reducing(TypeDescription declaringType, TypeVariableToken... typeVariableToken) {
2301                     this(declaringType, Arrays.asList(typeVariableToken));
2302                 }
2303
2304                 /**
2305                  * Creates a new reducing type visitor.
2306                  *
2307                  * @param declaringType      The generic type's declaring type.
2308                  * @param typeVariableTokens Any type variables that are directly declared by the member that declares the type being reduced.
2309                  */

2310                 public Reducing(TypeDescription declaringType, List<? extends TypeVariableToken> typeVariableTokens) {
2311                     this.declaringType = declaringType;
2312                     this.typeVariableTokens = typeVariableTokens;
2313                 }
2314
2315                 /**
2316                  * {@inheritDoc}
2317                  */

2318                 public TypeDescription onGenericArray(Generic genericArray) {
2319                     Generic targetType = genericArray;
2320                     int arity = 0;
2321                     do {
2322                         targetType = targetType.getComponentType();
2323                         arity++;
2324                     } while (targetType.isArray());
2325                     return TargetType.resolve(targetType.getSort().isTypeVariable()
2326                             ? TypeDescription.ArrayProjection.of(declaringType.findVariable(targetType.getSymbol()).asErasure(), arity)
2327                             : genericArray.asErasure(), declaringType);
2328                 }
2329
2330                 /**
2331                  * {@inheritDoc}
2332                  */

2333                 public TypeDescription onWildcard(Generic wildcard) {
2334                     throw new IllegalStateException("A wildcard cannot be a top-level type: " + wildcard);
2335                 }
2336
2337                 /**
2338                  * {@inheritDoc}
2339                  */

2340                 public TypeDescription onParameterizedType(Generic parameterizedType) {
2341                     return TargetType.resolve(parameterizedType.asErasure(), declaringType);
2342                 }
2343
2344                 /**
2345                  * {@inheritDoc}
2346                  */

2347                 public TypeDescription onTypeVariable(Generic typeVariable) {
2348                     for (TypeVariableToken typeVariableToken : typeVariableTokens) {
2349                         if (typeVariable.getSymbol().equals(typeVariableToken.getSymbol())) {
2350                             return typeVariableToken.getBounds().get(0).accept(this);
2351                         }
2352                     }
2353                     return TargetType.resolve(declaringType.findVariable(typeVariable.getSymbol()).asErasure(), declaringType);
2354                 }
2355
2356                 /**
2357                  * {@inheritDoc}
2358                  */

2359                 public TypeDescription onNonGenericType(Generic typeDescription) {
2360                     return TargetType.resolve(typeDescription.asErasure(), declaringType);
2361                 }
2362             }
2363         }
2364
2365         /**
2366          * An annotation reader is responsible for lazily evaluating type annotations if this language
2367          * feature is available on the current JVM.
2368          */

2369         interface AnnotationReader {
2370
2371             /**
2372              * The dispatcher to use.
2373              */

2374             Dispatcher DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE);
2375
2376             /**
2377              * Resolves the underlying {@link AnnotatedElement}.
2378              *
2379              * @return The underlying annotated element.
2380              */

2381             AnnotatedElement resolve();
2382
2383             /**
2384              * Returns the underlying type annotations as a list.
2385              *
2386              * @return The underlying type annotations as a list.
2387              */

2388             AnnotationList asList();
2389
2390             /**
2391              * Returns a reader for type annotations of an represented element's wildcard upper bound.
2392              *
2393              * @param index The wildcard bound's index.
2394              * @return An annotation reader for the underlying annotated upper bound.
2395              */

2396             AnnotationReader ofWildcardUpperBoundType(int index);
2397
2398             /**
2399              * Returns a reader for type annotations of an represented element's wildcard lower bound.
2400              *
2401              * @param index The wildcard bound's index.
2402              * @return An annotation reader for the underlying annotated lower bound.
2403              */

2404             AnnotationReader ofWildcardLowerBoundType(int index);
2405
2406             /**
2407              * Returns a reader for type annotations of a type variable's bound.
2408              *
2409              * @param index The bound's index.
2410              * @return An annotation reader for the underlying annotated bound.
2411              */

2412             AnnotationReader ofTypeVariableBoundType(int index);
2413
2414             /**
2415              * Returns a reader for type annotations of a parameterized type's type argument.
2416              *
2417              * @param index The bound's index.
2418              * @return An annotation reader for the underlying annotated bound..
2419              */

2420             AnnotationReader ofTypeArgument(int index);
2421
2422             /**
2423              * <p>
2424              * Returns a reader for type annotations of a parameterized type's owner type.
2425              * </p>
2426              * <p>
2427              * <b>Important</b>: This feature is not currently implemented by the Java reflection API.
2428              * </p>
2429              *
2430              * @return An annotation reader for the underlying owner type.
2431              */

2432             AnnotationReader ofOwnerType();
2433
2434             /**
2435              * <p>
2436              * Returns a reader for type annotations of an inner class type's outer type.
2437              * </p>
2438              * <p>
2439              * <b>Important</b>: This feature is not currently implemented by the Java reflection API.
2440              * </p>
2441              *
2442              * @return An annotation reader for the underlying owner type.
2443              */

2444             AnnotationReader ofOuterClass();
2445
2446             /**
2447              * Returns a reader for type annotations of an array's component type.
2448              *
2449              * @return An annotation reader for the underlying component type.
2450              */

2451             AnnotationReader ofComponentType();
2452
2453             /**
2454              * A dispatcher that represents the type annotation API via reflective calls if the language feature is available on the current JVM.
2455              */

2456             interface Dispatcher {
2457
2458                 /**
2459                  * An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call.
2460                  */

2461                 Object[] NO_ARGUMENTS = new Object[0];
2462
2463                 /**
2464                  * Resolves a formal type variable's type annotations.
2465                  *
2466                  * @param typeVariable The type variable to represent.
2467                  * @return A suitable annotation reader.
2468                  */

2469                 AnnotationReader resolveTypeVariable(TypeVariable<?> typeVariable);
2470
2471                 /**
2472                  * Resolves a loaded type's super class's type annotations.
2473                  *
2474                  * @param type The type to represent.
2475                  * @return A suitable annotation reader.
2476                  */

2477                 AnnotationReader resolveSuperClassType(Class<?> type);
2478
2479                 /**
2480                  * Resolves a loaded type's interface type's type annotations.
2481                  *
2482                  * @param type  The type to represent.
2483                  * @param index The index of the interface.
2484                  * @return A suitable annotation reader.
2485                  */

2486                 AnnotationReader resolveInterfaceType(Class<?> type, int index);
2487
2488                 /**
2489                  * Resolves a loaded field's type's type annotations.
2490                  *
2491                  * @param field The field to represent.
2492                  * @return A suitable annotation reader.
2493                  */

2494                 AnnotationReader resolveFieldType(Field field);
2495
2496                 /**
2497                  * Resolves a loaded method's return type's type annotations.
2498                  *
2499                  * @param method The method to represent.
2500                  * @return A suitable annotation reader.
2501                  */

2502                 AnnotationReader resolveReturnType(Method method);
2503
2504                 /**
2505                  * Resolves a loaded executable's type argument type's type annotations.
2506                  *
2507                  * @param executable The executable to represent.
2508                  * @param index      The type argument's index.
2509                  * @return A suitable annotation reader.
2510                  */

2511                 AnnotationReader resolveParameterType(AccessibleObject executable, int index);
2512
2513                 /**
2514                  * Resolves a loaded executable's exception type's type annotations.
2515                  *
2516                  * @param executable The executable to represent.
2517                  * @param index      The type argument's index.
2518                  * @return A suitable annotation reader.
2519                  */

2520                 AnnotationReader resolveExceptionType(AccessibleObject executable, int index);
2521
2522                 /**
2523                  * Resolves a method's or constructor's receiver type. If receiver types are not available on the executing VM,
2524                  * {@code null} is returned.
2525                  *
2526                  * @param executable The executable for which the receiver type should be resolved.
2527                  * @return The executable's receiver type or {@code null}.
2528                  */

2529                 Generic resolveReceiverType(AccessibleObject executable);
2530
2531                 /**
2532                  * Resolves the annotated type as generic type description.
2533                  *
2534                  * @param annotatedType The loaded annotated type.
2535                  * @return A description of the supplied annotated type.
2536                  */

2537                 Generic resolve(AnnotatedElement annotatedType);
2538
2539                 /**
2540                  * A creation action for a dispatcher.
2541                  */

2542                 enum CreationAction implements PrivilegedAction<Dispatcher> {
2543
2544                     /**
2545                      * The singleton instance.
2546                      */

2547                     INSTANCE;
2548
2549                     /**
2550                      * {@inheritDoc}
2551                      */

2552                     public Dispatcher run() {
2553                         try {
2554                             return new ForJava8CapableVm(Class.class.getMethod("getAnnotatedSuperclass"),
2555                                     Class.class.getMethod("getAnnotatedInterfaces"),
2556                                     Field.class.getMethod("getAnnotatedType"),
2557                                     Method.class.getMethod("getAnnotatedReturnType"),
2558                                     Class.forName("java.lang.reflect.Executable").getMethod("getAnnotatedParameterTypes"),
2559                                     Class.forName("java.lang.reflect.Executable").getMethod("getAnnotatedExceptionTypes"),
2560                                     Class.forName("java.lang.reflect.Executable").getMethod("getAnnotatedReceiverType"),
2561                                     Class.forName("java.lang.reflect.AnnotatedType").getMethod("getType"));
2562                         } catch (RuntimeException exception) {
2563                             throw exception;
2564                         } catch (Exception ignored) {
2565                             return Dispatcher.ForLegacyVm.INSTANCE;
2566                         }
2567                     }
2568                 }
2569
2570                 /**
2571                  * A dispatcher for {@link AnnotationReader}s on a legacy VM that does not support type annotations.
2572                  */

2573                 enum ForLegacyVm implements Dispatcher {
2574
2575                     /**
2576                      * The singleton instance.
2577                      */

2578                     INSTANCE;
2579
2580                     /**
2581                      * {@inheritDoc}
2582                      */

2583                     public AnnotationReader resolveTypeVariable(TypeVariable<?> typeVariable) {
2584                         return NoOp.INSTANCE;
2585                     }
2586
2587                     /**
2588                      * {@inheritDoc}
2589                      */

2590                     public AnnotationReader resolveSuperClassType(Class<?> type) {
2591                         return NoOp.INSTANCE;
2592                     }
2593
2594                     /**
2595                      * {@inheritDoc}
2596                      */

2597                     public AnnotationReader resolveInterfaceType(Class<?> type, int index) {
2598                         return NoOp.INSTANCE;
2599                     }
2600
2601                     /**
2602                      * {@inheritDoc}
2603                      */

2604                     public AnnotationReader resolveFieldType(Field field) {
2605                         return NoOp.INSTANCE;
2606                     }
2607
2608                     /**
2609                      * {@inheritDoc}
2610                      */

2611                     public AnnotationReader resolveReturnType(Method method) {
2612                         return NoOp.INSTANCE;
2613                     }
2614
2615                     /**
2616                      * {@inheritDoc}
2617                      */

2618                     public AnnotationReader resolveParameterType(AccessibleObject executable, int index) {
2619                         return NoOp.INSTANCE;
2620                     }
2621
2622                     /**
2623                      * {@inheritDoc}
2624                      */

2625                     public AnnotationReader resolveExceptionType(AccessibleObject executable, int index) {
2626                         return NoOp.INSTANCE;
2627                     }
2628
2629                     /**
2630                      * {@inheritDoc}
2631                      */

2632                     public Generic resolveReceiverType(AccessibleObject executable) {
2633                         return UNDEFINED;
2634                     }
2635
2636                     /**
2637                      * {@inheritDoc}
2638                      */

2639                     public Generic resolve(AnnotatedElement annotatedType) {
2640                         throw new UnsupportedOperationException("Loaded annotated type cannot be represented on this VM");
2641                     }
2642                 }
2643
2644                 /**
2645                  * A dispatcher for a modern JVM that supports type annotations.
2646                  */

2647                 @HashCodeAndEqualsPlugin.Enhance
2648                 class ForJava8CapableVm implements Dispatcher {
2649
2650                     /**
2651                      * The {@code java.lang.Class#getAnnotatedSuperclass} method.
2652                      */

2653                     private final Method getAnnotatedSuperclass;
2654
2655                     /**
2656                      * The {@code java.lang.Class#getAnnotatedInterfaces} method.
2657                      */

2658                     private final Method getAnnotatedInterfaces;
2659
2660                     /**
2661                      * The {@code java.lang.reflect.Field#getAnnotatedType} method.
2662                      */

2663                     private final Method getAnnotatedType;
2664
2665                     /**
2666                      * The {@code java.lang.reflect.Method#getAnnotatedReturnType} method.
2667                      */

2668                     private final Method getAnnotatedReturnType;
2669
2670                     /**
2671                      * The {@code java.lang.reflect.Executable#getAnnotatedParameterTypes} method.
2672                      */

2673                     private final Method getAnnotatedParameterTypes;
2674
2675                     /**
2676                      * The {@code java.lang.reflect.Executable#getAnnotatedExceptionTypes} method.
2677                      */

2678                     private final Method getAnnotatedExceptionTypes;
2679
2680                     /**
2681                      * The {@code java.lang.reflect.Executable#getAnnotatedReceiverType} method.
2682                      */

2683                     private final Method getAnnotatedReceiverType;
2684
2685                     /**
2686                      * The {@code java.lang.reflect.AnnotatedType#getType} method.
2687                      */

2688                     private final Method getType;
2689
2690                     /**
2691                      * Creates a new dispatcher for a VM that supports type annotations.
2692                      *
2693                      * @param getAnnotatedSuperclass     The {@code java.lang.Class#getAnnotatedSuperclass} method.
2694                      * @param getAnnotatedInterfaces     The {@code java.lang.Class#getAnnotatedInterfaces} method.
2695                      * @param getAnnotatedType           The {@code java.lang.reflect.Field#getAnnotatedType} method.
2696                      * @param getAnnotatedReturnType     The {@code java.lang.reflect.Method#getAnnotatedReturnType} method.
2697                      * @param getAnnotatedParameterTypes The {@code java.lang.reflect.Executable#getAnnotatedParameterTypes} method.
2698                      * @param getAnnotatedExceptionTypes The {@code java.lang.reflect.Executable#getAnnotatedExceptionTypes} method.
2699                      * @param getAnnotatedReceiverType   The {@code java.lang.reflect.Executable#getAnnotatedReceiverType} method.
2700                      * @param getType                    The {@code java.lang.reflect.AnnotatedType#getType} method.
2701                      */

2702                     protected ForJava8CapableVm(Method getAnnotatedSuperclass,
2703                                                 Method getAnnotatedInterfaces,
2704                                                 Method getAnnotatedType,
2705                                                 Method getAnnotatedReturnType,
2706                                                 Method getAnnotatedParameterTypes,
2707                                                 Method getAnnotatedExceptionTypes,
2708                                                 Method getAnnotatedReceiverType,
2709                                                 Method getType) {
2710                         this.getAnnotatedSuperclass = getAnnotatedSuperclass;
2711                         this.getAnnotatedInterfaces = getAnnotatedInterfaces;
2712                         this.getAnnotatedType = getAnnotatedType;
2713                         this.getAnnotatedReturnType = getAnnotatedReturnType;
2714                         this.getAnnotatedParameterTypes = getAnnotatedParameterTypes;
2715                         this.getAnnotatedExceptionTypes = getAnnotatedExceptionTypes;
2716                         this.getAnnotatedReceiverType = getAnnotatedReceiverType;
2717                         this.getType = getType;
2718                     }
2719
2720                     /**
2721                      * {@inheritDoc}
2722                      */

2723                     public AnnotationReader resolveTypeVariable(TypeVariable<?> typeVariable) {
2724                         return new AnnotatedTypeVariableType(typeVariable);
2725                     }
2726
2727                     /**
2728                      * {@inheritDoc}
2729                      */

2730                     public AnnotationReader resolveSuperClassType(Class<?> type) {
2731                         return new AnnotatedSuperClass(type);
2732                     }
2733
2734                     /**
2735                      * {@inheritDoc}
2736                      */

2737                     public AnnotationReader resolveInterfaceType(Class<?> type, int index) {
2738                         return new AnnotatedInterfaceType(type, index);
2739                     }
2740
2741                     /**
2742                      * {@inheritDoc}
2743                      */

2744                     public AnnotationReader resolveFieldType(Field field) {
2745                         return new AnnotatedFieldType(field);
2746                     }
2747
2748                     /**
2749                      * {@inheritDoc}
2750                      */

2751                     public AnnotationReader resolveReturnType(Method method) {
2752                         return new AnnotatedReturnType(method);
2753                     }
2754
2755                     /**
2756                      * {@inheritDoc}
2757                      */

2758                     public AnnotationReader resolveParameterType(AccessibleObject executable, int index) {
2759                         return new AnnotatedParameterizedType(executable, index);
2760                     }
2761
2762                     /**
2763                      * {@inheritDoc}
2764                      */

2765                     public AnnotationReader resolveExceptionType(AccessibleObject executable, int index) {
2766                         return new AnnotatedExceptionType(executable, index);
2767                     }
2768
2769                     /**
2770                      * {@inheritDoc}
2771                      */

2772                     public Generic resolveReceiverType(AccessibleObject executable) {
2773                         try {
2774                             return resolve((AnnotatedElement) getAnnotatedReceiverType.invoke(executable, NO_ARGUMENTS));
2775                         } catch (IllegalAccessException exception) {
2776                             throw new IllegalStateException("Cannot access java.lang.reflect.Executable#getAnnotatedReceiverType", exception);
2777                         } catch (InvocationTargetException exception) {
2778                             throw new IllegalStateException("Error invoking java.lang.reflect.Executable#getAnnotatedReceiverType", exception.getCause());
2779                         }
2780                     }
2781
2782                     /**
2783                      * {@inheritDoc}
2784                      */

2785                     public Generic resolve(AnnotatedElement annotatedType) {
2786                         try {
2787                             return annotatedType == null
2788                                     ? UNDEFINED
2789                                     : Sort.describe((java.lang.reflect.Type) getType.invoke(annotatedType, NO_ARGUMENTS), new Resolved(annotatedType));
2790                         } catch (IllegalAccessException exception) {
2791                             throw new IllegalStateException("Cannot access java.lang.reflect.AnnotatedType#getType", exception);
2792                         } catch (InvocationTargetException exception) {
2793                             throw new IllegalStateException("Error invoking java.lang.reflect.AnnotatedType#getType", exception.getCause());
2794                         }
2795                     }
2796
2797                     /**
2798                      * A delegator for an existing {@code java.lang.reflect.AnnotatedElement}.
2799                      */

2800                     @HashCodeAndEqualsPlugin.Enhance
2801                     protected static class Resolved extends Delegator {
2802
2803                         /**
2804                          * The represented annotated element.
2805                          */

2806                         private final AnnotatedElement annotatedElement;
2807
2808                         /**
2809                          * Creates a new resolved delegator.
2810                          *
2811                          * @param annotatedElement The represented annotated element.
2812                          */

2813                         protected Resolved(AnnotatedElement annotatedElement) {
2814                             this.annotatedElement = annotatedElement;
2815                         }
2816
2817                         /**
2818                          * {@inheritDoc}
2819                          */

2820                         public AnnotatedElement resolve() {
2821                             return annotatedElement;
2822                         }
2823                     }
2824
2825                     /**
2826                      * A delegating annotation reader for an annotated type variable.
2827                      */

2828                     @HashCodeAndEqualsPlugin.Enhance
2829                     protected static class AnnotatedTypeVariableType extends Delegator {
2830
2831                         /**
2832                          * The represented type variable.
2833                          */

2834                         private final TypeVariable<?> typeVariable;
2835
2836                         /**
2837                          * Creates a new annotation reader for the given type variable.
2838                          *
2839                          * @param typeVariable The represented type variable.
2840                          */

2841                         protected AnnotatedTypeVariableType(TypeVariable<?> typeVariable) {
2842                             this.typeVariable = typeVariable;
2843                         }
2844
2845                         /**
2846                          * {@inheritDoc}
2847                          */

2848                         public AnnotatedElement resolve() {
2849                             return (AnnotatedElement) typeVariable;
2850                         }
2851
2852                         /**
2853                          * {@inheritDoc}
2854                          */

2855                         public AnnotationReader ofTypeVariableBoundType(int index) {
2856                             return new ForTypeVariableBoundType.OfFormalTypeVariable(typeVariable, index);
2857                         }
2858                     }
2859
2860                     /**
2861                      * A delegating annotation reader for an annotated super type.
2862                      */

2863                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2864                     protected class AnnotatedSuperClass extends Delegator {
2865
2866                         /**
2867                          * The represented type.
2868                          */

2869                         private final Class<?> type;
2870
2871                         /**
2872                          * Creates a new annotation reader for an annotated super type.
2873                          *
2874                          * @param type The represented type.
2875                          */

2876                         protected AnnotatedSuperClass(Class<?> type) {
2877                             this.type = type;
2878                         }
2879
2880                         /**
2881                          * {@inheritDoc}
2882                          */

2883                         public AnnotatedElement resolve() {
2884                             try {
2885                                 return (AnnotatedElement) getAnnotatedSuperclass.invoke(type, NO_ARGUMENTS);
2886                             } catch (IllegalAccessException exception) {
2887                                 throw new IllegalStateException("Cannot access java.lang.Class#getAnnotatedSuperclass", exception);
2888                             } catch (InvocationTargetException exception) {
2889                                 throw new IllegalStateException("Error invoking java.lang.Class#getAnnotatedSuperclass", exception.getCause());
2890                             }
2891                         }
2892                     }
2893
2894                     /**
2895                      * A delegating annotation reader for an annotated interface type.
2896                      */

2897                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2898                     protected class AnnotatedInterfaceType extends Delegator {
2899
2900                         /**
2901                          * The represented interface type.
2902                          */

2903                         private final Class<?> type;
2904
2905                         /**
2906                          * The interface type's index.
2907                          */

2908                         private final int index;
2909
2910                         /**
2911                          * Creates a new annotation reader for an annotated interface type.
2912                          *
2913                          * @param type  The represented interface type.
2914                          * @param index The interface type's index.
2915                          */

2916                         protected AnnotatedInterfaceType(Class<?> type, int index) {
2917                             this.type = type;
2918                             this.index = index;
2919                         }
2920
2921                         /**
2922                          * {@inheritDoc}
2923                          */

2924                         public AnnotatedElement resolve() {
2925                             try {
2926                                 return (AnnotatedElement) Array.get(getAnnotatedInterfaces.invoke(type), index);
2927                             } catch (IllegalAccessException exception) {
2928                                 throw new IllegalStateException("Cannot access java.lang.Class#getAnnotatedInterfaces", exception);
2929                             } catch (InvocationTargetException exception) {
2930                                 throw new IllegalStateException("Error invoking java.lang.Class#getAnnotatedInterfaces", exception.getCause());
2931                             }
2932                         }
2933                     }
2934
2935                     /**
2936                      * A delegating annotation reader for an annotated field variable.
2937                      */

2938                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2939                     protected class AnnotatedFieldType extends Delegator {
2940
2941                         /**
2942                          * The represented field.
2943                          */

2944                         private final Field field;
2945
2946                         /**
2947                          * Creates a new annotation reader for an annotated field type.
2948                          *
2949                          * @param field The represented field.
2950                          */

2951                         protected AnnotatedFieldType(Field field) {
2952                             this.field = field;
2953                         }
2954
2955                         /**
2956                          * {@inheritDoc}
2957                          */

2958                         public AnnotatedElement resolve() {
2959                             try {
2960                                 return (AnnotatedElement) getAnnotatedType.invoke(field, NO_ARGUMENTS);
2961                             } catch (IllegalAccessException exception) {
2962                                 throw new IllegalStateException("Cannot access java.lang.reflect.Field#getAnnotatedType", exception);
2963                             } catch (InvocationTargetException exception) {
2964                                 throw new IllegalStateException("Error invoking java.lang.reflect.Field#getAnnotatedType", exception.getCause());
2965                             }
2966                         }
2967                     }
2968
2969                     /**
2970                      * A delegating annotation reader for an annotated return variable.
2971                      */

2972                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2973                     protected class AnnotatedReturnType extends Delegator {
2974
2975                         /**
2976                          * The represented method.
2977                          */

2978                         private final Method method;
2979
2980                         /**
2981                          * Creates a new annotation reader for an annotated return type.
2982                          *
2983                          * @param method The represented method.
2984                          */

2985                         protected AnnotatedReturnType(Method method) {
2986                             this.method = method;
2987                         }
2988
2989                         /**
2990                          * {@inheritDoc}
2991                          */

2992                         public AnnotatedElement resolve() {
2993                             try {
2994                                 return (AnnotatedElement) getAnnotatedReturnType.invoke(method, NO_ARGUMENTS);
2995                             } catch (IllegalAccessException exception) {
2996                                 throw new IllegalStateException("Cannot access java.lang.reflect.Method#getAnnotatedReturnType", exception);
2997                             } catch (InvocationTargetException exception) {
2998                                 throw new IllegalStateException("Error invoking java.lang.reflect.Method#getAnnotatedReturnType", exception.getCause());
2999                             }
3000                         }
3001                     }
3002
3003                     /**
3004                      * A delegating annotation reader for an annotated parameter variable.
3005                      */

3006                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
3007                     protected class AnnotatedParameterizedType extends Delegator {
3008
3009                         /**
3010                          * The represented executable.
3011                          */

3012                         private final AccessibleObject executable;
3013
3014                         /**
3015                          * The type argument's index.
3016                          */

3017                         private final int index;
3018
3019                         /**
3020                          * Creates a new annotation reader for an annotated type argument type.
3021                          *
3022                          * @param executable The represented executable.
3023                          * @param index      The type argument's index.
3024                          */

3025                         protected AnnotatedParameterizedType(AccessibleObject executable, int index) {
3026                             this.executable = executable;
3027                             this.index = index;
3028                         }
3029
3030                         /**
3031                          * {@inheritDoc}
3032                          */

3033                         public AnnotatedElement resolve() {
3034                             try {
3035                                 return (AnnotatedElement) Array.get(getAnnotatedParameterTypes.invoke(executable, NO_ARGUMENTS), index);
3036                             } catch (IllegalAccessException exception) {
3037                                 throw new IllegalStateException("Cannot access java.lang.reflect.Executable#getAnnotatedParameterTypes", exception);
3038                             } catch (InvocationTargetException exception) {
3039                                 throw new IllegalStateException("Error invoking java.lang.reflect.Executable#getAnnotatedParameterTypes", exception.getCause());
3040                             }
3041                         }
3042                     }
3043
3044                     /**
3045                      * A delegating annotation reader for an annotated exception variable.
3046                      */

3047                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
3048                     protected class AnnotatedExceptionType extends Delegator {
3049
3050                         /**
3051                          * The represented executable.
3052                          */

3053                         private final AccessibleObject executable;
3054
3055                         /**
3056                          * The exception type's index.
3057                          */

3058                         private final int index;
3059
3060                         /**
3061                          * Creates a new annotation reader for an annotated exception type.
3062                          *
3063                          * @param executable The represented executable.
3064                          * @param index      The exception type's index.
3065                          */

3066                         protected AnnotatedExceptionType(AccessibleObject executable, int index) {
3067                             this.executable = executable;
3068                             this.index = index;
3069                         }
3070
3071                         /**
3072                          * {@inheritDoc}
3073                          */

3074                         public AnnotatedElement resolve() {
3075                             try {
3076                                 return (AnnotatedElement) Array.get(getAnnotatedExceptionTypes.invoke(executable, NO_ARGUMENTS), index);
3077                             } catch (IllegalAccessException exception) {
3078                                 throw new IllegalStateException("Cannot access java.lang.reflect.Executable#getAnnotatedExceptionTypes", exception);
3079                             } catch (InvocationTargetException exception) {
3080                                 throw new IllegalStateException("Error invoking java.lang.reflect.Executable#getAnnotatedExceptionTypes", exception.getCause());
3081                             }
3082                         }
3083                     }
3084                 }
3085             }
3086
3087             /**
3088              * A non-operational annotation reader.
3089              */

3090             enum NoOp implements AnnotationReader, AnnotatedElement {
3091
3092                 /**
3093                  * The singleton instance.
3094                  */

3095                 INSTANCE;
3096
3097                 /**
3098                  * {@inheritDoc}
3099                  */

3100                 public AnnotatedElement resolve() {
3101                     return this;
3102                 }
3103
3104                 /**
3105                  * {@inheritDoc}
3106                  */

3107                 public AnnotationList asList() {
3108                     return new AnnotationList.Empty();
3109                 }
3110
3111                 /**
3112                  * {@inheritDoc}
3113                  */

3114                 public AnnotationReader ofWildcardUpperBoundType(int index) {
3115                     return this;
3116                 }
3117
3118                 /**
3119                  * {@inheritDoc}
3120                  */

3121                 public AnnotationReader ofWildcardLowerBoundType(int index) {
3122                     return this;
3123                 }
3124
3125                 /**
3126                  * {@inheritDoc}
3127                  */

3128                 public AnnotationReader ofTypeVariableBoundType(int index) {
3129                     return this;
3130                 }
3131
3132                 /**
3133                  * {@inheritDoc}
3134                  */

3135                 public AnnotationReader ofTypeArgument(int index) {
3136                     return this;
3137                 }
3138
3139                 /**
3140                  * {@inheritDoc}
3141                  */

3142                 public AnnotationReader ofOwnerType() {
3143                     return this;
3144                 }
3145
3146                 /**
3147                  * {@inheritDoc}
3148                  */

3149                 public AnnotationReader ofOuterClass() {
3150                     return this;
3151                 }
3152
3153                 /**
3154                  * {@inheritDoc}
3155                  */

3156                 public AnnotationReader ofComponentType() {
3157                     return this;
3158                 }
3159
3160                 /**
3161                  * {@inheritDoc}
3162                  */

3163                 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
3164                     throw new IllegalStateException("Cannot resolve annotations for no-op reader: " + this);
3165                 }
3166
3167                 /**
3168                  * {@inheritDoc}
3169                  */

3170                 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
3171                     throw new IllegalStateException("Cannot resolve annotations for no-op reader: " + this);
3172                 }
3173
3174                 /**
3175                  * {@inheritDoc}
3176                  */

3177                 public Annotation[] getAnnotations() {
3178                     throw new IllegalStateException("Cannot resolve annotations for no-op reader: " + this);
3179                 }
3180
3181                 /**
3182                  * {@inheritDoc}
3183                  */

3184                 public Annotation[] getDeclaredAnnotations() {
3185                     return new Annotation[0];
3186                 }
3187             }
3188
3189             /**
3190              * A delegating annotation reader that delegates all invocations to an annotation reader that wraps the previous one.
3191              */

3192             abstract class Delegator implements AnnotationReader {
3193
3194                 /**
3195                  * An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call.
3196                  */

3197                 protected static final Object[] NO_ARGUMENTS = new Object[0];
3198
3199                 /**
3200                  * {@inheritDoc}
3201                  */

3202                 public AnnotationReader ofWildcardUpperBoundType(int index) {
3203                     return new ForWildcardUpperBoundType(this, index);
3204                 }
3205
3206                 /**
3207                  * {@inheritDoc}
3208                  */

3209                 public AnnotationReader ofWildcardLowerBoundType(int index) {
3210                     return new ForWildcardLowerBoundType(this, index);
3211                 }
3212
3213                 /**
3214                  * {@inheritDoc}
3215                  */

3216                 public AnnotationReader ofTypeVariableBoundType(int index) {
3217                     return new ForTypeVariableBoundType(this, index);
3218                 }
3219
3220                 /**
3221                  * {@inheritDoc}
3222                  */

3223                 public AnnotationReader ofTypeArgument(int index) {
3224                     return new ForTypeArgument(this, index);
3225                 }
3226
3227                 /**
3228                  * {@inheritDoc}
3229                  */

3230                 public AnnotationReader ofOwnerType() {
3231                     return ForOwnerType.of(this);
3232                 }
3233
3234                 /**
3235                  * {@inheritDoc}
3236                  */

3237                 public AnnotationReader ofOuterClass() {
3238                     return ForOwnerType.of(this);
3239                 }
3240
3241                 /**
3242                  * {@inheritDoc}
3243                  */

3244                 public AnnotationReader ofComponentType() {
3245                     return new ForComponentType(this);
3246                 }
3247
3248                 /**
3249                  * {@inheritDoc}
3250                  */

3251                 public AnnotationList asList() {
3252                     return new AnnotationList.ForLoadedAnnotations(resolve().getDeclaredAnnotations());
3253                 }
3254
3255                 /**
3256                  * A chained delegator that bases its result on an underlying annotation reader.
3257                  */

3258                 @HashCodeAndEqualsPlugin.Enhance
3259                 protected abstract static class Chained extends Delegator {
3260
3261                     /**
3262                      * Indicates that a method is not available on the current VM.
3263                      */

3264                     protected static final Method NOT_AVAILABLE = null;
3265
3266                     /**
3267                      * The underlying annotation reader.
3268                      */

3269                     protected final AnnotationReader annotationReader;
3270
3271                     /**
3272                      * Creates a new chained annotation reader.
3273                      *
3274                      * @param annotationReader The underlying annotation reader.
3275                      */

3276                     protected Chained(AnnotationReader annotationReader) {
3277                         this.annotationReader = annotationReader;
3278                     }
3279
3280                     /**
3281                      * Resolves the method to invoke or returns {@code nullif the method does not exist on the current VM.
3282                      *
3283                      * @param typeName   The declaring type's name.
3284                      * @param methodName The method's name.
3285                      * @return The resolved method or {@code null}.
3286                      */

3287                     @SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Exception should not be rethrown but trigger a fallback")
3288                     protected static Method of(String typeName, String methodName) {
3289                         try {
3290                             return Class.forName(typeName).getMethod(methodName);
3291                         } catch (Exception exception) {
3292                             return NOT_AVAILABLE;
3293                         }
3294                     }
3295
3296                     /**
3297                      * {@inheritDoc}
3298                      */

3299                     public AnnotatedElement resolve() {
3300                         return resolve(annotationReader.resolve());
3301                     }
3302
3303                     /**
3304                      * Resolves the type annotations from a given annotated element into the annotated element that this instance represents.
3305                      *
3306                      * @param annotatedElement The original annotated element.
3307                      * @return The resolved annotated element.
3308                      */

3309                     protected abstract AnnotatedElement resolve(AnnotatedElement annotatedElement);
3310                 }
3311
3312                 /**
3313                  * An annotation reader for a {@code java.lang.reflect.RecordComponent}.
3314                  */

3315                 protected static class ForRecordComponent extends Delegator {
3316
3317                     /**
3318                      * The represented {@code java.lang.reflect.RecordComponent}.
3319                      */

3320                     private final Object recordComponent;
3321
3322                     /**
3323                      * Creates a new annotation reader for a {@code java.lang.reflect.RecordComponent}.
3324                      *
3325                      * @param recordComponent The represented {@code java.lang.reflect.RecordComponent}.
3326                      */

3327                     protected ForRecordComponent(Object recordComponent) {
3328                         this.recordComponent = recordComponent;
3329                     }
3330
3331                     /**
3332                      * {@inheritDoc}
3333                      */

3334                     public AnnotatedElement resolve() {
3335                         return RecordComponentDescription.ForLoadedRecordComponent.DISPATCHER.getAnnotatedType(recordComponent);
3336                     }
3337                 }
3338             }
3339
3340             /**
3341              * A chained annotation reader for reading a wildcard type's upper bound type.
3342              */

3343             @HashCodeAndEqualsPlugin.Enhance
3344             class ForWildcardUpperBoundType extends Delegator.Chained {
3345
3346                 /**
3347                  * The {@code java.lang.reflect.AnnotatedWildcardType#getAnnotatedUpperBounds} method.
3348                  */

3349                 private static final Method GET_ANNOTATED_UPPER_BOUNDS = of("java.lang.reflect.AnnotatedWildcardType""getAnnotatedUpperBounds");
3350
3351                 /**
3352                  * The wildcard bound's index.
3353                  */

3354                 private final int index;
3355
3356                 /**
3357                  * Creates a chained annotation reader for reading a upper-bound wildcard's bound type.
3358                  *
3359                  * @param annotationReader The annotation reader from which to delegate.
3360                  * @param index            The wildcard bound's index.
3361                  */

3362                 protected ForWildcardUpperBoundType(AnnotationReader annotationReader, int index) {
3363                     super(annotationReader);
3364                     this.index = index;
3365                 }
3366
3367                 @Override
3368                 protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
3369                     if (!GET_ANNOTATED_UPPER_BOUNDS.getDeclaringClass().isInstance(annotatedElement)) { // Avoid problem with Kotlin compiler.
3370                         return NoOp.INSTANCE;
3371                     }
3372                     try {
3373                         Object annotatedUpperBounds = GET_ANNOTATED_UPPER_BOUNDS.invoke(annotatedElement, NO_ARGUMENTS);
3374                         return Array.getLength(annotatedUpperBounds) == 0 // Wildcards with a lower bound do not define annotations for their implicit upper bound.
3375                                 ? NoOp.INSTANCE
3376                                 : (AnnotatedElement) Array.get(annotatedUpperBounds, index);
3377                     } catch (ClassCastException ignored) { // To avoid bug on early releases of Java 8.
3378                         return NoOp.INSTANCE;
3379                     } catch (IllegalAccessException exception) {
3380                         throw new IllegalStateException("Cannot access java.lang.reflect.AnnotatedWildcardType#getAnnotatedUpperBounds", exception);
3381                     } catch (InvocationTargetException exception) {
3382                         throw new IllegalStateException("Error invoking java.lang.reflect.AnnotatedWildcardType#getAnnotatedUpperBounds", exception.getCause());
3383                     }
3384                 }
3385             }
3386
3387             /**
3388              * A chained annotation reader for reading a wildcard type's lower bound type.
3389              */

3390             @HashCodeAndEqualsPlugin.Enhance
3391             class ForWildcardLowerBoundType extends Delegator.Chained {
3392
3393                 /**
3394                  * The {@code java.lang.reflect.AnnotatedWildcardType#getAnnotatedLowerBounds} method.
3395                  */

3396                 private static final Method GET_ANNOTATED_LOWER_BOUNDS = of("java.lang.reflect.AnnotatedWildcardType""getAnnotatedLowerBounds");
3397
3398                 /**
3399                  * The wildcard bound's index.
3400                  */

3401                 private final int index;
3402
3403                 /**
3404                  * Creates a chained annotation reader for reading a lower-bound wildcard's bound type.
3405                  *
3406                  * @param annotationReader The annotation reader from which to delegate.
3407                  * @param index            The wildcard bound's index.
3408                  */

3409                 protected ForWildcardLowerBoundType(AnnotationReader annotationReader, int index) {
3410                     super(annotationReader);
3411                     this.index = index;
3412                 }
3413
3414                 @Override
3415                 protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
3416                     if (!GET_ANNOTATED_LOWER_BOUNDS.getDeclaringClass().isInstance(annotatedElement)) { // Avoid problem with Kotlin compiler.
3417                         return NoOp.INSTANCE;
3418                     }
3419                     try {
3420                         return (AnnotatedElement) Array.get(GET_ANNOTATED_LOWER_BOUNDS.invoke(annotatedElement, NO_ARGUMENTS), index);
3421                     } catch (ClassCastException ignored) { // To avoid bug on early releases of Java 8.
3422                         return NoOp.INSTANCE;
3423                     } catch (IllegalAccessException exception) {
3424                         throw new IllegalStateException("Cannot access java.lang.reflect.AnnotatedWildcardType#getAnnotatedLowerBounds", exception);
3425                     } catch (InvocationTargetException exception) {
3426                         throw new IllegalStateException("Error invoking java.lang.reflect.AnnotatedWildcardType#getAnnotatedLowerBounds", exception.getCause());
3427                     }
3428                 }
3429             }
3430
3431             /**
3432              * A chained annotation reader for reading a type variable's type argument.
3433              */

3434             @HashCodeAndEqualsPlugin.Enhance
3435             class ForTypeVariableBoundType extends Delegator.Chained {
3436
3437                 /**
3438                  * The {@code java.lang.reflect.AnnotatedTypeVariable#getAnnotatedBounds} method.
3439                  */

3440                 private static final Method GET_ANNOTATED_BOUNDS = of("java.lang.reflect.AnnotatedTypeVariable""getAnnotatedBounds");
3441
3442                 /**
3443                  * The type variable's index.
3444                  */

3445                 private final int index;
3446
3447                 /**
3448                  * Creates a chained annotation reader for reading a type variable's bound type.
3449                  *
3450                  * @param annotationReader The annotation reader from which to delegate.
3451                  * @param index            The type variable's index.
3452                  */

3453                 protected ForTypeVariableBoundType(AnnotationReader annotationReader, int index) {
3454                     super(annotationReader);
3455                     this.index = index;
3456                 }
3457
3458                 @Override
3459                 protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
3460                     if (!GET_ANNOTATED_BOUNDS.getDeclaringClass().isInstance(annotatedElement)) { // Avoid problem with Kotlin compiler.
3461                         return NoOp.INSTANCE;
3462                     }
3463                     try {
3464                         return (AnnotatedElement) Array.get(GET_ANNOTATED_BOUNDS.invoke(annotatedElement, NO_ARGUMENTS), index);
3465                     } catch (ClassCastException ignored) { // To avoid bug on early releases of Java 8.
3466                         return NoOp.INSTANCE;
3467                     } catch (IllegalAccessException exception) {
3468                         throw new IllegalStateException("Cannot access java.lang.reflect.AnnotatedTypeVariable#getAnnotatedBounds", exception);
3469                     } catch (InvocationTargetException exception) {
3470                         throw new IllegalStateException("Error invoking java.lang.reflect.AnnotatedTypeVariable#getAnnotatedBounds", exception.getCause());
3471                     }
3472                 }
3473
3474                 /**
3475                  * A chained annotation reader for reading a formal type variable's type argument.
3476                  */

3477                 @HashCodeAndEqualsPlugin.Enhance
3478                 protected static class OfFormalTypeVariable extends Delegator {
3479
3480                     /**
3481                      * The {@code java.lang.reflect.TypeVariable#getAnnotatedBounds} method.
3482                      */

3483                     private static final Method GET_ANNOTATED_BOUNDS = of(TypeVariable.class.getName(), "getAnnotatedBounds");
3484
3485                     /**
3486                      * The represented type variable.
3487                      */

3488                     private final TypeVariable<?> typeVariable;
3489
3490                     /**
3491                      * The type variable's index.
3492                      */

3493                     private final int index;
3494
3495                     /**
3496                      * Creates a chained annotation reader for reading a formal type variable's bound type.
3497                      *
3498                      * @param typeVariable The represented type variable.
3499                      * @param index        The type variable's index.
3500                      */

3501                     protected OfFormalTypeVariable(TypeVariable<?> typeVariable, int index) {
3502                         this.typeVariable = typeVariable;
3503                         this.index = index;
3504                     }
3505
3506                     /**
3507                      * {@inheritDoc}
3508                      */

3509                     public AnnotatedElement resolve() {
3510                         try {
3511                             return (AnnotatedElement) Array.get(GET_ANNOTATED_BOUNDS.invoke(typeVariable, NO_ARGUMENTS), index);
3512                         } catch (ClassCastException ignored) { // To avoid bug on early releases of Java 8.
3513                             return NoOp.INSTANCE;
3514                         } catch (IllegalAccessException exception) {
3515                             throw new IllegalStateException("Cannot access java.lang.reflect.TypeVariable#getAnnotatedBounds", exception);
3516                         } catch (InvocationTargetException exception) {
3517                             throw new IllegalStateException("Error invoking java.lang.reflect.TypeVariable#getAnnotatedBounds", exception.getCause());
3518                         }
3519                     }
3520                 }
3521             }
3522
3523             /**
3524              * A chained annotation reader for reading a parameterized type's type argument.
3525              */

3526             @HashCodeAndEqualsPlugin.Enhance
3527             class ForTypeArgument extends Delegator.Chained {
3528
3529                 /**
3530                  * The {@code java.lang.reflect.AnnotatedParameterizedType#getAnnotatedActualTypeArguments} method.
3531                  */

3532                 private static final Method GET_ANNOTATED_ACTUAL_TYPE_ARGUMENTS = of("java.lang.reflect.AnnotatedParameterizedType""getAnnotatedActualTypeArguments");
3533
3534                 /**
3535                  * The type argument's index.
3536                  */

3537                 private final int index;
3538
3539                 /**
3540                  * Creates a chained annotation reader for reading a component type.
3541                  *
3542                  * @param annotationReader The annotation reader from which to delegate.
3543                  * @param index            The type argument's index.
3544                  */

3545                 protected ForTypeArgument(AnnotationReader annotationReader, int index) {
3546                     super(annotationReader);
3547                     this.index = index;
3548                 }
3549
3550                 @Override
3551                 protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
3552                     if (!GET_ANNOTATED_ACTUAL_TYPE_ARGUMENTS.getDeclaringClass().isInstance(annotatedElement)) { // Avoid problem with Kotlin compiler.
3553                         return NoOp.INSTANCE;
3554                     }
3555                     try {
3556                         return (AnnotatedElement) Array.get(GET_ANNOTATED_ACTUAL_TYPE_ARGUMENTS.invoke(annotatedElement, NO_ARGUMENTS), index);
3557                     } catch (ClassCastException ignored) { // To avoid bug on early releases of Java 8.
3558                         return NoOp.INSTANCE;
3559                     } catch (IllegalAccessException exception) {
3560                         throw new IllegalStateException("Cannot access java.lang.reflect.AnnotatedParameterizedType#getAnnotatedActualTypeArguments", exception);
3561                     } catch (InvocationTargetException exception) {
3562                         throw new IllegalStateException("Error invoking java.lang.reflect.AnnotatedParameterizedType#getAnnotatedActualTypeArguments", exception.getCause());
3563                     }
3564                 }
3565             }
3566
3567             /**
3568              * A chained annotation reader for reading a component type.
3569              */

3570             class ForComponentType extends Delegator.Chained {
3571
3572                 /**
3573                  * The {@code java.lang.reflect.AnnotatedArrayType#getAnnotatedGenericComponentType} method.
3574                  */

3575                 private static final Method GET_ANNOTATED_GENERIC_COMPONENT_TYPE = of("java.lang.reflect.AnnotatedArrayType""getAnnotatedGenericComponentType");
3576
3577                 /**
3578                  * Creates a chained annotation reader for reading a component type.
3579                  *
3580                  * @param annotationReader The annotation reader from which to delegate.
3581                  */

3582                 protected ForComponentType(AnnotationReader annotationReader) {
3583                     super(annotationReader);
3584                 }
3585
3586                 @Override
3587                 protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
3588                     if (!GET_ANNOTATED_GENERIC_COMPONENT_TYPE.getDeclaringClass().isInstance(annotatedElement)) { // Avoid problem with Kotlin compiler.
3589                         return NoOp.INSTANCE;
3590                     }
3591                     try {
3592                         return (AnnotatedElement) GET_ANNOTATED_GENERIC_COMPONENT_TYPE.invoke(annotatedElement, NO_ARGUMENTS);
3593                     } catch (ClassCastException ignored) { // To avoid bug on early releases of Java 8.
3594                         return NoOp.INSTANCE;
3595                     } catch (IllegalAccessException exception) {
3596                         throw new IllegalStateException("Cannot access java.lang.reflect.AnnotatedArrayType#getAnnotatedGenericComponentType", exception);
3597                     } catch (InvocationTargetException exception) {
3598                         throw new IllegalStateException("Error invoking java.lang.reflect.AnnotatedArrayType#getAnnotatedGenericComponentType", exception.getCause());
3599                     }
3600                 }
3601             }
3602
3603             /**
3604              * A chained annotation reader for reading an owner type.
3605              */

3606             class ForOwnerType extends Delegator.Chained {
3607
3608                 /**
3609                  * The {@code java.lang.reflect.AnnotatedType#getAnnotatedOwnerType} method.
3610                  */

3611                 private static final Method GET_ANNOTATED_OWNER_TYPE = of("java.lang.reflect.AnnotatedType""getAnnotatedOwnerType");
3612
3613                 /**
3614                  * Creates a chained annotation reader for reading an owner type if it is accessible. This method checks if annotated
3615                  * owner types are available on the executing VM (Java 9+). If this is not the case, a non-operational annotation
3616                  * reader is returned.
3617                  *
3618                  * @param annotationReader The annotation reader from which to delegate.
3619                  * @return An annotation reader for the resolved type's owner type.
3620                  */

3621                 private static AnnotationReader of(AnnotationReader annotationReader) {
3622                     return GET_ANNOTATED_OWNER_TYPE == null
3623                             ? NoOp.INSTANCE
3624                             : new ForOwnerType(annotationReader);
3625                 }
3626
3627                 /**
3628                  * Creates a chained annotation reader for reading an owner type if it is accessible.
3629                  *
3630                  * @param annotationReader The annotation reader from which to delegate.
3631                  */

3632                 protected ForOwnerType(AnnotationReader annotationReader) {
3633                     super(annotationReader);
3634                 }
3635
3636                 @Override
3637                 protected AnnotatedElement resolve(AnnotatedElement annotatedElement) {
3638                     if (!GET_ANNOTATED_OWNER_TYPE.getDeclaringClass().isInstance(annotatedElement)) { // Avoid problem with Kotlin compiler.
3639                         return NoOp.INSTANCE;
3640                     }
3641                     try {
3642                         AnnotatedElement annotatedOwnerType = (AnnotatedElement) GET_ANNOTATED_OWNER_TYPE.invoke(annotatedElement, NO_ARGUMENTS);
3643                         return annotatedOwnerType == null
3644                                 ? NoOp.INSTANCE
3645                                 : annotatedOwnerType;
3646                     } catch (ClassCastException ignored) { // To avoid bug on early releases of Java 8.
3647                         return NoOp.INSTANCE;
3648                     } catch (IllegalAccessException exception) {
3649                         throw new IllegalStateException("Cannot access java.lang.reflect.AnnotatedType#getAnnotatedOwnerType", exception);
3650                     } catch (InvocationTargetException exception) {
3651                         throw new IllegalStateException("Error invoking java.lang.reflect.AnnotatedType#getAnnotatedOwnerType", exception.getCause());
3652                     }
3653                 }
3654             }
3655         }
3656
3657         /**
3658          * An abstract base implementation of a generic type description.
3659          */

3660         abstract class AbstractBase extends ModifierReviewable.AbstractBase implements Generic {
3661
3662             /**
3663              * {@inheritDoc}
3664              */

3665             public int getModifiers() {
3666                 return asErasure().getModifiers();
3667             }
3668
3669             /**
3670              * {@inheritDoc}
3671              */

3672             public Generic asGenericType() {
3673                 return this;
3674             }
3675
3676             /**
3677              * {@inheritDoc}
3678              */

3679             public Generic asRawType() {
3680                 return asErasure().asGenericType();
3681             }
3682
3683             /**
3684              * {@inheritDoc}
3685              */

3686             public boolean represents(java.lang.reflect.Type type) {
3687                 return equals(Sort.describe(type));
3688             }
3689         }
3690
3691         /**
3692          * <p>
3693          * A raw type representation of a non-generic type. This raw type differs from a raw type in the Java programming language by
3694          * representing a minimal erasure compared to Java's full erasure. This means that generic types are preserved as long as they
3695          * do not involve a type variable. Nested type variables are erased on the deepest possible level.
3696          * </p>
3697          * <p>
3698          * All fields, methods, interfaces and the super type that are returned from this instance represent appropriately erased types.
3699          * </p>
3700          */

3701         abstract class OfNonGenericType extends AbstractBase {
3702
3703             /**
3704              * {@inheritDoc}
3705              */

3706             public Sort getSort() {
3707                 return Sort.NON_GENERIC;
3708             }
3709
3710             /**
3711              * {@inheritDoc}
3712              */

3713             public Generic getSuperClass() {
3714                 TypeDescription erasure = asErasure();
3715                 Generic superClass = erasure.getSuperClass();
3716                 if (TypeDescription.AbstractBase.RAW_TYPES) {
3717                     return superClass;
3718                 }
3719                 return superClass == null
3720                         ? Generic.UNDEFINED
3721                         : new Generic.LazyProjection.WithResolvedErasure(superClass, new Visitor.ForRawType(erasure), Empty.INSTANCE);
3722             }
3723
3724             /**
3725              * {@inheritDoc}
3726              */

3727             public TypeList.Generic getInterfaces() {
3728                 TypeDescription erasure = asErasure();
3729                 if (TypeDescription.AbstractBase.RAW_TYPES) {
3730                     return erasure.getInterfaces();
3731                 }
3732                 return new TypeList.Generic.ForDetachedTypes.WithResolvedErasure(erasure.getInterfaces(), new Visitor.ForRawType(erasure));
3733             }
3734
3735             /**
3736              * {@inheritDoc}
3737              */

3738             public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
3739                 TypeDescription erasure = asErasure();
3740                 return new FieldList.TypeSubstituting(this, erasure.getDeclaredFields(), TypeDescription.AbstractBase.RAW_TYPES
3741                         ? Visitor.NoOp.INSTANCE
3742                         : new Visitor.ForRawType(erasure));
3743             }
3744
3745             /**
3746              * {@inheritDoc}
3747              */

3748             public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
3749                 TypeDescription erasure = asErasure();
3750                 return new MethodList.TypeSubstituting(this, erasure.getDeclaredMethods(), TypeDescription.AbstractBase.RAW_TYPES
3751                         ? Visitor.NoOp.INSTANCE
3752                         : new Visitor.ForRawType(erasure));
3753             }
3754
3755             /**
3756              * {@inheritDoc}
3757              */

3758             public RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents() {
3759                 TypeDescription erasure = asErasure();
3760                 return new RecordComponentList.TypeSubstituting(this, erasure.getRecordComponents(), TypeDescription.AbstractBase.RAW_TYPES
3761                         ? Visitor.NoOp.INSTANCE
3762                         : new Visitor.ForRawType(erasure));
3763             }
3764
3765             /**
3766              * {@inheritDoc}
3767              */

3768             public TypeList.Generic getTypeArguments() {
3769                 throw new IllegalStateException("A non-generic type does not imply type arguments: " + this);
3770             }
3771
3772             /**
3773              * {@inheritDoc}
3774              */

3775             public Generic findBindingOf(Generic typeVariable) {
3776                 throw new IllegalStateException("A non-generic type does not imply type arguments: " + this);
3777             }
3778
3779             /**
3780              * {@inheritDoc}
3781              */

3782             public <T> T accept(Visitor<T> visitor) {
3783                 return visitor.onNonGenericType(this);
3784             }
3785
3786             /**
3787              * {@inheritDoc}
3788              */

3789             public String getTypeName() {
3790                 return asErasure().getTypeName();
3791             }
3792
3793             /**
3794              * {@inheritDoc}
3795              */

3796             public TypeList.Generic getUpperBounds() {
3797                 throw new IllegalStateException("A non-generic type does not imply upper type bounds: " + this);
3798             }
3799
3800             /**
3801              * {@inheritDoc}
3802              */

3803             public TypeList.Generic getLowerBounds() {
3804                 throw new IllegalStateException("A non-generic type does not imply lower type bounds: " + this);
3805             }
3806
3807             /**
3808              * {@inheritDoc}
3809              */

3810             public TypeVariableSource getTypeVariableSource() {
3811                 throw new IllegalStateException("A non-generic type does not imply a type variable source: " + this);
3812             }
3813
3814             /**
3815              * {@inheritDoc}
3816              */

3817             public String getSymbol() {
3818                 throw new IllegalStateException("A non-generic type does not imply a symbol: " + this);
3819             }
3820
3821             /**
3822              * {@inheritDoc}
3823              */

3824             public StackSize getStackSize() {
3825                 return asErasure().getStackSize();
3826             }
3827
3828             /**
3829              * {@inheritDoc}
3830              */

3831             public String getActualName() {
3832                 return asErasure().getActualName();
3833             }
3834
3835             /**
3836              * {@inheritDoc}
3837              */

3838             public boolean isArray() {
3839                 return asErasure().isArray();
3840             }
3841
3842             /**
3843              * {@inheritDoc}
3844              */

3845             public boolean isPrimitive() {
3846                 return asErasure().isPrimitive();
3847             }
3848
3849             /**
3850              * {@inheritDoc}
3851              */

3852             public boolean isRecord() {
3853                 return asErasure().isRecord();
3854             }
3855
3856             /**
3857              * {@inheritDoc}
3858              */

3859             public boolean represents(java.lang.reflect.Type type) {
3860                 return asErasure().represents(type);
3861             }
3862
3863             /**
3864              * {@inheritDoc}
3865              */

3866             public Iterator<TypeDefinition> iterator() {
3867                 return new SuperClassIterator(this);
3868             }
3869
3870             @Override
3871             @CachedReturnPlugin.Enhance
3872             public int hashCode() {
3873                 return asErasure().hashCode();
3874             }
3875
3876             @Override
3877             @SuppressFBWarnings(value = "EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS", justification = "Type check is performed by erasure implementation")
3878             public boolean equals(Object other) {
3879                 return this == other || asErasure().equals(other);
3880             }
3881
3882             @Override
3883             public String toString() {
3884                 return asErasure().toString();
3885             }
3886
3887             /**
3888              * Represents a non-generic type for a loaded {@link Class}.
3889              */

3890             public static class ForLoadedType extends OfNonGenericType {
3891
3892                 /**
3893                  * A cache of generic type descriptions for commonly used types to avoid unnecessary allocations.
3894                  */

3895                 @SuppressFBWarnings(value = "MS_MUTABLE_COLLECTION_PKGPROTECT", justification = "This collection is not exposed.")
3896                 private static final Map<Class<?>, Generic> TYPE_CACHE;
3897
3898                 /*
3899                  * Initializes the type cache.
3900                  */

3901                 static {
3902                     TYPE_CACHE = new HashMap<Class<?>, Generic>();
3903                     TYPE_CACHE.put(TargetType.classnew ForLoadedType(TargetType.class));
3904                     TYPE_CACHE.put(Object.classnew ForLoadedType(Object.class));
3905                     TYPE_CACHE.put(String.classnew ForLoadedType(String.class));
3906                     TYPE_CACHE.put(Boolean.classnew ForLoadedType(Boolean.class));
3907                     TYPE_CACHE.put(Byte.classnew ForLoadedType(Byte.class));
3908                     TYPE_CACHE.put(Short.classnew ForLoadedType(Short.class));
3909                     TYPE_CACHE.put(Character.classnew ForLoadedType(Character.class));
3910                     TYPE_CACHE.put(Integer.classnew ForLoadedType(Integer.class));
3911                     TYPE_CACHE.put(Long.classnew ForLoadedType(Long.class));
3912                     TYPE_CACHE.put(Float.classnew ForLoadedType(Float.class));
3913                     TYPE_CACHE.put(Double.classnew ForLoadedType(Double.class));
3914                     TYPE_CACHE.put(void.classnew ForLoadedType(void.class));
3915                     TYPE_CACHE.put(boolean.classnew ForLoadedType(boolean.class));
3916                     TYPE_CACHE.put(byte.classnew ForLoadedType(byte.class));
3917                     TYPE_CACHE.put(short.classnew ForLoadedType(short.class));
3918                     TYPE_CACHE.put(char.classnew ForLoadedType(char.class));
3919                     TYPE_CACHE.put(int.classnew ForLoadedType(int.class));
3920                     TYPE_CACHE.put(long.classnew ForLoadedType(long.class));
3921                     TYPE_CACHE.put(float.classnew ForLoadedType(float.class));
3922                     TYPE_CACHE.put(double.classnew ForLoadedType(double.class));
3923                 }
3924
3925                 /**
3926                  * The type that this instance represents.
3927                  */

3928                 private final Class<?> type;
3929
3930                 /**
3931                  * The annotation reader to query for the non-generic type's annotations.
3932                  */

3933                 private final AnnotationReader annotationReader;
3934
3935                 /**
3936                  * Creates a new description of a generic type of a loaded type. This constructor should not normally be used.
3937                  * Use {@link ForLoadedType#of(Class)} instead.
3938                  *
3939                  * @param type The represented type.
3940                  */

3941                 public ForLoadedType(Class<?> type) {
3942                     this(type, AnnotationReader.NoOp.INSTANCE);
3943                 }
3944
3945                 /**
3946                  * /**
3947                  * Creates a new description of a generic type of a loaded type.
3948                  *
3949                  * @param type             The represented type.
3950                  * @param annotationReader The annotation reader to query for the non-generic type's annotations.
3951                  */

3952                 protected ForLoadedType(Class<?> type, AnnotationReader annotationReader) {
3953                     this.type = type;
3954                     this.annotationReader = annotationReader;
3955                 }
3956
3957                 /**
3958                  * Returns a new immutable generic type description for a loaded type.
3959                  *
3960                  * @param type The type to be represented by this generic type description.
3961                  * @return The generic type description representing the given type.
3962                  */

3963                 public static Generic of(Class<?> type) {
3964                     Generic typeDescription = TYPE_CACHE.get(type);
3965                     return typeDescription == null
3966                             ? new ForLoadedType(type)
3967                             : typeDescription;
3968                 }
3969
3970                 /**
3971                  * {@inheritDoc}
3972                  */

3973                 public TypeDescription asErasure() {
3974                     return TypeDescription.ForLoadedType.of(type);
3975                 }
3976
3977                 /**
3978                  * {@inheritDoc}
3979                  */

3980                 public Generic getOwnerType() {
3981                     Class<?> declaringClass = this.type.getDeclaringClass();
3982                     return declaringClass == null
3983                             ? Generic.UNDEFINED
3984                             : new ForLoadedType(declaringClass, annotationReader.ofOuterClass());
3985                 }
3986
3987                 /**
3988                  * {@inheritDoc}
3989                  */

3990                 public Generic getComponentType() {
3991                     Class<?> componentType = type.getComponentType();
3992                     return componentType == null
3993                             ? Generic.UNDEFINED
3994                             : new ForLoadedType(componentType, annotationReader.ofComponentType());
3995                 }
3996
3997                 /**
3998                  * {@inheritDoc}
3999                  */

4000                 public AnnotationList getDeclaredAnnotations() {
4001                     return annotationReader.asList();
4002                 }
4003
4004                 /**
4005                  * {@inheritDoc}
4006                  */

4007                 public boolean represents(java.lang.reflect.Type type) {
4008                     return this.type == type || super.represents(type);
4009                 }
4010             }
4011
4012             /**
4013              * A type description for a type erasure. Compared to a {@link Latent} representation, this
4014              * representation does not allow for the specification of any complex properties but does
4015              * not require any form of navigation on the type.
4016              */

4017             public static class ForErasure extends OfNonGenericType {
4018
4019                 /**
4020                  * The represented type erasure.
4021                  */

4022                 private final TypeDescription typeDescription;
4023
4024                 /**
4025                  * Creates a new description of a non-generic type as an erasure.
4026                  *
4027                  * @param typeDescription The represented type erasure.
4028                  */

4029                 public ForErasure(TypeDescription typeDescription) {
4030                     this.typeDescription = typeDescription;
4031                 }
4032
4033                 /**
4034                  * {@inheritDoc}
4035                  */

4036                 public TypeDescription asErasure() {
4037                     return typeDescription;
4038                 }
4039
4040                 /**
4041                  * {@inheritDoc}
4042                  */

4043                 public Generic getOwnerType() {
4044                     TypeDescription declaringType = typeDescription.getDeclaringType();
4045                     return declaringType == null
4046                             ? Generic.UNDEFINED
4047                             : declaringType.asGenericType();
4048                 }
4049
4050                 /**
4051                  * {@inheritDoc}
4052                  */

4053                 public Generic getComponentType() {
4054                     TypeDescription componentType = typeDescription.getComponentType();
4055                     return componentType == null
4056                             ? Generic.UNDEFINED
4057                             : componentType.asGenericType();
4058                 }
4059
4060                 /**
4061                  * {@inheritDoc}
4062                  */

4063                 public AnnotationList getDeclaredAnnotations() {
4064                     return new AnnotationList.Empty();
4065                 }
4066             }
4067
4068             /**
4069              * A latent description of a non-generic type.
4070              */

4071             public static class Latent extends OfNonGenericType {
4072
4073                 /**
4074                  * The non-generic type's raw type.
4075                  */

4076                 private final TypeDescription typeDescription;
4077
4078                 /**
4079                  * The non-generic type's declaring type.
4080                  */

4081                 private final TypeDescription.Generic declaringType;
4082
4083                 /**
4084                  * The annotation source to query for the declared annotations.
4085                  */

4086                 private final AnnotationSource annotationSource;
4087
4088                 /**
4089                  * Creates a non-generic type with an implicit owner type.
4090                  *
4091                  * @param typeDescription  The non-generic type's raw type.
4092                  * @param annotationSource The annotation source to query for the declared annotations.
4093                  */

4094                 public Latent(TypeDescription typeDescription, AnnotationSource annotationSource) {
4095                     this(typeDescription, typeDescription.getDeclaringType(), annotationSource);
4096                 }
4097
4098                 /**
4099                  * Creates a non-generic type with a raw owner type.
4100                  *
4101                  * @param typeDescription  The non-generic type's raw type.
4102                  * @param declaringType    The non-generic type's declaring type.
4103                  * @param annotationSource The annotation source to query for the declared annotations.
4104                  */

4105                 private Latent(TypeDescription typeDescription, TypeDescription declaringType, AnnotationSource annotationSource) {
4106                     this(typeDescription,
4107                             declaringType == null
4108                                     ? Generic.UNDEFINED
4109                                     : declaringType.asGenericType(),
4110                             annotationSource);
4111                 }
4112
4113                 /**
4114                  * Creates a non-generic type.
4115                  *
4116                  * @param typeDescription  The non-generic type's raw type.
4117                  * @param declaringType    The non-generic type's declaring type.
4118                  * @param annotationSource The annotation source to query for the declared annotations.
4119                  */

4120                 protected Latent(TypeDescription typeDescription, Generic declaringType, AnnotationSource annotationSource) {
4121                     this.typeDescription = typeDescription;
4122                     this.declaringType = declaringType;
4123                     this.annotationSource = annotationSource;
4124                 }
4125
4126                 /**
4127                  * {@inheritDoc}
4128                  */

4129                 public Generic getOwnerType() {
4130                     return declaringType;
4131                 }
4132
4133                 /**
4134                  * {@inheritDoc}
4135                  */

4136                 public Generic getComponentType() {
4137                     TypeDescription componentType = typeDescription.getComponentType();
4138                     return componentType == null
4139                             ? Generic.UNDEFINED
4140                             : componentType.asGenericType();
4141                 }
4142
4143                 /**
4144                  * {@inheritDoc}
4145                  */

4146                 public AnnotationList getDeclaredAnnotations() {
4147                     return annotationSource.getDeclaredAnnotations();
4148                 }
4149
4150                 /**
4151                  * {@inheritDoc}
4152                  */

4153                 public TypeDescription asErasure() {
4154                     return typeDescription;
4155                 }
4156             }
4157
4158             /**
4159              * A representation of a raw type that preserves its generic super types' generic information with a minimum
4160              * but erases all of their members' types.
4161              */

4162             public static class ForReifiedErasure extends OfNonGenericType {
4163
4164                 /**
4165                  * The represented type erasure.
4166                  */

4167                 private final TypeDescription typeDescription;
4168
4169                 /**
4170                  * Creates a new reified non-generic type.
4171                  *
4172                  * @param typeDescription The represented type erasure.
4173                  */

4174                 protected ForReifiedErasure(TypeDescription typeDescription) {
4175                     this.typeDescription = typeDescription;
4176                 }
4177
4178                 /**
4179                  * Creates a new generic type representation for an erasure where any generified type is reified.
4180                  *
4181                  * @param typeDescription The erasure to represent.
4182                  * @return An appropriate generic type representation where any generified type is reified.
4183                  */

4184                 protected static Generic of(TypeDescription typeDescription) {
4185                     return typeDescription.isGenerified()
4186                             ? new ForReifiedErasure(typeDescription)
4187                             : new ForErasure(typeDescription);
4188                 }
4189
4190                 /**
4191                  * {@inheritDoc}
4192                  */

4193                 public Generic getSuperClass() {
4194                     Generic superClass = typeDescription.getSuperClass();
4195                     return superClass == null
4196                             ? Generic.UNDEFINED
4197                             : new LazyProjection.WithResolvedErasure(superClass, Visitor.Reifying.INHERITING);
4198                 }
4199
4200                 /**
4201                  * {@inheritDoc}
4202                  */

4203                 public TypeList.Generic getInterfaces() {
4204                     return new TypeList.Generic.ForDetachedTypes.WithResolvedErasure(typeDescription.getInterfaces(), Visitor.Reifying.INHERITING);
4205                 }
4206
4207                 /**
4208                  * {@inheritDoc}
4209                  */

4210                 public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
4211                     return new FieldList.TypeSubstituting(this, typeDescription.getDeclaredFields(), Visitor.TypeErasing.INSTANCE);
4212                 }
4213
4214                 /**
4215                  * {@inheritDoc}
4216                  */

4217                 public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
4218                     return new MethodList.TypeSubstituting(this, typeDescription.getDeclaredMethods(), Visitor.TypeErasing.INSTANCE);
4219                 }
4220
4221                 /**
4222                  * {@inheritDoc}
4223                  */

4224                 public TypeDescription asErasure() {
4225                     return typeDescription;
4226                 }
4227
4228                 /**
4229                  * {@inheritDoc}
4230                  */

4231                 public Generic getOwnerType() {
4232                     TypeDescription declaringType = typeDescription.getDeclaringType();
4233                     return declaringType == null
4234                             ? Generic.UNDEFINED
4235                             : of(declaringType);
4236                 }
4237
4238                 /**
4239                  * {@inheritDoc}
4240                  */

4241                 public Generic getComponentType() {
4242                     TypeDescription componentType = typeDescription.getComponentType();
4243                     return componentType == null
4244                             ? Generic.UNDEFINED
4245                             : of(componentType);
4246                 }
4247
4248                 /**
4249                  * {@inheritDoc}
4250                  */

4251                 public AnnotationList getDeclaredAnnotations() {
4252                     return new AnnotationList.Empty();
4253                 }
4254             }
4255         }
4256
4257         /**
4258          * A base implementation of a generic type description that represents a potentially generic array. Instances represent a non-generic type
4259          * if the given component type is non-generic.
4260          */

4261         abstract class OfGenericArray extends AbstractBase {
4262
4263             /**
4264              * {@inheritDoc}
4265              */

4266             public Sort getSort() {
4267                 return getComponentType().getSort().isNonGeneric()
4268                         ? Sort.NON_GENERIC
4269                         : Sort.GENERIC_ARRAY;
4270             }
4271
4272             /**
4273              * {@inheritDoc}
4274              */

4275             public TypeDescription asErasure() {
4276                 return ArrayProjection.of(getComponentType().asErasure(), 1);
4277             }
4278
4279             /**
4280              * {@inheritDoc}
4281              */

4282             public Generic getSuperClass() {
4283                 return TypeDescription.Generic.OBJECT;
4284             }
4285
4286             /**
4287              * {@inheritDoc}
4288              */

4289             public TypeList.Generic getInterfaces() {
4290                 return ARRAY_INTERFACES;
4291             }
4292
4293             /**
4294              * {@inheritDoc}
4295              */

4296             public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
4297                 return new FieldList.Empty<FieldDescription.InGenericShape>();
4298             }
4299
4300             /**
4301              * {@inheritDoc}
4302              */

4303             public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
4304                 return new MethodList.Empty<MethodDescription.InGenericShape>();
4305             }
4306
4307             /**
4308              * {@inheritDoc}
4309              */

4310             public RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents() {
4311                 return new RecordComponentList.Empty<RecordComponentDescription.InGenericShape>();
4312             }
4313
4314             /**
4315              * {@inheritDoc}
4316              */

4317             public TypeList.Generic getUpperBounds() {
4318                 throw new IllegalStateException("A generic array type does not imply upper type bounds: " + this);
4319             }
4320
4321             /**
4322              * {@inheritDoc}
4323              */

4324             public TypeList.Generic getLowerBounds() {
4325                 throw new IllegalStateException("A generic array type does not imply lower type bounds: " + this);
4326             }
4327
4328             /**
4329              * {@inheritDoc}
4330              */

4331             public TypeVariableSource getTypeVariableSource() {
4332                 throw new IllegalStateException("A generic array type does not imply a type variable source: " + this);
4333             }
4334
4335             /**
4336              * {@inheritDoc}
4337              */

4338             public TypeList.Generic getTypeArguments() {
4339                 throw new IllegalStateException("A generic array type does not imply type arguments: " + this);
4340             }
4341
4342             /**
4343              * {@inheritDoc}
4344              */

4345             public Generic findBindingOf(Generic typeVariable) {
4346                 throw new IllegalStateException("A generic array type does not imply type arguments: " + this);
4347             }
4348
4349             /**
4350              * {@inheritDoc}
4351              */

4352             public Generic getOwnerType() {
4353                 return Generic.UNDEFINED;
4354             }
4355
4356             /**
4357              * {@inheritDoc}
4358              */

4359             public String getSymbol() {
4360                 throw new IllegalStateException("A generic array type does not imply a symbol: " + this);
4361             }
4362
4363             /**
4364              * {@inheritDoc}
4365              */

4366             public String getTypeName() {
4367                 return getSort().isNonGeneric()
4368                         ? asErasure().getTypeName()
4369                         : toString();
4370             }
4371
4372             /**
4373              * {@inheritDoc}
4374              */

4375             public String getActualName() {
4376                 return getSort().isNonGeneric()
4377                         ? asErasure().getActualName()
4378                         : toString();
4379             }
4380
4381             /**
4382              * {@inheritDoc}
4383              */

4384             public boolean isArray() {
4385                 return true;
4386             }
4387
4388             /**
4389              * {@inheritDoc}
4390              */

4391             public boolean isPrimitive() {
4392                 return false;
4393             }
4394
4395             /**
4396              * {@inheritDoc}
4397              */

4398             public boolean isRecord() {
4399                 return false;
4400             }
4401
4402             /**
4403              * {@inheritDoc}
4404              */

4405             public Iterator<TypeDefinition> iterator() {
4406                 return new SuperClassIterator(this);
4407             }
4408
4409             /**
4410              * {@inheritDoc}
4411              */

4412             public <T> T accept(Visitor<T> visitor) {
4413                 return getSort().isNonGeneric()
4414                         ? visitor.onNonGenericType(this)
4415                         : visitor.onGenericArray(this);
4416             }
4417
4418             /**
4419              * {@inheritDoc}
4420              */

4421             public StackSize getStackSize() {
4422                 return StackSize.SINGLE;
4423             }
4424
4425             @Override
4426             @CachedReturnPlugin.Enhance
4427             public int hashCode() {
4428                 return getSort().isNonGeneric()
4429                         ? asErasure().hashCode()
4430                         : getComponentType().hashCode();
4431             }
4432
4433             @Override
4434             @SuppressFBWarnings(value = "EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS", justification = "Type check is performed by erasure implementation")
4435             public boolean equals(Object other) {
4436                 if (this == other) {
4437                     return true;
4438                 } else if (getSort().isNonGeneric()) {
4439                     return asErasure().equals(other);
4440                 }
4441                 if (!(other instanceof Generic)) {
4442                     return false;
4443                 }
4444                 Generic typeDescription = (Generic) other;
4445                 return typeDescription.getSort().isGenericArray() && getComponentType().equals(typeDescription.getComponentType());
4446             }
4447
4448             @Override
4449             public String toString() {
4450                 return getSort().isNonGeneric()
4451                         ? asErasure().toString()
4452                         : getComponentType().getTypeName() + "[]";
4453             }
4454
4455             /**
4456              * A description of a loaded generic array type.
4457              */

4458             public static class ForLoadedType extends OfGenericArray {
4459
4460                 /**
4461                  * The loaded generic array type.
4462                  */

4463                 private final GenericArrayType genericArrayType;
4464
4465                 /**
4466                  * The annotation reader to query for the generic array type's annotations.
4467                  */

4468                 private final AnnotationReader annotationReader;
4469
4470                 /**
4471                  * Creates a type description of the given generic array type.
4472                  *
4473                  * @param genericArrayType The loaded generic array type.
4474                  */

4475                 public ForLoadedType(GenericArrayType genericArrayType) {
4476                     this(genericArrayType, AnnotationReader.NoOp.INSTANCE);
4477                 }
4478
4479                 /**
4480                  * Creates a type description of the given generic array type.
4481                  *
4482                  * @param genericArrayType The loaded generic array type.
4483                  * @param annotationReader The annotation reader to query for the generic array type's annotations.
4484                  */

4485                 protected ForLoadedType(GenericArrayType genericArrayType, AnnotationReader annotationReader) {
4486                     this.genericArrayType = genericArrayType;
4487                     this.annotationReader = annotationReader;
4488                 }
4489
4490                 /**
4491                  * {@inheritDoc}
4492                  */

4493                 public Generic getComponentType() {
4494                     return Sort.describe(genericArrayType.getGenericComponentType(), annotationReader.ofComponentType());
4495                 }
4496
4497                 /**
4498                  * {@inheritDoc}
4499                  */

4500                 public AnnotationList getDeclaredAnnotations() {
4501                     return annotationReader.asList();
4502                 }
4503
4504                 /**
4505                  * {@inheritDoc}
4506                  */

4507                 public boolean represents(java.lang.reflect.Type type) {
4508                     return genericArrayType == type || super.represents(type);
4509                 }
4510             }
4511
4512             /**
4513              * A latent implementation of a generic array type.
4514              */

4515             public static class Latent extends OfGenericArray {
4516
4517                 /**
4518                  * The component type of the generic array.
4519                  */

4520                 private final Generic componentType;
4521
4522                 /**
4523                  * The annotation source to query for the declared annotations.
4524                  */

4525                 private final AnnotationSource annotationSource;
4526
4527                 /**
4528                  * Creates a latent representation of a generic array type.
4529                  *
4530                  * @param componentType    The component type.
4531                  * @param annotationSource The annotation source to query for the declared annotations.
4532                  */

4533                 public Latent(Generic componentType, AnnotationSource annotationSource) {
4534                     this.componentType = componentType;
4535                     this.annotationSource = annotationSource;
4536                 }
4537
4538                 /**
4539                  * {@inheritDoc}
4540                  */

4541                 public Generic getComponentType() {
4542                     return componentType;
4543                 }
4544
4545                 /**
4546                  * {@inheritDoc}
4547                  */

4548                 public AnnotationList getDeclaredAnnotations() {
4549                     return annotationSource.getDeclaredAnnotations();
4550                 }
4551             }
4552         }
4553
4554         /**
4555          * A base implementation of a generic type description that represents a wildcard type.
4556          */

4557         abstract class OfWildcardType extends AbstractBase {
4558
4559             /**
4560              * The source code representation of a wildcard.
4561              */

4562             public static final String SYMBOL = "?";
4563
4564             /**
4565              * {@inheritDoc}
4566              */

4567             public Sort getSort() {
4568                 return Sort.WILDCARD;
4569             }
4570
4571             /**
4572              * {@inheritDoc}
4573              */

4574             public TypeDescription asErasure() {
4575                 throw new IllegalStateException("A wildcard does not represent an erasable type: " + this);
4576             }
4577
4578             /**
4579              * {@inheritDoc}
4580              */

4581             public Generic getSuperClass() {
4582                 throw new IllegalStateException("A wildcard does not imply a super type definition: " + this);
4583             }
4584
4585             /**
4586              * {@inheritDoc}
4587              */

4588             public TypeList.Generic getInterfaces() {
4589                 throw new IllegalStateException("A wildcard does not imply an interface type definition: " + this);
4590             }
4591
4592             /**
4593              * {@inheritDoc}
4594              */

4595             public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
4596                 throw new IllegalStateException("A wildcard does not imply field definitions: " + this);
4597             }
4598
4599             /**
4600              * {@inheritDoc}
4601              */

4602             public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
4603                 throw new IllegalStateException("A wildcard does not imply method definitions: " + this);
4604             }
4605
4606             /**
4607              * {@inheritDoc}
4608              */

4609             public RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents() {
4610                 throw new IllegalStateException("A wildcard does not imply record component definitions: " + this);
4611             }
4612
4613             /**
4614              * {@inheritDoc}
4615              */

4616             public Generic getComponentType() {
4617                 throw new IllegalStateException("A wildcard does not imply a component type: " + this);
4618             }
4619
4620             /**
4621              * {@inheritDoc}
4622              */

4623             public TypeVariableSource getTypeVariableSource() {
4624                 throw new IllegalStateException("A wildcard does not imply a type variable source: " + this);
4625             }
4626
4627             /**
4628              * {@inheritDoc}
4629              */

4630             public TypeList.Generic getTypeArguments() {
4631                 throw new IllegalStateException("A wildcard does not imply type arguments: " + this);
4632             }
4633
4634             /**
4635              * {@inheritDoc}
4636              */

4637             public Generic findBindingOf(Generic typeVariable) {
4638                 throw new IllegalStateException("A wildcard does not imply type arguments: " + this);
4639             }
4640
4641             /**
4642              * {@inheritDoc}
4643              */

4644             public Generic getOwnerType() {
4645                 throw new IllegalStateException("A wildcard does not imply an owner type: " + this);
4646             }
4647
4648             /**
4649              * {@inheritDoc}
4650              */

4651             public String getSymbol() {
4652                 throw new IllegalStateException("A wildcard does not imply a symbol: " + this);
4653             }
4654
4655             /**
4656              * {@inheritDoc}
4657              */

4658             public String getTypeName() {
4659                 return toString();
4660             }
4661
4662             /**
4663              * {@inheritDoc}
4664              */

4665             public String getActualName() {
4666                 return toString();
4667             }
4668
4669             /**
4670              * {@inheritDoc}
4671              */

4672             public boolean isPrimitive() {
4673                 return false;
4674             }
4675
4676             /**
4677              * {@inheritDoc}
4678              */

4679             public boolean isArray() {
4680                 return false;
4681             }
4682
4683             /**
4684              * {@inheritDoc}
4685              */

4686             public boolean isRecord() {
4687                 return false;
4688             }
4689
4690             /**
4691              * {@inheritDoc}
4692              */

4693             public boolean represents(java.lang.reflect.Type type) {
4694                 return equals(Sort.describe(type));
4695             }
4696
4697             /**
4698              * {@inheritDoc}
4699              */

4700             public Iterator<TypeDefinition> iterator() {
4701                 throw new IllegalStateException("A wildcard does not imply a super type definition: " + this);
4702             }
4703
4704             /**
4705              * {@inheritDoc}
4706              */

4707             public <T> T accept(Visitor<T> visitor) {
4708                 return visitor.onWildcard(this);
4709             }
4710
4711             /**
4712              * {@inheritDoc}
4713              */

4714             public StackSize getStackSize() {
4715                 throw new IllegalStateException("A wildcard does not imply an operand stack size: " + this);
4716             }
4717
4718             @Override
4719             @CachedReturnPlugin.Enhance
4720             public int hashCode() {
4721                 int lowerHash = 1, upperHash = 1;
4722                 for (Generic lowerBound : getLowerBounds()) {
4723                     lowerHash = 31 * lowerHash + lowerBound.hashCode();
4724                 }
4725                 for (Generic upperBound : getUpperBounds()) {
4726                     upperHash = 31 * upperHash + upperBound.hashCode();
4727                 }
4728                 return lowerHash ^ upperHash;
4729             }
4730
4731             @Override
4732             public boolean equals(Object other) {
4733                 if (this == other) {
4734                     return true;
4735                 } else if (!(other instanceof Generic)) {
4736                     return false;
4737                 }
4738                 Generic typeDescription = (Generic) other;
4739                 return typeDescription.getSort().isWildcard()
4740                         && getUpperBounds().equals(typeDescription.getUpperBounds())
4741                         && getLowerBounds().equals(typeDescription.getLowerBounds());
4742             }
4743
4744             @Override
4745             public String toString() {
4746                 StringBuilder stringBuilder = new StringBuilder(SYMBOL);
4747                 TypeList.Generic bounds = getLowerBounds();
4748                 if (!bounds.isEmpty()) {
4749                     stringBuilder.append(super ");
4750                 } else {
4751                     bounds = getUpperBounds();
4752                     if (bounds.getOnly().equals(TypeDescription.Generic.OBJECT)) {
4753                         return SYMBOL;
4754                     }
4755                     stringBuilder.append(extends ");
4756                 }
4757                 return stringBuilder.append(bounds.getOnly().getTypeName()).toString();
4758             }
4759
4760             /**
4761              * Description of a loaded wildcard.
4762              */

4763             public static class ForLoadedType extends OfWildcardType {
4764
4765                 /**
4766                  * The represented loaded wildcard type.
4767                  */

4768                 private final WildcardType wildcardType;
4769
4770                 /**
4771                  * The annotation reader to query for the wildcard type's annotations.
4772                  */

4773                 private final AnnotationReader annotationReader;
4774
4775                 /**
4776                  * Creates a description of a loaded wildcard.
4777                  *
4778                  * @param wildcardType The represented loaded wildcard type.
4779                  */

4780                 public ForLoadedType(WildcardType wildcardType) {
4781                     this(wildcardType, AnnotationReader.NoOp.INSTANCE);
4782                 }
4783
4784                 /**
4785                  * Creates a description of a loaded wildcard.
4786                  *
4787                  * @param wildcardType     The represented loaded wildcard type.
4788                  * @param annotationReader The annotation reader to query for the wildcard type's annotations.
4789                  */

4790                 protected ForLoadedType(WildcardType wildcardType, AnnotationReader annotationReader) {
4791                     this.wildcardType = wildcardType;
4792                     this.annotationReader = annotationReader;
4793                 }
4794
4795                 /**
4796                  * {@inheritDoc}
4797                  */

4798                 public TypeList.Generic getUpperBounds() {
4799                     return new WildcardUpperBoundTypeList(wildcardType.getUpperBounds(), annotationReader);
4800                 }
4801
4802                 /**
4803                  * {@inheritDoc}
4804                  */

4805                 public TypeList.Generic getLowerBounds() {
4806                     return new WildcardLowerBoundTypeList(wildcardType.getLowerBounds(), annotationReader);
4807                 }
4808
4809                 /**
4810                  * {@inheritDoc}
4811                  */

4812                 public AnnotationList getDeclaredAnnotations() {
4813                     return annotationReader.asList();
4814                 }
4815
4816                 /**
4817                  * {@inheritDoc}
4818                  */

4819                 public boolean represents(java.lang.reflect.Type type) {
4820                     return wildcardType == type || super.represents(type);
4821                 }
4822
4823                 /**
4824                  * A type list representing an upper-bound type variable's bound types.
4825                  */

4826                 protected static class WildcardUpperBoundTypeList extends TypeList.Generic.AbstractBase {
4827
4828                     /**
4829                      * The represented upper bounds.
4830                      */

4831                     private final java.lang.reflect.Type[] upperBound;
4832
4833                     /**
4834                      * The annotation reader to query for type annotations.
4835                      */

4836                     private final AnnotationReader annotationReader;
4837
4838                     /**
4839                      * Creates a type list for a wildcard type's upper bounds.
4840                      *
4841                      * @param upperBound       The represented upper bounds.
4842                      * @param annotationReader The annotation reader to query for type annotations.
4843                      */

4844                     protected WildcardUpperBoundTypeList(java.lang.reflect.Type[] upperBound, AnnotationReader annotationReader) {
4845                         this.upperBound = upperBound;
4846                         this.annotationReader = annotationReader;
4847                     }
4848
4849                     /**
4850                      * {@inheritDoc}
4851                      */

4852                     public Generic get(int index) {
4853                         return Sort.describe(upperBound[index], annotationReader.ofWildcardUpperBoundType(index));
4854                     }
4855
4856                     /**
4857                      * {@inheritDoc}
4858                      */

4859                     public int size() {
4860                         return upperBound.length;
4861                     }
4862                 }
4863
4864                 /**
4865                  * A type list representing an upper-bound type variable's bound types.
4866                  */

4867                 protected static class WildcardLowerBoundTypeList extends TypeList.Generic.AbstractBase {
4868
4869                     /**
4870                      * The represented lower bounds.
4871                      */

4872                     private final java.lang.reflect.Type[] lowerBound;
4873
4874                     /**
4875                      * The annotation reader to query for type annotations.
4876                      */

4877                     private final AnnotationReader annotationReader;
4878
4879                     /**
4880                      * Creates a type list for a wildcard type's lower bounds.
4881                      *
4882                      * @param lowerBound       The represented lower bounds.
4883                      * @param annotationReader The annotation reader to query for type annotations.
4884                      */

4885                     protected WildcardLowerBoundTypeList(java.lang.reflect.Type[] lowerBound, AnnotationReader annotationReader) {
4886                         this.lowerBound = lowerBound;
4887                         this.annotationReader = annotationReader;
4888                     }
4889
4890                     /**
4891                      * {@inheritDoc}
4892                      */

4893                     public Generic get(int index) {
4894                         return Sort.describe(lowerBound[index], annotationReader.ofWildcardLowerBoundType(index));
4895                     }
4896
4897                     /**
4898                      * {@inheritDoc}
4899                      */

4900                     public int size() {
4901                         return lowerBound.length;
4902                     }
4903                 }
4904             }
4905
4906             /**
4907              * A latent description of a wildcard type.
4908              */

4909             public static class Latent extends OfWildcardType {
4910
4911                 /**
4912                  * The wildcard's upper bounds.
4913                  */

4914                 private final List<? extends Generic> upperBounds;
4915
4916                 /**
4917                  * The wildcard's lower bounds.
4918                  */

4919                 private final List<? extends Generic> lowerBounds;
4920
4921                 /**
4922                  * The annotation source to query for the declared annotations.
4923                  */

4924                 private final AnnotationSource annotationSource;
4925
4926                 /**
4927                  * Creates a description of a latent wildcard.
4928                  *
4929                  * @param upperBounds      The wildcard's upper bounds.
4930                  * @param lowerBounds      The wildcard's lower bounds.
4931                  * @param annotationSource The annotation source to query for the declared annotations.
4932                  */

4933                 protected Latent(List<? extends Generic> upperBounds, List<? extends Generic> lowerBounds, AnnotationSource annotationSource) {
4934                     this.upperBounds = upperBounds;
4935                     this.lowerBounds = lowerBounds;
4936                     this.annotationSource = annotationSource;
4937                 }
4938
4939                 /**
4940                  * Creates an unbounded wildcard. Such a wildcard is implicitly bound above by the {@link Object} type.
4941                  *
4942                  * @param annotationSource The annotation source to query for the declared annotations.
4943                  * @return A description of an unbounded wildcard.
4944                  */

4945                 public static Generic unbounded(AnnotationSource annotationSource) {
4946                     return new Latent(Collections.singletonList(TypeDescription.Generic.OBJECT), Collections.<Generic>emptyList(), annotationSource);
4947                 }
4948
4949                 /**
4950                  * Creates a wildcard with an upper bound.
4951                  *
4952                  * @param upperBound       The upper bound of the wildcard.
4953                  * @param annotationSource The annotation source to query for the declared annotations.
4954                  * @return A wildcard with the given upper bound.
4955                  */

4956                 public static Generic boundedAbove(Generic upperBound, AnnotationSource annotationSource) {
4957                     return new Latent(Collections.singletonList(upperBound), Collections.<Generic>emptyList(), annotationSource);
4958                 }
4959
4960                 /**
4961                  * Creates a wildcard with a lower bound. Such a wildcard is implicitly bounded above by the {@link Object} type.
4962                  *
4963                  * @param lowerBound       The lower bound of the wildcard.
4964                  * @param annotationSource The annotation source to query for the declared annotations.
4965                  * @return A wildcard with the given lower bound.
4966                  */

4967                 public static Generic boundedBelow(Generic lowerBound, AnnotationSource annotationSource) {
4968                     return new Latent(Collections.singletonList(TypeDescription.Generic.OBJECT), Collections.singletonList(lowerBound), annotationSource);
4969                 }
4970
4971                 /**
4972                  * {@inheritDoc}
4973                  */

4974                 public TypeList.Generic getUpperBounds() {
4975                     return new TypeList.Generic.Explicit(upperBounds);
4976                 }
4977
4978                 /**
4979                  * {@inheritDoc}
4980                  */

4981                 public TypeList.Generic getLowerBounds() {
4982                     return new TypeList.Generic.Explicit(lowerBounds);
4983                 }
4984
4985                 /**
4986                  * {@inheritDoc}
4987                  */

4988                 public AnnotationList getDeclaredAnnotations() {
4989                     return annotationSource.getDeclaredAnnotations();
4990                 }
4991             }
4992         }
4993
4994         /**
4995          * A base implementation of a generic type description that represents a parameterized type.
4996          */

4997         abstract class OfParameterizedType extends AbstractBase {
4998
4999             /**
5000              * {@inheritDoc}
5001              */

5002             public Sort getSort() {
5003                 return Sort.PARAMETERIZED;
5004             }
5005
5006             /**
5007              * {@inheritDoc}
5008              */

5009             public Generic getSuperClass() {
5010                 Generic superClass = asErasure().getSuperClass();
5011                 return superClass == null
5012                         ? Generic.UNDEFINED
5013                         : new LazyProjection.WithResolvedErasure(superClass, new Visitor.Substitutor.ForTypeVariableBinding(this));
5014             }
5015
5016             /**
5017              * {@inheritDoc}
5018              */

5019             public TypeList.Generic getInterfaces() {
5020                 return new TypeList.Generic.ForDetachedTypes.WithResolvedErasure(asErasure().getInterfaces(), new Visitor.Substitutor.ForTypeVariableBinding(this));
5021             }
5022
5023             /**
5024              * {@inheritDoc}
5025              */

5026             public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
5027                 return new FieldList.TypeSubstituting(this, asErasure().getDeclaredFields(), new Visitor.Substitutor.ForTypeVariableBinding(this));
5028             }
5029
5030             /**
5031              * {@inheritDoc}
5032              */

5033             public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
5034                 return new MethodList.TypeSubstituting(this, asErasure().getDeclaredMethods(), new Visitor.Substitutor.ForTypeVariableBinding(this));
5035             }
5036
5037             /**
5038              * {@inheritDoc}
5039              */

5040             public RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents() {
5041                 return new RecordComponentList.TypeSubstituting(this, asErasure().getRecordComponents(), new Visitor.Substitutor.ForTypeVariableBinding(this));
5042             }
5043
5044             /**
5045              * {@inheritDoc}
5046              */

5047             public Generic findBindingOf(Generic typeVariable) {
5048                 Generic typeDescription = this;
5049                 do {
5050                     TypeList.Generic typeArguments = typeDescription.getTypeArguments(), typeVariables = typeDescription.asErasure().getTypeVariables();
5051                     for (int index = 0; index < Math.min(typeArguments.size(), typeVariables.size()); index++) {
5052                         if (typeVariable.equals(typeVariables.get(index))) {
5053                             return typeArguments.get(index);
5054                         }
5055                     }
5056                     typeDescription = typeDescription.getOwnerType();
5057                 } while (typeDescription != null && typeDescription.getSort().isParameterized());
5058                 return Generic.UNDEFINED;
5059             }
5060
5061             /**
5062              * {@inheritDoc}
5063              */

5064             public TypeList.Generic getUpperBounds() {
5065                 throw new IllegalStateException("A parameterized type does not imply upper bounds: " + this);
5066             }
5067
5068             /**
5069              * {@inheritDoc}
5070              */

5071             public TypeList.Generic getLowerBounds() {
5072                 throw new IllegalStateException("A parameterized type does not imply lower bounds: " + this);
5073             }
5074
5075             /**
5076              * {@inheritDoc}
5077              */

5078             public Generic getComponentType() {
5079                 throw new IllegalStateException("A parameterized type does not imply a component type: " + this);
5080             }
5081
5082             /**
5083              * {@inheritDoc}
5084              */

5085             public TypeVariableSource getTypeVariableSource() {
5086                 throw new IllegalStateException("A parameterized type does not imply a type variable source: " + this);
5087             }
5088
5089             /**
5090              * {@inheritDoc}
5091              */

5092             public String getSymbol() {
5093                 throw new IllegalStateException("A parameterized type does not imply a symbol: " + this);
5094             }
5095
5096             /**
5097              * {@inheritDoc}
5098              */

5099             public String getTypeName() {
5100                 return toString();
5101             }
5102
5103             /**
5104              * {@inheritDoc}
5105              */

5106             public String getActualName() {
5107                 return toString();
5108             }
5109
5110             /**
5111              * {@inheritDoc}
5112              */

5113             public boolean isPrimitive() {
5114                 return false;
5115             }
5116
5117             /**
5118              * {@inheritDoc}
5119              */

5120             public boolean isArray() {
5121                 return false;
5122             }
5123
5124             /**
5125              * {@inheritDoc}
5126              */

5127             public boolean isRecord() {
5128                 return asErasure().isRecord();
5129             }
5130
5131             /**
5132              * {@inheritDoc}
5133              */

5134             public boolean represents(java.lang.reflect.Type type) {
5135                 return equals(Sort.describe(type));
5136             }
5137
5138             /**
5139              * {@inheritDoc}
5140              */

5141             public Iterator<TypeDefinition> iterator() {
5142                 return new SuperClassIterator(this);
5143             }
5144
5145             /**
5146              * {@inheritDoc}
5147              */

5148             public <T> T accept(Visitor<T> visitor) {
5149                 return visitor.onParameterizedType(this);
5150             }
5151
5152             /**
5153              * {@inheritDoc}
5154              */

5155             public StackSize getStackSize() {
5156                 return StackSize.SINGLE;
5157             }
5158
5159             @Override
5160             @CachedReturnPlugin.Enhance
5161             public int hashCode() {
5162                 int result = 1;
5163                 for (Generic typeArgument : getTypeArguments()) {
5164                     result = 31 * result + typeArgument.hashCode();
5165                 }
5166                 Generic ownerType = getOwnerType();
5167                 return result ^ (ownerType == null
5168                         ? asErasure().hashCode()
5169                         : ownerType.hashCode());
5170             }
5171
5172             @Override
5173             public boolean equals(Object other) {
5174                 if (this == other) {
5175                     return true;
5176                 } else if (!(other instanceof Generic)) {
5177                     return false;
5178                 }
5179                 Generic typeDescription = (Generic) other;
5180                 if (!typeDescription.getSort().isParameterized()) {
5181                     return false;
5182                 }
5183                 Generic ownerType = getOwnerType(), otherOwnerType = typeDescription.getOwnerType();
5184                 return asErasure().equals(typeDescription.asErasure())
5185                         && !(ownerType == null && otherOwnerType != null) && !(ownerType != null && !ownerType.equals(otherOwnerType))
5186                         && getTypeArguments().equals(typeDescription.getTypeArguments());
5187             }
5188
5189             @Override
5190             public String toString() {
5191                 StringBuilder stringBuilder = new StringBuilder();
5192                 RenderingDelegate.CURRENT.apply(stringBuilder, asErasure(), getOwnerType());
5193                 TypeList.Generic typeArguments = getTypeArguments();
5194                 if (!typeArguments.isEmpty()) {
5195                     stringBuilder.append('<');
5196                     boolean multiple = false;
5197                     for (Generic typeArgument : typeArguments) {
5198                         if (multiple) {
5199                             stringBuilder.append(", ");
5200                         }
5201                         stringBuilder.append(typeArgument.getTypeName());
5202                         multiple = true;
5203                     }
5204                     stringBuilder.append('>');
5205                 }
5206                 return stringBuilder.toString();
5207             }
5208
5209             /**
5210              * A rendering delegate for resolving a parameterized type's {@link Object#toString()} representation.
5211              */

5212             protected enum RenderingDelegate {
5213
5214                 /**
5215                  * A rendering delegate for any VM prior to Java 9 where types are concatenated using a {@code .} character
5216                  * and where the fully qualified names are appended to non-parameterized types.
5217                  */

5218                 FOR_LEGACY_VM {
5219                     @Override
5220                     protected void apply(StringBuilder stringBuilder, TypeDescription erasure, Generic ownerType) {
5221                         if (ownerType != null) {
5222                             stringBuilder.append(ownerType.getTypeName()).append('.').append(ownerType.getSort().isParameterized()
5223                                     ? erasure.getSimpleName()
5224                                     : erasure.getName());
5225                         } else {
5226                             stringBuilder.append(erasure.getName());
5227                         }
5228                     }
5229                 },
5230
5231                 /**
5232                  * A rendering delegate for any VM supporting Java 8 or newer where a type's simple name is appended.
5233                  */

5234                 FOR_JAVA_8_CAPABLE_VM {
5235                     @Override
5236                     protected void apply(StringBuilder stringBuilder, TypeDescription erasure, Generic ownerType) {
5237                         if (ownerType != null) {
5238                             stringBuilder.append(ownerType.getTypeName()).append('$');
5239                             if (ownerType.getSort().isParameterized()) {
5240                                 stringBuilder.append(erasure.getName().replace(ownerType.asErasure().getName() + "$"""));
5241                             } else {
5242                                 stringBuilder.append(erasure.getSimpleName());
5243                             }
5244                         } else {
5245                             stringBuilder.append(erasure.getName());
5246                         }
5247                     }
5248                 };
5249
5250                 /**
5251                  * A rendering delegate for the current VM.
5252                  */

5253                 protected static final RenderingDelegate CURRENT = ClassFileVersion.ofThisVm(ClassFileVersion.JAVA_V6).isAtLeast(ClassFileVersion.JAVA_V8)
5254                         ? RenderingDelegate.FOR_JAVA_8_CAPABLE_VM
5255                         : RenderingDelegate.FOR_LEGACY_VM;
5256
5257                 /**
5258                  * Applies this rendering delegate.
5259                  *
5260                  * @param stringBuilder The string builder which is used for creating a parameterized type's string representation.
5261                  * @param erasure       The rendered type's erasure.
5262                  * @param ownerType     The rendered type's owner type.
5263                  */

5264                 protected abstract void apply(StringBuilder stringBuilder, TypeDescription erasure, Generic ownerType);
5265             }
5266
5267             /**
5268              * Description of a loaded parameterized type.
5269              */

5270             public static class ForLoadedType extends OfParameterizedType {
5271
5272                 /**
5273                  * The represented parameterized type.
5274                  */

5275                 private final ParameterizedType parameterizedType;
5276
5277                 /**
5278                  * The annotation reader to query for the parameterized type's annotations.
5279                  */

5280                 private final AnnotationReader annotationReader;
5281
5282                 /**
5283                  * Creates a description of the loaded parameterized type.
5284                  *
5285                  * @param parameterizedType The represented parameterized type.
5286                  */

5287                 public ForLoadedType(ParameterizedType parameterizedType) {
5288                     this(parameterizedType, AnnotationReader.NoOp.INSTANCE);
5289                 }
5290
5291                 /**
5292                  * Creates a description of the loaded parameterized type.
5293                  *
5294                  * @param parameterizedType The represented parameterized type.
5295                  * @param annotationReader  The annotation reader to query for the parameterized type's annotations.
5296                  */

5297                 protected ForLoadedType(ParameterizedType parameterizedType, AnnotationReader annotationReader) {
5298                     this.parameterizedType = parameterizedType;
5299                     this.annotationReader = annotationReader;
5300                 }
5301
5302                 /**
5303                  * {@inheritDoc}
5304                  */

5305                 public TypeList.Generic getTypeArguments() {
5306                     return new ParameterArgumentTypeList(parameterizedType.getActualTypeArguments(), annotationReader);
5307                 }
5308
5309                 /**
5310                  * {@inheritDoc}
5311                  */

5312                 public Generic getOwnerType() {
5313                     java.lang.reflect.Type ownerType = parameterizedType.getOwnerType();
5314                     return ownerType == null
5315                             ? Generic.UNDEFINED
5316                             : Sort.describe(ownerType, annotationReader.ofOwnerType());
5317                 }
5318
5319                 /**
5320                  * {@inheritDoc}
5321                  */

5322                 public TypeDescription asErasure() {
5323                     return TypeDescription.ForLoadedType.of((Class<?>) parameterizedType.getRawType());
5324                 }
5325
5326                 /**
5327                  * {@inheritDoc}
5328                  */

5329                 public AnnotationList getDeclaredAnnotations() {
5330                     return annotationReader.asList();
5331                 }
5332
5333                 /**
5334                  * {@inheritDoc}
5335                  */

5336                 public boolean represents(java.lang.reflect.Type type) {
5337                     return parameterizedType == type || super.represents(type);
5338                 }
5339
5340                 /**
5341                  * A type list that represents a loaded parameterized type's parameter types.
5342                  */

5343                 protected static class ParameterArgumentTypeList extends TypeList.Generic.AbstractBase {
5344
5345                     /**
5346                      * The represented argument types.
5347                      */

5348                     private final java.lang.reflect.Type[] argumentType;
5349
5350                     /**
5351                      * The annotation reader to query for type annotations.
5352                      */

5353                     private final AnnotationReader annotationReader;
5354
5355                     /**
5356                      * Creates a list representing a parameterized type's type arguments.
5357                      *
5358                      * @param argumentType     The represented argument types.
5359                      * @param annotationReader The annotation reader to query for type annotations.
5360                      */

5361                     protected ParameterArgumentTypeList(java.lang.reflect.Type[] argumentType, AnnotationReader annotationReader) {
5362                         this.argumentType = argumentType;
5363                         this.annotationReader = annotationReader;
5364                     }
5365
5366                     /**
5367                      * {@inheritDoc}
5368                      */

5369                     public Generic get(int index) {
5370                         // Obfuscators sometimes render parameterized type arguments as null values.
5371                         return Sort.describe(argumentType[index], annotationReader.ofTypeArgument(index));
5372                     }
5373
5374                     /**
5375                      * {@inheritDoc}
5376                      */

5377                     public int size() {
5378                         return argumentType.length;
5379                     }
5380                 }
5381             }
5382
5383             /**
5384              * A latent description of a parameterized type.
5385              */

5386             public static class Latent extends OfParameterizedType {
5387
5388                 /**
5389                  * The raw type of the described parameterized type.
5390                  */

5391                 private final TypeDescription rawType;
5392
5393                 /**
5394                  * This parameterized type's owner type or {@code nullif no owner type exists.
5395                  */

5396                 private final Generic ownerType;
5397
5398                 /**
5399                  * The parameters of this parameterized type.
5400                  */

5401                 private final List<? extends Generic> parameters;
5402
5403                 /**
5404                  * The annotation source to query for the declared annotations.
5405                  */

5406                 private final AnnotationSource annotationSource;
5407
5408                 /**
5409                  * Creates a description of a latent parameterized type.
5410                  *
5411                  * @param rawType          The raw type of the described parameterized type.
5412                  * @param ownerType        This parameterized type's owner type or {@code nullif no owner type exists.
5413                  * @param parameters       The parameters of this parameterized type.
5414                  * @param annotationSource The annotation source to query for the declared annotations.
5415                  */

5416                 public Latent(TypeDescription rawType,
5417                               Generic ownerType,
5418                               List<? extends Generic> parameters,
5419                               AnnotationSource annotationSource) {
5420                     this.rawType = rawType;
5421                     this.ownerType = ownerType;
5422                     this.parameters = parameters;
5423                     this.annotationSource = annotationSource;
5424                 }
5425
5426                 /**
5427                  * {@inheritDoc}
5428                  */

5429                 public TypeDescription asErasure() {
5430                     return rawType;
5431                 }
5432
5433                 /**
5434                  * {@inheritDoc}
5435                  */

5436                 public Generic getOwnerType() {
5437                     return ownerType;
5438                 }
5439
5440                 /**
5441                  * {@inheritDoc}
5442                  */

5443                 public TypeList.Generic getTypeArguments() {
5444                     return new TypeList.Generic.Explicit(parameters);
5445                 }
5446
5447                 /**
5448                  * {@inheritDoc}
5449                  */

5450                 public AnnotationList getDeclaredAnnotations() {
5451                     return annotationSource.getDeclaredAnnotations();
5452                 }
5453             }
5454
5455             /**
5456              * A representation of a parameterized type that is a super type of a raw type but preserves the minimal type information
5457              * that is required for allowing creating correct erasures for overridden methods. All members' types are erased and all
5458              * type arguments are reduced to their erasure.
5459              */

5460             public static class ForReifiedType extends OfParameterizedType {
5461
5462                 /**
5463                  * The represented parameterized type.
5464                  */

5465                 private final Generic parameterizedType;
5466
5467                 /**
5468                  * Creates a new reified parameterized type.
5469                  *
5470                  * @param parameterizedType The represented parameterized type.
5471                  */

5472                 protected ForReifiedType(Generic parameterizedType) {
5473                     this.parameterizedType = parameterizedType;
5474                 }
5475
5476                 /**
5477                  * {@inheritDoc}
5478                  */

5479                 public Generic getSuperClass() {
5480                     Generic superClass = super.getSuperClass();
5481                     return superClass == null
5482                             ? Generic.UNDEFINED
5483                             : new LazyProjection.WithResolvedErasure(superClass, Visitor.Reifying.INHERITING);
5484                 }
5485
5486                 /**
5487                  * {@inheritDoc}
5488                  */

5489                 public TypeList.Generic getInterfaces() {
5490                     return new TypeList.Generic.ForDetachedTypes.WithResolvedErasure(super.getInterfaces(), Visitor.Reifying.INHERITING);
5491                 }
5492
5493                 /**
5494                  * {@inheritDoc}
5495                  */

5496                 public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
5497                     return new FieldList.TypeSubstituting(thissuper.getDeclaredFields(), Visitor.TypeErasing.INSTANCE);
5498                 }
5499
5500                 /**
5501                  * {@inheritDoc}
5502                  */

5503                 public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
5504                     return new MethodList.TypeSubstituting(thissuper.getDeclaredMethods(), Visitor.TypeErasing.INSTANCE);
5505                 }
5506
5507                 /**
5508                  * {@inheritDoc}
5509                  */

5510                 public TypeList.Generic getTypeArguments() {
5511                     return new TypeList.Generic.ForDetachedTypes(parameterizedType.getTypeArguments(), Visitor.TypeErasing.INSTANCE);
5512                 }
5513
5514                 /**
5515                  * {@inheritDoc}
5516                  */

5517                 public Generic getOwnerType() {
5518                     Generic ownerType = parameterizedType.getOwnerType();
5519                     return ownerType == null
5520                             ? Generic.UNDEFINED
5521                             : ownerType.accept(Visitor.Reifying.INHERITING);
5522                 }
5523
5524                 /**
5525                  * {@inheritDoc}
5526                  */

5527                 public TypeDescription asErasure() {
5528                     return parameterizedType.asErasure();
5529                 }
5530
5531                 /**
5532                  * {@inheritDoc}
5533                  */

5534                 public AnnotationList getDeclaredAnnotations() {
5535                     return new AnnotationList.Empty();
5536                 }
5537             }
5538
5539             /**
5540              * Represents an erasure as a generic type where all type variables are representing their own arguments.
5541              */

5542             public static class ForGenerifiedErasure extends OfParameterizedType {
5543
5544                 /**
5545                  * The represented erasure.
5546                  */

5547                 private final TypeDescription typeDescription;
5548
5549                 /**
5550                  * Creates a new generified erasure.
5551                  *
5552                  * @param typeDescription The represented erasure.
5553                  */

5554                 protected ForGenerifiedErasure(TypeDescription typeDescription) {
5555                     this.typeDescription = typeDescription;
5556                 }
5557
5558                 /**
5559                  * Represents the supplied type description as a generified erasure if it is generified or as a non-generic type if not so.
5560                  *
5561                  * @param typeDescription The represented erasure.
5562                  * @return An appropriate generic type.
5563                  */

5564                 public static Generic of(TypeDescription typeDescription) {
5565                     return typeDescription.isGenerified()
5566                             ? new ForGenerifiedErasure(typeDescription)
5567                             : new OfNonGenericType.ForErasure(typeDescription);
5568                 }
5569
5570                 /**
5571                  * {@inheritDoc}
5572                  */

5573                 public TypeDescription asErasure() {
5574                     return typeDescription;
5575                 }
5576
5577                 /**
5578                  * {@inheritDoc}
5579                  */

5580                 public TypeList.Generic getTypeArguments() {
5581                     return new TypeList.Generic.ForDetachedTypes(typeDescription.getTypeVariables(), Visitor.AnnotationStripper.INSTANCE);
5582                 }
5583
5584                 /**
5585                  * {@inheritDoc}
5586                  */

5587                 public Generic getOwnerType() {
5588                     TypeDescription declaringType = typeDescription.getDeclaringType();
5589                     return declaringType == null
5590                             ? Generic.UNDEFINED
5591                             : of(declaringType);
5592                 }
5593
5594                 /**
5595                  * {@inheritDoc}
5596                  */

5597                 public AnnotationList getDeclaredAnnotations() {
5598                     return new AnnotationList.Empty();
5599                 }
5600             }
5601         }
5602
5603         /**
5604          * A base implementation of a generic type description that represents a type variable.
5605          */

5606         abstract class OfTypeVariable extends AbstractBase {
5607
5608             /**
5609              * {@inheritDoc}
5610              */

5611             public Sort getSort() {
5612                 return Sort.VARIABLE;
5613             }
5614
5615             /**
5616              * {@inheritDoc}
5617              */

5618             public TypeDescription asErasure() {
5619                 TypeList.Generic upperBounds = getUpperBounds();
5620                 return upperBounds.isEmpty()
5621                         ? TypeDescription.OBJECT
5622                         : upperBounds.get(0).asErasure();
5623             }
5624
5625             /**
5626              * {@inheritDoc}
5627              */

5628             public Generic getSuperClass() {
5629                 throw new IllegalStateException("A type variable does not imply a super type definition: " + this);
5630             }
5631
5632             /**
5633              * {@inheritDoc}
5634              */

5635             public TypeList.Generic getInterfaces() {
5636                 throw new IllegalStateException("A type variable does not imply an interface type definition: " + this);
5637             }
5638
5639             /**
5640              * {@inheritDoc}
5641              */

5642             public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
5643                 throw new IllegalStateException("A type variable does not imply field definitions: " + this);
5644             }
5645
5646             /**
5647              * {@inheritDoc}
5648              */

5649             public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
5650                 throw new IllegalStateException("A type variable does not imply method definitions: " + this);
5651             }
5652
5653             /**
5654              * {@inheritDoc}
5655              */

5656             public RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents() {
5657                 throw new IllegalStateException("A type variable does not imply record component definitions: " + this);
5658             }
5659
5660             /**
5661              * {@inheritDoc}
5662              */

5663             public Generic getComponentType() {
5664                 throw new IllegalStateException("A type variable does not imply a component type: " + this);
5665             }
5666
5667             /**
5668              * {@inheritDoc}
5669              */

5670             public TypeList.Generic getTypeArguments() {
5671                 throw new IllegalStateException("A type variable does not imply type arguments: " + this);
5672             }
5673
5674             /**
5675              * {@inheritDoc}
5676              */

5677             public Generic findBindingOf(Generic typeVariable) {
5678                 throw new IllegalStateException("A type variable does not imply type arguments: " + this);
5679             }
5680
5681             /**
5682              * {@inheritDoc}
5683              */

5684             public TypeList.Generic getLowerBounds() {
5685                 throw new IllegalStateException("A type variable does not imply lower bounds: " + this);
5686             }
5687
5688             /**
5689              * {@inheritDoc}
5690              */

5691             public Generic getOwnerType() {
5692                 throw new IllegalStateException("A type variable does not imply an owner type: " + this);
5693             }
5694
5695             /**
5696              * {@inheritDoc}
5697              */

5698             public String getTypeName() {
5699                 return toString();
5700             }
5701
5702             /**
5703              * {@inheritDoc}
5704              */

5705             public String getActualName() {
5706                 return getSymbol();
5707             }
5708
5709             /**
5710              * {@inheritDoc}
5711              */

5712             public <T> T accept(Visitor<T> visitor) {
5713                 return visitor.onTypeVariable(this);
5714             }
5715
5716             /**
5717              * {@inheritDoc}
5718              */

5719             public StackSize getStackSize() {
5720                 return StackSize.SINGLE;
5721             }
5722
5723             /**
5724              * {@inheritDoc}
5725              */

5726             public boolean isArray() {
5727                 return false;
5728             }
5729
5730             /**
5731              * {@inheritDoc}
5732              */

5733             public boolean isPrimitive() {
5734                 return false;
5735             }
5736
5737             /**
5738              * {@inheritDoc}
5739              */

5740             public boolean isRecord() {
5741                 return false;
5742             }
5743
5744             /**
5745              * {@inheritDoc}
5746              */

5747             public boolean represents(java.lang.reflect.Type type) {
5748                 return equals(Sort.describe(type));
5749             }
5750
5751             /**
5752              * {@inheritDoc}
5753              */

5754             public Iterator<TypeDefinition> iterator() {
5755                 throw new IllegalStateException("A type variable does not imply a super type definition: " + this);
5756             }
5757
5758             @Override
5759             @CachedReturnPlugin.Enhance
5760             public int hashCode() {
5761                 return getTypeVariableSource().hashCode() ^ getSymbol().hashCode();
5762             }
5763
5764             @Override
5765             public boolean equals(Object other) {
5766                 if (this == other) {
5767                     return true;
5768                 } else if (!(other instanceof Generic)) {
5769                     return false;
5770                 }
5771                 Generic typeDescription = (Generic) other;
5772                 return typeDescription.getSort().isTypeVariable()
5773                         && getSymbol().equals(typeDescription.getSymbol())
5774                         && getTypeVariableSource().equals(typeDescription.getTypeVariableSource());
5775             }
5776
5777             @Override
5778             public String toString() {
5779                 return getSymbol();
5780             }
5781
5782             /**
5783              * Implementation of a symbolic type variable.
5784              */

5785             public static class Symbolic extends Generic.AbstractBase {
5786
5787                 /**
5788                  * The symbol of the symbolic type variable.
5789                  */

5790                 private final String symbol;
5791
5792                 /**
5793                  * The annotation source to query for the declared annotations.
5794                  */

5795                 private final AnnotationSource annotationSource;
5796
5797                 /**
5798                  * Creates a symbolic type variable.
5799                  *
5800                  * @param symbol           The symbol of the symbolic type variable.
5801                  * @param annotationSource The annotation source to query for the declared annotations.
5802                  */

5803                 public Symbolic(String symbol, AnnotationSource annotationSource) {
5804                     this.symbol = symbol;
5805                     this.annotationSource = annotationSource;
5806                 }
5807
5808                 /**
5809                  * {@inheritDoc}
5810                  */

5811                 public Sort getSort() {
5812                     return Sort.VARIABLE_SYMBOLIC;
5813                 }
5814
5815                 /**
5816                  * {@inheritDoc}
5817                  */

5818                 public String getSymbol() {
5819                     return symbol;
5820                 }
5821
5822                 /**
5823                  * {@inheritDoc}
5824                  */

5825                 public AnnotationList getDeclaredAnnotations() {
5826                     return annotationSource.getDeclaredAnnotations();
5827                 }
5828
5829                 /**
5830                  * {@inheritDoc}
5831                  */

5832                 public TypeDescription asErasure() {
5833                     throw new IllegalStateException("A symbolic type variable does not imply an erasure: " + this);
5834                 }
5835
5836                 /**
5837                  * {@inheritDoc}
5838                  */

5839                 public TypeList.Generic getUpperBounds() {
5840                     throw new IllegalStateException("A symbolic type variable does not imply an upper type bound: " + this);
5841                 }
5842
5843                 /**
5844                  * {@inheritDoc}
5845                  */

5846                 public TypeVariableSource getTypeVariableSource() {
5847                     throw new IllegalStateException("A symbolic type variable does not imply a variable source: " + this);
5848                 }
5849
5850                 /**
5851                  * {@inheritDoc}
5852                  */

5853                 public Generic getSuperClass() {
5854                     throw new IllegalStateException("A symbolic type variable does not imply a super type definition: " + this);
5855                 }
5856
5857                 /**
5858                  * {@inheritDoc}
5859                  */

5860                 public TypeList.Generic getInterfaces() {
5861                     throw new IllegalStateException("A symbolic type variable does not imply an interface type definition: " + this);
5862                 }
5863
5864                 /**
5865                  * {@inheritDoc}
5866                  */

5867                 public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
5868                     throw new IllegalStateException("A symbolic type variable does not imply field definitions: " + this);
5869                 }
5870
5871                 /**
5872                  * {@inheritDoc}
5873                  */

5874                 public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
5875                     throw new IllegalStateException("A symbolic type variable does not imply method definitions: " + this);
5876                 }
5877
5878                 /**
5879                  * {@inheritDoc}
5880                  */

5881                 public RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents() {
5882                     throw new IllegalStateException("A symbolic type variable does not imply record component definitions: " + this);
5883                 }
5884
5885                 /**
5886                  * {@inheritDoc}
5887                  */

5888                 public Generic getComponentType() {
5889                     throw new IllegalStateException("A symbolic type variable does not imply a component type: " + this);
5890                 }
5891
5892                 /**
5893                  * {@inheritDoc}
5894                  */

5895                 public TypeList.Generic getTypeArguments() {
5896                     throw new IllegalStateException("A symbolic type variable does not imply type arguments: " + this);
5897                 }
5898
5899                 /**
5900                  * {@inheritDoc}
5901                  */

5902                 public Generic findBindingOf(Generic typeVariable) {
5903                     throw new IllegalStateException("A symbolic type variable does not imply type arguments: " + this);
5904                 }
5905
5906                 /**
5907                  * {@inheritDoc}
5908                  */

5909                 public TypeList.Generic getLowerBounds() {
5910                     throw new IllegalStateException("A symbolic type variable does not imply lower bounds: " + this);
5911                 }
5912
5913                 /**
5914                  * {@inheritDoc}
5915                  */

5916                 public Generic getOwnerType() {
5917                     throw new IllegalStateException("A symbolic type variable does not imply an owner type: " + this);
5918                 }
5919
5920                 /**
5921                  * {@inheritDoc}
5922                  */

5923                 public String getTypeName() {
5924                     return toString();
5925                 }
5926
5927                 /**
5928                  * {@inheritDoc}
5929                  */

5930                 public String getActualName() {
5931                     return getSymbol();
5932                 }
5933
5934                 /**
5935                  * {@inheritDoc}
5936                  */

5937                 public <T> T accept(Visitor<T> visitor) {
5938                     return visitor.onTypeVariable(this);
5939                 }
5940
5941                 /**
5942                  * {@inheritDoc}
5943                  */

5944                 public StackSize getStackSize() {
5945                     return StackSize.SINGLE;
5946                 }
5947
5948                 /**
5949                  * {@inheritDoc}
5950                  */

5951                 public boolean isArray() {
5952                     return false;
5953                 }
5954
5955                 /**
5956                  * {@inheritDoc}
5957                  */

5958                 public boolean isPrimitive() {
5959                     return false;
5960                 }
5961
5962                 /**
5963                  * {@inheritDoc}
5964                  */

5965                 public boolean isRecord() {
5966                     return false;
5967                 }
5968
5969                 /**
5970                  * {@inheritDoc}
5971                  */

5972                 public boolean represents(java.lang.reflect.Type type) {
5973                     if (type == null) {
5974                         throw new NullPointerException();
5975                     }
5976                     return false;
5977                 }
5978
5979                 /**
5980                  * {@inheritDoc}
5981                  */

5982                 public Iterator<TypeDefinition> iterator() {
5983                     throw new IllegalStateException("A symbolic type variable does not imply a super type definition: " + this);
5984                 }
5985
5986                 @Override
5987                 public int hashCode() {
5988                     return symbol.hashCode();
5989                 }
5990
5991                 @Override
5992                 public boolean equals(Object other) {
5993                     if (this == other) {
5994                         return true;
5995                     } else if (!(other instanceof Generic)) {
5996                         return false;
5997                     }
5998                     Generic typeDescription = (Generic) other;
5999                     return typeDescription.getSort().isTypeVariable() && getSymbol().equals(typeDescription.getSymbol());
6000                 }
6001
6002                 @Override
6003                 public String toString() {
6004                     return getSymbol();
6005                 }
6006             }
6007
6008             /**
6009              * Description of a loaded type variable.
6010              */

6011             public static class ForLoadedType extends OfTypeVariable {
6012
6013                 /**
6014                  * The represented type variable.
6015                  */

6016                 private final TypeVariable<?> typeVariable;
6017
6018                 /**
6019                  * The annotation reader to query for the variable's annotations.
6020                  */

6021                 private final AnnotationReader annotationReader;
6022
6023                 /**
6024                  * Creates a description of a loaded type variable.
6025                  *
6026                  * @param typeVariable The represented type variable.
6027                  */

6028                 public ForLoadedType(TypeVariable<?> typeVariable) {
6029                     this(typeVariable, AnnotationReader.NoOp.INSTANCE);
6030                 }
6031
6032                 /**
6033                  * Creates a description of a loaded type variable with an annotation.
6034                  *
6035                  * @param typeVariable     The represented type variable.
6036                  * @param annotationReader The annotation reader to query for the variable's annotations.
6037                  */

6038                 protected ForLoadedType(TypeVariable<?> typeVariable, AnnotationReader annotationReader) {
6039                     this.typeVariable = typeVariable;
6040                     this.annotationReader = annotationReader;
6041                 }
6042
6043                 /**
6044                  * {@inheritDoc}
6045                  */

6046                 public TypeVariableSource getTypeVariableSource() {
6047                     GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
6048                     if (genericDeclaration instanceof Class) {
6049                         return TypeDescription.ForLoadedType.of((Class<?>) genericDeclaration);
6050                     } else if (genericDeclaration instanceof Method) {
6051                         return new MethodDescription.ForLoadedMethod((Method) genericDeclaration);
6052                     } else if (genericDeclaration instanceof Constructor) {
6053                         return new MethodDescription.ForLoadedConstructor((Constructor<?>) genericDeclaration);
6054                     } else {
6055                         throw new IllegalStateException("Unknown declaration: " + genericDeclaration);
6056                     }
6057                 }
6058
6059                 /**
6060                  * {@inheritDoc}
6061                  */

6062                 public TypeList.Generic getUpperBounds() {
6063                     return new TypeVariableBoundList(typeVariable.getBounds(), annotationReader);
6064                 }
6065
6066                 /**
6067                  * {@inheritDoc}
6068                  */

6069                 public String getSymbol() {
6070                     return typeVariable.getName();
6071                 }
6072
6073                 /**
6074                  * {@inheritDoc}
6075                  */

6076                 public AnnotationList getDeclaredAnnotations() {
6077                     return annotationReader.asList();
6078                 }
6079
6080                 /**
6081                  * {@inheritDoc}
6082                  */

6083                 public boolean represents(java.lang.reflect.Type type) {
6084                     return typeVariable == type || super.represents(type);
6085                 }
6086
6087                 /**
6088                  * A list of type variable bounds for a loaded {@link TypeVariable} that resolves annotations..
6089                  */

6090                 protected static class TypeVariableBoundList extends TypeList.Generic.AbstractBase {
6091
6092                     /**
6093                      * The type variable bounds.
6094                      */

6095                     private final java.lang.reflect.Type[] bound;
6096
6097                     /**
6098                      * The annotation reader to query for the type bounds.
6099                      */

6100                     private final AnnotationReader annotationReader;
6101
6102                     /**
6103                      * Creates a new list for a {@link TypeVariable}'s bound.
6104                      *
6105                      * @param bound            The type variable bounds.
6106                      * @param annotationReader The annotation reader to query for the type bounds.
6107                      */

6108                     protected TypeVariableBoundList(java.lang.reflect.Type[] bound, AnnotationReader annotationReader) {
6109                         this.bound = bound;
6110                         this.annotationReader = annotationReader;
6111                     }
6112
6113                     /**
6114                      * {@inheritDoc}
6115                      */

6116                     public Generic get(int index) {
6117                         return Sort.describe(bound[index], annotationReader.ofTypeVariableBoundType(index));
6118                     }
6119
6120                     /**
6121                      * {@inheritDoc}
6122                      */

6123                     public int size() {
6124                         return bound.length;
6125                     }
6126                 }
6127             }
6128
6129             /**
6130              * A type variable with explicit annotations that replace the annotations that are declared by the provided type variable.
6131              */

6132             public static class WithAnnotationOverlay extends OfTypeVariable {
6133
6134                 /**
6135                  * The type variable to represent.
6136                  */

6137                 private final Generic typeVariable;
6138
6139                 /**
6140                  * The annotation source to query for the declared annotations.
6141                  */

6142                 private final AnnotationSource annotationSource;
6143
6144                 /**
6145                  * Creates a new type definition for a type variable with explicit annotations.
6146                  *
6147                  * @param typeVariable     The type variable to represent.
6148                  * @param annotationSource The annotation source to query for the declared annotations.
6149                  */

6150                 public WithAnnotationOverlay(Generic typeVariable, AnnotationSource annotationSource) {
6151                     this.typeVariable = typeVariable;
6152                     this.annotationSource = annotationSource;
6153                 }
6154
6155                 /**
6156                  * {@inheritDoc}
6157                  */

6158                 public AnnotationList getDeclaredAnnotations() {
6159                     return annotationSource.getDeclaredAnnotations();
6160                 }
6161
6162                 /**
6163                  * {@inheritDoc}
6164                  */

6165                 public TypeList.Generic getUpperBounds() {
6166                     return typeVariable.getUpperBounds();
6167                 }
6168
6169                 /**
6170                  * {@inheritDoc}
6171                  */

6172                 public TypeVariableSource getTypeVariableSource() {
6173                     return typeVariable.getTypeVariableSource();
6174                 }
6175
6176                 /**
6177                  * {@inheritDoc}
6178                  */

6179                 public String getSymbol() {
6180                     return typeVariable.getSymbol();
6181                 }
6182             }
6183         }
6184
6185         /**
6186          * A lazy projection of a generic type. Such projections allow to only read generic type information in case it is required. This
6187          * is meaningful as the Java virtual needs to process generic type information which requires extra resources. Also, this allows
6188          * the extraction of non-generic type information even if the generic type information is invalid.
6189          */

6190         abstract class LazyProjection extends AbstractBase {
6191
6192             /**
6193              * Resolves the actual generic type.
6194              *
6195              * @return An actual description of the represented generic type.
6196              */

6197             protected abstract Generic resolve();
6198
6199             /**
6200              * {@inheritDoc}
6201              */

6202             public Sort getSort() {
6203                 return resolve().getSort();
6204             }
6205
6206             /**
6207              * {@inheritDoc}
6208              */

6209             public FieldList<FieldDescription.InGenericShape> getDeclaredFields() {
6210                 return resolve().getDeclaredFields();
6211             }
6212
6213             /**
6214              * {@inheritDoc}
6215              */

6216             public MethodList<MethodDescription.InGenericShape> getDeclaredMethods() {
6217                 return resolve().getDeclaredMethods();
6218             }
6219
6220             /**
6221              * {@inheritDoc}
6222              */

6223             public RecordComponentList<RecordComponentDescription.InGenericShape> getRecordComponents() {
6224                 return resolve().getRecordComponents();
6225             }
6226
6227             /**
6228              * {@inheritDoc}
6229              */

6230             public TypeList.Generic getUpperBounds() {
6231                 return resolve().getUpperBounds();
6232             }
6233
6234             /**
6235              * {@inheritDoc}
6236              */

6237             public TypeList.Generic getLowerBounds() {
6238                 return resolve().getLowerBounds();
6239             }
6240
6241             /**
6242              * {@inheritDoc}
6243              */

6244             public Generic getComponentType() {
6245                 return resolve().getComponentType();
6246             }
6247
6248             /**
6249              * {@inheritDoc}
6250              */

6251             public TypeList.Generic getTypeArguments() {
6252                 return resolve().getTypeArguments();
6253             }
6254
6255             /**
6256              * {@inheritDoc}
6257              */

6258             public Generic findBindingOf(Generic typeVariable) {
6259                 return resolve().findBindingOf(typeVariable);
6260             }
6261
6262             /**
6263              * {@inheritDoc}
6264              */

6265             public TypeVariableSource getTypeVariableSource() {
6266                 return resolve().getTypeVariableSource();
6267             }
6268
6269             /**
6270              * {@inheritDoc}
6271              */

6272             public Generic getOwnerType() {
6273                 return resolve().getOwnerType();
6274             }
6275
6276             /**
6277              * {@inheritDoc}
6278              */

6279             public String getTypeName() {
6280                 return resolve().getTypeName();
6281             }
6282
6283             /**
6284              * {@inheritDoc}
6285              */

6286             public String getSymbol() {
6287                 return resolve().getSymbol();
6288             }
6289
6290             /**
6291              * {@inheritDoc}
6292              */

6293             public String getActualName() {
6294                 return resolve().getActualName();
6295             }
6296
6297             /**
6298              * {@inheritDoc}
6299              */

6300             public <T> T accept(Visitor<T> visitor) {
6301                 return resolve().accept(visitor);
6302             }
6303
6304             /**
6305              * {@inheritDoc}
6306              */

6307             public StackSize getStackSize() {
6308                 return asErasure().getStackSize();
6309             }
6310
6311             /**
6312              * {@inheritDoc}
6313              */

6314             public boolean isArray() {
6315                 return asErasure().isArray();
6316             }
6317
6318             /**
6319              * {@inheritDoc}
6320              */

6321             public boolean isPrimitive() {
6322                 return asErasure().isPrimitive();
6323             }
6324
6325             /**
6326              * {@inheritDoc}
6327              */

6328             public boolean isRecord() {
6329                 return asErasure().isRecord();
6330             }
6331
6332             /**
6333              * {@inheritDoc}
6334              */

6335             public boolean represents(java.lang.reflect.Type type) {
6336                 return resolve().represents(type);
6337             }
6338
6339             @Override
6340             @CachedReturnPlugin.Enhance
6341             public int hashCode() {
6342                 return resolve().hashCode();
6343             }
6344
6345             @Override
6346             public boolean equals(Object other) {
6347                 return this == other || other instanceof TypeDefinition && resolve().equals(other);
6348             }
6349
6350             @Override
6351             public String toString() {
6352                 return resolve().toString();
6353             }
6354
6355             /**
6356              * A lazy projection of a type with a lazy resolution of super class and interface types. A lazy navigation
6357              * must only be used for describing types that are guaranteed to define a super class and interface types,
6358              * i.e. non-generic types and parameterized types. Lazy navigation can also be applied to array types where
6359              * the usage does however make little sense as those properties are never generic.
6360              */

6361             public abstract static class WithLazyNavigation extends LazyProjection {
6362
6363                 /**
6364                  * {@inheritDoc}
6365                  */

6366                 public Generic getSuperClass() {
6367                     return LazySuperClass.of(this);
6368                 }
6369
6370                 /**
6371                  * {@inheritDoc}
6372                  */

6373                 public TypeList.Generic getInterfaces() {
6374                     return LazyInterfaceList.of(this);
6375                 }
6376
6377                 /**
6378                  * {@inheritDoc}
6379                  */

6380                 public Iterator<TypeDefinition> iterator() {
6381                     return new TypeDefinition.SuperClassIterator(this);
6382                 }
6383
6384                 /**
6385                  * A lazy super class description for a lazy projection.
6386                  */

6387                 protected static class LazySuperClass extends WithLazyNavigation {
6388
6389                     /**
6390                      * The lazy projection for which this description is a delegate.
6391                      */

6392                     private final LazyProjection delegate;
6393
6394                     /**
6395                      * Creates a new lazy super class description.
6396                      *
6397                      * @param delegate The lazy projection for which this description is a delegate.
6398                      */

6399                     protected LazySuperClass(LazyProjection delegate) {
6400                         this.delegate = delegate;
6401                     }
6402
6403                     /**
6404                      * Resolves a lazy super class description.
6405                      *
6406                      * @param delegate The lazy projection for which this description is a delegate.
6407                      * @return A lazy description of the super class or {@code nullif the delegate does not define a super class.
6408                      */

6409                     protected static Generic of(LazyProjection delegate) {
6410                         return delegate.asErasure().getSuperClass() == null
6411                                 ? Generic.UNDEFINED
6412                                 : new LazySuperClass(delegate);
6413                     }
6414
6415                     /**
6416                      * {@inheritDoc}
6417                      */

6418                     public AnnotationList getDeclaredAnnotations() {
6419                         return resolve().getDeclaredAnnotations();
6420                     }
6421
6422                     /**
6423                      * {@inheritDoc}
6424                      */

6425                     public TypeDescription asErasure() {
6426                         return delegate.asErasure().getSuperClass().asErasure();
6427                     }
6428
6429                     @Override
6430                     @CachedReturnPlugin.Enhance("resolved")
6431                     protected Generic resolve() {
6432                         return delegate.resolve().getSuperClass();
6433                     }
6434                 }
6435
6436                 /**
6437                  * A lazy interface type description for a lazy projection.
6438                  */

6439                 protected static class LazyInterfaceType extends WithLazyNavigation {
6440
6441                     /**
6442                      * The lazy projection for which this description is a delegate.
6443                      */

6444                     private final LazyProjection delegate;
6445
6446                     /**
6447                      * The index of the interface in question.
6448                      */

6449                     private final int index;
6450
6451                     /**
6452                      * The raw interface that is declared by the erasure of the represented lazy projection.
6453                      */

6454                     private final TypeDescription.Generic rawInterface;
6455
6456                     /**
6457                      * Creates a new lazy interface type.
6458                      *
6459                      * @param delegate     The lazy projection for which this description is a delegate.
6460                      * @param index        The index of the interface in question.
6461                      * @param rawInterface The raw interface that is declared by the erasure of the represented lazy projection.
6462                      */

6463                     protected LazyInterfaceType(LazyProjection delegate, int index, Generic rawInterface) {
6464                         this.delegate = delegate;
6465                         this.index = index;
6466                         this.rawInterface = rawInterface;
6467                     }
6468
6469                     /**
6470                      * {@inheritDoc}
6471                      */

6472                     public AnnotationList getDeclaredAnnotations() {
6473                         return resolve().getDeclaredAnnotations();
6474                     }
6475
6476                     /**
6477                      * {@inheritDoc}
6478                      */

6479                     public TypeDescription asErasure() {
6480                         return rawInterface.asErasure();
6481                     }
6482
6483                     @Override
6484                     @CachedReturnPlugin.Enhance("resolved")
6485                     protected Generic resolve() {
6486                         return delegate.resolve().getInterfaces().get(index);
6487                     }
6488                 }
6489
6490                 /**
6491                  * A lazy representation of a lazy projection's interfaces.
6492                  */

6493                 protected static class LazyInterfaceList extends TypeList.Generic.AbstractBase {
6494
6495                     /**
6496                      * The lazy projection for which this description is a delegate.
6497                      */

6498                     private final LazyProjection delegate;
6499
6500                     /**
6501                      * A list of raw interface types declared by the lazy projection's erasure.
6502                      */

6503                     private final TypeList.Generic rawInterfaces;
6504
6505                     /**
6506                      * Creates a new lazy interface list.
6507                      *
6508                      * @param delegate      The lazy projection for which this description is a delegate.
6509                      * @param rawInterfaces A list of raw interface types declared by the lazy projection's erasure.
6510                      */

6511                     protected LazyInterfaceList(LazyProjection delegate, TypeList.Generic rawInterfaces) {
6512                         this.delegate = delegate;
6513                         this.rawInterfaces = rawInterfaces;
6514                     }
6515
6516                     /**
6517                      * Resolves a lazy interface list.
6518                      *
6519                      * @param delegate The delegate for which to represent interfaces.
6520                      * @return A lazy list representing the delegate's interfaces lazily.
6521                      */

6522                     protected static TypeList.Generic of(LazyProjection delegate) {
6523                         return new LazyInterfaceList(delegate, delegate.asErasure().getInterfaces());
6524                     }
6525
6526                     /**
6527                      * {@inheritDoc}
6528                      */

6529                     public Generic get(int index) {
6530                         return new LazyInterfaceType(delegate, index, rawInterfaces.get(index));
6531                     }
6532
6533                     /**
6534                      * {@inheritDoc}
6535                      */

6536                     public int size() {
6537                         return rawInterfaces.size();
6538                     }
6539                 }
6540
6541                 /**
6542                  * A description of an annotated lazy type with lazy navigation.
6543                  */

6544                 protected abstract static class OfAnnotatedElement extends WithLazyNavigation {
6545
6546                     /**
6547                      * Returns the current type's annotation reader.
6548                      *
6549                      * @return The current type's annotation reader.
6550                      */

6551                     protected abstract AnnotationReader getAnnotationReader();
6552
6553                     /**
6554                      * {@inheritDoc}
6555                      */

6556                     public AnnotationList getDeclaredAnnotations() {
6557                         return getAnnotationReader().asList();
6558                     }
6559                 }
6560             }
6561
6562             /**
6563              * A lazy projection of a type that resolves super class and interface types eagerly.
6564              */

6565             public abstract static class WithEagerNavigation extends LazyProjection {
6566
6567                 /**
6568                  * {@inheritDoc}
6569                  */

6570                 public Generic getSuperClass() {
6571                     return resolve().getSuperClass();
6572                 }
6573
6574                 /**
6575                  * {@inheritDoc}
6576                  */

6577                 public TypeList.Generic getInterfaces() {
6578                     return resolve().getInterfaces();
6579                 }
6580
6581                 /**
6582                  * {@inheritDoc}
6583                  */

6584                 public Iterator<TypeDefinition> iterator() {
6585                     return resolve().iterator();
6586                 }
6587
6588                 /**
6589                  * A description of an annotated lazy type with eager navigation.
6590                  */

6591                 protected abstract static class OfAnnotatedElement extends WithEagerNavigation {
6592
6593                     /**
6594                      * Returns the current type's annotation reader.
6595                      *
6596                      * @return The current type's annotation reader.
6597                      */

6598                     protected abstract AnnotationReader getAnnotationReader();
6599
6600                     /**
6601                      * {@inheritDoc}
6602                      */

6603                     public AnnotationList getDeclaredAnnotations() {
6604                         return getAnnotationReader().asList();
6605                     }
6606                 }
6607             }
6608
6609             /**
6610              * A lazy projection of a generic super type.
6611              */

6612             public static class ForLoadedSuperClass extends LazyProjection.WithLazyNavigation.OfAnnotatedElement {
6613
6614                 /**
6615                  * The type of which the super class is represented.
6616                  */

6617                 private final Class<?> type;
6618
6619                 /**
6620                  * Creates a new lazy projection of a type's super class.
6621                  *
6622                  * @param type The type of which the super class is represented.
6623                  */

6624                 public ForLoadedSuperClass(Class<?> type) {
6625                     this.type = type;
6626                 }
6627
6628                 /**
6629                  * {@inheritDoc}
6630                  */

6631                 @CachedReturnPlugin.Enhance("resolved")
6632                 protected Generic resolve() {
6633                     java.lang.reflect.Type superClass = type.getGenericSuperclass();
6634                     return superClass == null
6635                             ? Generic.UNDEFINED
6636                             : Sort.describe(superClass, getAnnotationReader());
6637                 }
6638
6639                 /**
6640                  * {@inheritDoc}
6641                  */

6642                 public TypeDescription asErasure() {
6643                     Class<?> superClass = type.getSuperclass();
6644                     return superClass == null
6645                             ? TypeDescription.UNDEFINED
6646                             : ForLoadedType.of(superClass);
6647                 }
6648
6649                 @Override
6650                 protected AnnotationReader getAnnotationReader() {
6651                     return AnnotationReader.DISPATCHER.resolveSuperClassType(type);
6652                 }
6653             }
6654
6655             /**
6656              * A lazy projection of a field's type.
6657              */

6658             public static class ForLoadedFieldType extends LazyProjection.WithEagerNavigation.OfAnnotatedElement {
6659
6660                 /**
6661                  * The field of which the type is represented.
6662                  */

6663                 private final Field field;
6664
6665                 /**
6666                  * Create's a lazy projection of a field type.
6667                  *
6668                  * @param field The field of which the type is represented.
6669                  */

6670                 public ForLoadedFieldType(Field field) {
6671                     this.field = field;
6672                 }
6673
6674                 @Override
6675                 @CachedReturnPlugin.Enhance("resolved")
6676                 protected Generic resolve() {
6677                     return Sort.describe(field.getGenericType(), getAnnotationReader());
6678                 }
6679
6680                 /**
6681                  * {@inheritDoc}
6682                  */

6683                 public TypeDescription asErasure() {
6684                     return ForLoadedType.of(field.getType());
6685                 }
6686
6687                 @Override
6688                 protected AnnotationReader getAnnotationReader() {
6689                     return AnnotationReader.DISPATCHER.resolveFieldType(field);
6690                 }
6691             }
6692
6693             /**
6694              * A lazy projection of a method's generic return type.
6695              */

6696             public static class ForLoadedReturnType extends LazyProjection.WithEagerNavigation.OfAnnotatedElement {
6697
6698                 /**
6699                  * The method which defines the return type.
6700                  */

6701                 private final Method method;
6702
6703                 /**
6704                  * Creates a new lazy projection of a method's return type.
6705                  *
6706                  * @param method The method which defines the return type.
6707                  */

6708                 public ForLoadedReturnType(Method method) {
6709                     this.method = method;
6710                 }
6711
6712                 @Override
6713                 @CachedReturnPlugin.Enhance("resolved")
6714                 protected Generic resolve() {
6715                     return Sort.describe(method.getGenericReturnType(), getAnnotationReader());
6716                 }
6717
6718                 /**
6719                  * {@inheritDoc}
6720                  */

6721                 public TypeDescription asErasure() {
6722                     return ForLoadedType.of(method.getReturnType());
6723                 }
6724
6725                 @Override
6726                 protected AnnotationReader getAnnotationReader() {
6727                     return AnnotationReader.DISPATCHER.resolveReturnType(method);
6728                 }
6729             }
6730
6731             /**
6732              * A lazy projection of the parameter type of a {@link Constructor}.
6733              */

6734             public static class OfConstructorParameter extends LazyProjection.WithEagerNavigation.OfAnnotatedElement {
6735
6736                 /**
6737                  * The constructor of which a parameter type is represented.
6738                  */

6739                 private final Constructor<?> constructor;
6740
6741                 /**
6742                  * The parameter's index.
6743                  */

6744                 private final int index;
6745
6746                 /**
6747                  * The erasure of the parameter type.
6748                  */

6749                 private final Class<?>[] erasure;
6750
6751                 /**
6752                  * Creates a lazy projection of a constructor's parameter.
6753                  *
6754                  * @param constructor The constructor of which a parameter type is represented.
6755                  * @param index       The parameter's index.
6756                  * @param erasure     The erasure of the parameter type.
6757                  */

6758                 @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "The array is never exposed outside of the class")
6759                 public OfConstructorParameter(Constructor<?> constructor, int index, Class<?>[] erasure) {
6760                     this.constructor = constructor;
6761                     this.index = index;
6762                     this.erasure = erasure;
6763                 }
6764
6765                 @Override
6766                 @CachedReturnPlugin.Enhance("delegate")
6767                 protected Generic resolve() {
6768                     java.lang.reflect.Type[] type = constructor.getGenericParameterTypes();
6769                     return erasure.length == type.length
6770                             ? Sort.describe(type[index], getAnnotationReader())
6771                             : OfNonGenericType.ForLoadedType.of(erasure[index]);
6772                 }
6773
6774                 /**
6775                  * {@inheritDoc}
6776                  */

6777                 public TypeDescription asErasure() {
6778                     return TypeDescription.ForLoadedType.of(erasure[index]);
6779                 }
6780
6781                 @Override
6782                 protected AnnotationReader getAnnotationReader() {
6783                     return AnnotationReader.DISPATCHER.resolveParameterType(constructor, index);
6784                 }
6785             }
6786
6787             /**
6788              * A lazy projection of the parameter type of a {@link Method}.
6789              */

6790             public static class OfMethodParameter extends LazyProjection.WithEagerNavigation.OfAnnotatedElement {
6791
6792                 /**
6793                  * The method of which a parameter type is represented.
6794                  */

6795                 private final Method method;
6796
6797                 /**
6798                  * The parameter's index.
6799                  */

6800                 private final int index;
6801
6802                 /**
6803                  * The erasures of the method's parameter types.
6804                  */

6805                 private final Class<?>[] erasure;
6806
6807                 /**
6808                  * Creates a lazy projection of a constructor's parameter.
6809                  *
6810                  * @param method  The method of which a parameter type is represented.
6811                  * @param index   The parameter's index.
6812                  * @param erasure The erasures of the method's parameter types.
6813                  */

6814                 @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "The array is never exposed outside of the class")
6815                 public OfMethodParameter(Method method, int index, Class<?>[] erasure) {
6816                     this.method = method;
6817                     this.index = index;
6818                     this.erasure = erasure;
6819                 }
6820
6821                 @Override
6822                 @CachedReturnPlugin.Enhance("resolved")
6823                 protected Generic resolve() {
6824                     java.lang.reflect.Type[] type = method.getGenericParameterTypes();
6825                     return erasure.length == type.length
6826                             ? Sort.describe(type[index], getAnnotationReader())
6827                             : OfNonGenericType.ForLoadedType.of(erasure[index]);
6828                 }
6829
6830                 /**
6831                  * {@inheritDoc}
6832                  */

6833                 public TypeDescription asErasure() {
6834                     return TypeDescription.ForLoadedType.of(erasure[index]);
6835                 }
6836
6837                 @Override
6838                 protected AnnotationReader getAnnotationReader() {
6839                     return AnnotationReader.DISPATCHER.resolveParameterType(method, index);
6840                 }
6841             }
6842
6843             /**
6844              * A lazy projection of a {@code java.lang.reflect.RecordComponent}'s type.
6845              */

6846             public static class OfRecordComponent extends LazyProjection.WithEagerNavigation.OfAnnotatedElement {
6847
6848                 /**
6849                  * The represented record component.
6850                  */

6851                 private final Object recordComponent;
6852
6853                 /**
6854                  * Creates a lazy projection of a {@code java.lang.reflect.RecordComponent}'s type.
6855                  *
6856                  * @param recordComponent The represented record component.
6857                  */

6858                 protected OfRecordComponent(Object recordComponent) {
6859                     this.recordComponent = recordComponent;
6860                 }
6861
6862                 @Override
6863                 @CachedReturnPlugin.Enhance("resolved")
6864                 protected Generic resolve() {
6865                     return Sort.describe(RecordComponentDescription.ForLoadedRecordComponent.DISPATCHER.getGenericType(recordComponent), getAnnotationReader());
6866                 }
6867
6868                 @Override
6869                 public TypeDescription asErasure() {
6870                     return ForLoadedType.of(RecordComponentDescription.ForLoadedRecordComponent.DISPATCHER.getType(recordComponent));
6871                 }
6872
6873                 @Override
6874                 protected AnnotationReader getAnnotationReader() {
6875                     return new AnnotationReader.Delegator.ForRecordComponent(recordComponent);
6876                 }
6877             }
6878
6879             /**
6880              * A lazy projection that applies a visitor only when resolving the generic type but not when reading the erasure.
6881              */

6882             public static class WithResolvedErasure extends LazyProjection.WithEagerNavigation {
6883
6884                 /**
6885                  * The unresolved generic type.
6886                  */

6887                 private final Generic delegate;
6888
6889                 /**
6890                  * The visitor to apply for resolving the generic type.
6891                  */

6892                 private final Visitor<? extends Generic> visitor;
6893
6894                 /**
6895                  * The annotation source to apply.
6896                  */

6897                 private final AnnotationSource annotationSource;
6898
6899                 /**
6900                  * Creates a lazy projection with a resolved erasure that retains the delegates type annotations.
6901                  *
6902                  * @param delegate The unresolved generic type.
6903                  * @param visitor  The visitor to apply for resolving the generic type.
6904                  */

6905                 public WithResolvedErasure(Generic delegate, Visitor<? extends Generic> visitor) {
6906                     this(delegate, visitor, delegate);
6907                 }
6908
6909                 /**
6910                  * Creates a lazy projection with a resolved erasure.
6911                  *
6912                  * @param delegate         The unresolved generic type.
6913                  * @param visitor          The visitor to apply for resolving the generic type.
6914                  * @param annotationSource The annotation source representing this type's type annotations.
6915                  */

6916                 public WithResolvedErasure(Generic delegate, Visitor<? extends Generic> visitor, AnnotationSource annotationSource) {
6917                     this.delegate = delegate;
6918                     this.visitor = visitor;
6919                     this.annotationSource = annotationSource;
6920                 }
6921
6922                 /**
6923                  * {@inheritDoc}
6924                  */

6925                 public AnnotationList getDeclaredAnnotations() {
6926                     return annotationSource.getDeclaredAnnotations();
6927                 }
6928
6929                 /**
6930                  * {@inheritDoc}
6931                  */

6932                 public TypeDescription asErasure() {
6933                     return delegate.asErasure();
6934                 }
6935
6936                 @Override
6937                 @CachedReturnPlugin.Enhance("resolved")
6938                 protected Generic resolve() {
6939                     return delegate.accept(visitor);
6940                 }
6941             }
6942         }
6943
6944         /**
6945          * A builder for creating describing a generic type as a {@link Generic}.
6946          */

6947         @HashCodeAndEqualsPlugin.Enhance
6948         abstract class Builder {
6949
6950             /**
6951              * Represents an undefined {@link java.lang.reflect.Type} within a build step.
6952              */

6953             private static final java.lang.reflect.Type UNDEFINED = null;
6954
6955             /**
6956              * The type annotations of the current annotated type.
6957              */

6958             protected final List<? extends AnnotationDescription> annotations;
6959
6960             /**
6961              * Creates a new builder for a generic type description.
6962              *
6963              * @param annotations The type annotations of the current annotated type.
6964              */

6965             protected Builder(List<? extends AnnotationDescription> annotations) {
6966                 this.annotations = annotations;
6967             }
6968
6969             /**
6970              * Creates a raw type of a type description.
6971              *
6972              * @param type The type to represent as a raw type.
6973              * @return A builder for creating a raw type.
6974              */

6975             public static Builder rawType(Class<?> type) {
6976                 return rawType(ForLoadedType.of(type));
6977             }
6978
6979             /**
6980              * Creates a raw type of a type description.
6981              *
6982              * @param type The type to represent as a raw type.
6983              * @return A builder for creating a raw type.
6984              */

6985             public static Builder rawType(TypeDescription type) {
6986                 return new Builder.OfNonGenericType(type);
6987             }
6988
6989             /**
6990              * Creates a raw type of a type description where the supplied owner type is used as .
6991              *
6992              * @param type      The type to represent as a raw type.
6993              * @param ownerType The raw type's (annotated) declaring type or {@code nullif no owner type should be declared.
6994              * @return A builder for creating a raw type.
6995              */

6996             public static Builder rawType(Class<?> type, Generic ownerType) {
6997                 return rawType(ForLoadedType.of(type), ownerType);
6998             }
6999
7000             /**
7001              * Creates a raw type of a type description.
7002              *
7003              * @param type      The type to represent as a raw type.
7004              * @param ownerType The raw type's (annotated) declaring type or {@code nullif no owner type should be declared.
7005              * @return A builder for creating a raw type.
7006              */

7007             public static Builder rawType(TypeDescription type, Generic ownerType) {
7008                 TypeDescription declaringType = type.getDeclaringType();
7009                 if (declaringType == null && ownerType != null) {
7010                     throw new IllegalArgumentException(type + " does not have a declaring type: " + ownerType);
7011                 } else if (declaringType != null && (ownerType == null || !declaringType.equals(ownerType.asErasure()))) {
7012                     throw new IllegalArgumentException(ownerType + " is not the declaring type of " + type);
7013                 }
7014                 return new Builder.OfNonGenericType(type, ownerType);
7015             }
7016
7017             /**
7018              * Creates an unbound wildcard without type annotations.
7019              *
7020              * @return A description of an unbound wildcard without type annotations.
7021              */

7022             public static Generic unboundWildcard() {
7023                 return unboundWildcard(Collections.<AnnotationDescription>emptySet());
7024             }
7025
7026             /**
7027              * Creates an unbound wildcard.
7028              *
7029              * @param annotation The type annotations of the unbound wildcard.
7030              * @return A description of an unbound wildcard.
7031              */

7032             public static Generic unboundWildcard(Annotation... annotation) {
7033                 return unboundWildcard(Arrays.asList(annotation));
7034             }
7035
7036             /**
7037              * Creates an unbound wildcard.
7038              *
7039              * @param annotations The type annotations of the unbound wildcard.
7040              * @return A description of an unbound wildcard.
7041              */

7042             public static Generic unboundWildcard(List<? extends Annotation> annotations) {
7043                 return unboundWildcard(new AnnotationList.ForLoadedAnnotations(annotations));
7044             }
7045
7046             /**
7047              * Creates an unbound wildcard.
7048              *
7049              * @param annotation The type annotations of the unbound wildcard.
7050              * @return A description of an unbound wildcard.
7051              */

7052             public static Generic unboundWildcard(AnnotationDescription... annotation) {
7053                 return unboundWildcard(Arrays.asList(annotation));
7054             }
7055
7056             /**
7057              * Creates an unbound wildcard.
7058              *
7059              * @param annotations The type annotations of the unbound wildcard.
7060              * @return A description of an unbound wildcard.
7061              */

7062             public static Generic unboundWildcard(Collection<? extends AnnotationDescription> annotations) {
7063                 return OfWildcardType.Latent.unbounded(new Explicit(new ArrayList<AnnotationDescription>(annotations)));
7064             }
7065
7066             /**
7067              * Creates a symbolic type variable of the given name.
7068              *
7069              * @param symbol The symbolic name of the type variable.
7070              * @return A builder for creating a type variable.
7071              */

7072             public static Builder typeVariable(String symbol) {
7073                 return new OfTypeVariable(symbol);
7074             }
7075
7076             /**
7077              * Creates a parameterized type without an owner type or with a non-generic owner type.
7078              *
7079              * @param rawType   A raw version of the type to describe as a parameterized type.
7080              * @param parameter The type arguments to attach to the raw type as parameters.
7081              * @return A builder for creating a parameterized type.
7082              */

7083             public static Builder parameterizedType(Class<?> rawType, java.lang.reflect.Type... parameter) {
7084                 return parameterizedType(rawType, Arrays.asList(parameter));
7085             }
7086
7087             /**
7088              * Creates a parameterized type without an owner type or with a non-generic owner type.
7089              *
7090              * @param rawType    A raw version of the type to describe as a parameterized type.
7091              * @param parameters The type arguments to attach to the raw type as parameters.
7092              * @return A builder for creating a parameterized type.
7093              */

7094             public static Builder parameterizedType(Class<?> rawType, List<? extends java.lang.reflect.Type> parameters) {
7095                 return parameterizedType(rawType, UNDEFINED, parameters);
7096             }
7097
7098             /**
7099              * Creates a parameterized type.
7100              *
7101              * @param rawType    A raw version of the type to describe as a parameterized type.
7102              * @param ownerType  The owner type of the parameterized type.
7103              * @param parameters The type arguments to attach to the raw type as parameters.
7104              * @return A builder for creating a parameterized type.
7105              */

7106             public static Builder parameterizedType(Class<?> rawType, java.lang.reflect.Type ownerType, List<? extends java.lang.reflect.Type> parameters) {
7107                 return parameterizedType(ForLoadedType.of(rawType),
7108                         ownerType == null
7109                                 ? null
7110                                 : Sort.describe(ownerType),
7111                         new TypeList.Generic.ForLoadedTypes(parameters));
7112             }
7113
7114             /**
7115              * Creates a parameterized type without an owner type or with a non-generic owner type.
7116              *
7117              * @param rawType   A raw version of the type to describe as a parameterized type.
7118              * @param parameter The type arguments to attach to the raw type as parameters.
7119              * @return A builder for creating a parameterized type.
7120              */

7121             public static Builder parameterizedType(TypeDescription rawType, TypeDefinition... parameter) {
7122                 return parameterizedType(rawType, Arrays.asList(parameter));
7123             }
7124
7125             /**
7126              * Creates a parameterized type without an owner type or with a non-generic owner type.
7127              *
7128              * @param rawType    A raw version of the type to describe as a parameterized type.
7129              * @param parameters The type arguments to attach to the raw type as parameters.
7130              * @return A builder for creating a parameterized type.
7131              */

7132             public static Builder parameterizedType(TypeDescription rawType, Collection<? extends TypeDefinition> parameters) {
7133                 return parameterizedType(rawType, Generic.UNDEFINED, parameters);
7134             }
7135
7136             /**
7137              * Creates a parameterized type.
7138              *
7139              * @param rawType    A raw version of the type to describe as a parameterized type.
7140              * @param ownerType  The owner type of the parameterized type.
7141              * @param parameters The type arguments to attach to the raw type as parameters.
7142              * @return A builder for creating a parameterized type.
7143              */

7144             public static Builder parameterizedType(TypeDescription rawType, Generic ownerType, Collection<? extends TypeDefinition> parameters) {
7145                 TypeDescription declaringType = rawType.getDeclaringType();
7146                 if (ownerType == null && declaringType != null && rawType.isStatic()) {
7147                     ownerType = declaringType.asGenericType();
7148                 }
7149                 if (!rawType.represents(TargetType.class)) {
7150                     if (!rawType.isGenerified()) {
7151                         throw new IllegalArgumentException(rawType + " is not a parameterized type");
7152                     } else if (ownerType == null && declaringType != null && !rawType.isStatic()) {
7153                         throw new IllegalArgumentException(rawType + " requires an owner type");
7154                     } else if (ownerType != null && !ownerType.asErasure().equals(declaringType)) {
7155                         throw new IllegalArgumentException(ownerType + " does not represent required owner for " + rawType);
7156                     } else if (ownerType != null && (rawType.isStatic() ^ ownerType.getSort().isNonGeneric())) {
7157                         throw new IllegalArgumentException(ownerType + " does not define the correct parameters for owning " + rawType);
7158                     } else if (rawType.getTypeVariables().size() != parameters.size()) {
7159                         throw new IllegalArgumentException(parameters + " does not contain number of required parameters for " + rawType);
7160                     }
7161                 }
7162                 return new Builder.OfParameterizedType(rawType, ownerType, new TypeList.Generic.Explicit(new ArrayList<TypeDefinition>(parameters)));
7163             }
7164
7165             /**
7166              * Transforms this type into the upper bound of a wildcard type.
7167              *
7168              * @return A generic type description of a wildcard type with this builder's type as an upper bound.
7169              */

7170             public Generic asWildcardUpperBound() {
7171                 return asWildcardUpperBound(Collections.<AnnotationDescription>emptySet());
7172             }
7173
7174             /**
7175              * Transforms this type into the upper bound of a wildcard type.
7176              *
7177              * @param annotation Type annotations to be declared by the wildcard type.
7178              * @return A generic type description of a wildcard type with this builder's type as an upper bound.
7179              */

7180             public Generic asWildcardUpperBound(Annotation... annotation) {
7181                 return asWildcardUpperBound(Arrays.asList(annotation));
7182             }
7183
7184             /**
7185              * Transforms this type into the upper bound of a wildcard type.
7186              *
7187              * @param annotations Type annotations to be declared by the wildcard type.
7188              * @return A generic type description of a wildcard type with this builder's type as an upper bound.
7189              */

7190             public Generic asWildcardUpperBound(List<? extends Annotation> annotations) {
7191                 return asWildcardUpperBound(new AnnotationList.ForLoadedAnnotations(annotations));
7192             }
7193
7194             /**
7195              * Transforms this type into the upper bound of a wildcard type.
7196              *
7197              * @param annotation Type annotations to be declared by the wildcard type.
7198              * @return A generic type description of a wildcard type with this builder's type as an upper bound.
7199              */

7200             public Generic asWildcardUpperBound(AnnotationDescription... annotation) {
7201                 return asWildcardUpperBound(Arrays.asList(annotation));
7202             }
7203
7204             /**
7205              * Transforms this type into the upper bound of a wildcard type.
7206              *
7207              * @param annotations Type annotations to be declared by the wildcard type.
7208              * @return A generic type description of a wildcard type with this builder's type as an upper bound.
7209              */

7210             public Generic asWildcardUpperBound(Collection<? extends AnnotationDescription> annotations) {
7211                 return OfWildcardType.Latent.boundedAbove(build(), new Explicit(new ArrayList<AnnotationDescription>(annotations)));
7212             }
7213
7214             /**
7215              * Transforms this type into the lower bound of a wildcard type.
7216              *
7217              * @return A generic type description of a wildcard type with this builder's type as an lower bound.
7218              */

7219             public Generic asWildcardLowerBound() {
7220                 return asWildcardLowerBound(Collections.<AnnotationDescription>emptySet());
7221             }
7222
7223             /**
7224              * Transforms this type into the lower bound of a wildcard type.
7225              *
7226              * @param annotation Type annotations to be declared by the wildcard type.
7227              * @return A generic type description of a wildcard type with this builder's type as an lower bound.
7228              */

7229             public Generic asWildcardLowerBound(Annotation... annotation) {
7230                 return asWildcardLowerBound(Arrays.asList(annotation));
7231             }
7232
7233             /**
7234              * Transforms this type into the lower bound of a wildcard type.
7235              *
7236              * @param annotations Type annotations to be declared by the wildcard type.
7237              * @return A generic type description of a wildcard type with this builder's type as an lower bound.
7238              */

7239             public Generic asWildcardLowerBound(List<? extends Annotation> annotations) {
7240                 return asWildcardLowerBound(new AnnotationList.ForLoadedAnnotations(annotations));
7241             }
7242
7243             /**
7244              * Transforms this type into the lower bound of a wildcard type.
7245              *
7246              * @param annotation Type annotations to be declared by the wildcard type.
7247              * @return A generic type description of a wildcard type with this builder's type as an lower bound.
7248              */

7249             public Generic asWildcardLowerBound(AnnotationDescription... annotation) {
7250                 return asWildcardLowerBound(Arrays.asList(annotation));
7251             }
7252
7253             /**
7254              * Transforms this type into the lower bound of a wildcard type.
7255              *
7256              * @param annotations Type annotations to be declared by the wildcard type.
7257              * @return A generic type description of a wildcard type with this builder's type as an lower bound.
7258              */

7259             public Generic asWildcardLowerBound(Collection<? extends AnnotationDescription> annotations) {
7260                 return OfWildcardType.Latent.boundedBelow(build(), new Explicit(new ArrayList<AnnotationDescription>(annotations)));
7261             }
7262
7263             /**
7264              * Represents the built type into an array.
7265              *
7266              * @return A builder for creating an array of the currently built type.
7267              */

7268             public Builder asArray() {
7269                 return asArray(1);
7270             }
7271
7272             /**
7273              * Represents the built type into an array.
7274              *
7275              * @param arity The arity of the array.
7276              * @return A builder for creating an array of the currently built type.
7277              */

7278             public Builder asArray(int arity) {
7279                 if (arity < 1) {
7280                     throw new IllegalArgumentException("Cannot define an array of a non-positive arity: " + arity);
7281                 }
7282                 TypeDescription.Generic typeDescription = build();
7283                 while (--arity > 0) {
7284                     typeDescription = new OfGenericArray.Latent(typeDescription, Empty.INSTANCE);
7285                 }
7286                 return new Builder.OfGenericArrayType(typeDescription);
7287             }
7288
7289             /**
7290              * Defines type annotations to be declared by the current type.
7291              *
7292              * @param annotation Type annotations to be declared by the current type.
7293              * @return A new builder where the current type declares the supplied type annotations.
7294              */

7295             public Builder annotate(Annotation... annotation) {
7296                 return annotate(Arrays.asList(annotation));
7297             }
7298
7299             /**
7300              * Defines type annotations to be declared by the current type.
7301              *
7302              * @param annotations Type annotations to be declared by the current type.
7303              * @return A new builder where the current type declares the supplied type annotations.
7304              */

7305             public Builder annotate(List<? extends Annotation> annotations) {
7306                 return annotate(new AnnotationList.ForLoadedAnnotations(annotations));
7307             }
7308
7309             /**
7310              * Defines type annotations to be declared by the current type.
7311              *
7312              * @param annotation Type annotations to be declared by the current type.
7313              * @return A new builder where the current type declares the supplied type annotations.
7314              */

7315             public Builder annotate(AnnotationDescription... annotation) {
7316                 return annotate(Arrays.asList(annotation));
7317             }
7318
7319             /**
7320              * Defines type annotations to be declared by the current type.
7321              *
7322              * @param annotations Type annotations to be declared by the current type.
7323              * @return A new builder where the current type declares the supplied type annotations.
7324              */

7325             public Builder annotate(Collection<? extends AnnotationDescription> annotations) {
7326                 return doAnnotate(new ArrayList<AnnotationDescription>(annotations));
7327             }
7328
7329             /**
7330              * Creates a new builder for the current type and the applied type annotations.
7331              *
7332              * @param annotations Type annotations to be declared by the current type.
7333              * @return A new builder where the current type declares the supplied type annotations.
7334              */

7335             protected abstract Builder doAnnotate(List<? extends AnnotationDescription> annotations);
7336
7337             /**
7338              * Finalizes the build and finalizes the created type as a generic type description.
7339              *
7340              * @return A generic type description of the built type.
7341              */

7342             public Generic build() {
7343                 return doBuild();
7344             }
7345
7346             /**
7347              * Finalizes the build and finalizes the created type as a generic type description.
7348              *
7349              * @param annotation Type annotations place for the built generic type to declare.
7350              * @return A generic type description of the built type.
7351              */

7352             public Generic build(Annotation... annotation) {
7353                 return build(Arrays.asList(annotation));
7354             }
7355
7356             /**
7357              * Finalizes the build and finalizes the created type as a generic type description.
7358              *
7359              * @param annotations Type annotations place for the built generic type to declare.
7360              * @return A generic type description of the built type.
7361              */

7362             public Generic build(List<? extends Annotation> annotations) {
7363                 return build(new AnnotationList.ForLoadedAnnotations(annotations));
7364             }
7365
7366             /**
7367              * Finalizes the build and finalizes the created type as a generic type description.
7368              *
7369              * @param annotation Type annotations place for the built generic type to declare.
7370              * @return A generic type description of the built type.
7371              */

7372             public Generic build(AnnotationDescription... annotation) {
7373                 return build(Arrays.asList(annotation));
7374             }
7375
7376             /**
7377              * Finalizes the build and finalizes the created type as a generic type description.
7378              *
7379              * @param annotations Type annotations place for the built generic type to declare.
7380              * @return A generic type description of the built type.
7381              */

7382             public Generic build(Collection<? extends AnnotationDescription> annotations) {
7383                 return doAnnotate(new ArrayList<AnnotationDescription>(annotations)).doBuild();
7384             }
7385
7386             /**
7387              * Builds the generic type.
7388              *
7389              * @return The generic type.
7390              */

7391             protected abstract Generic doBuild();
7392
7393             /**
7394              * A generic type builder for building a non-generic type.
7395              */

7396             @HashCodeAndEqualsPlugin.Enhance
7397             protected static class OfNonGenericType extends Builder {
7398
7399                 /**
7400                  * The type's erasure.
7401                  */

7402                 private final TypeDescription typeDescription;
7403
7404                 /**
7405                  * The raw type's (annotated) declaring type or {@code nullif no such type is defined.
7406                  */

7407                 @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
7408                 private final Generic ownerType;
7409
7410                 /**
7411                  * Creates a builder for a non-generic type.
7412                  *
7413                  * @param typeDescription The type's erasure.
7414                  */

7415                 protected OfNonGenericType(TypeDescription typeDescription) {
7416                     this(typeDescription, typeDescription.getDeclaringType());
7417                 }
7418
7419                 /**
7420                  * Creates a builder for a non-generic type.
7421                  *
7422                  * @param typeDescription The type's erasure.
7423                  * @param ownerType       The raw type's raw declaring type or {@code nullif no such type is defined.
7424                  */

7425                 private OfNonGenericType(TypeDescription typeDescription, TypeDescription ownerType) {
7426                     this(typeDescription, ownerType == null
7427                             ? Generic.UNDEFINED
7428                             : ownerType.asGenericType());
7429                 }
7430
7431                 /**
7432                  * Creates a builder for a non-generic type.
7433                  *
7434                  * @param typeDescription The type's erasure.
7435                  * @param ownerType       The raw type's (annotated) declaring type.
7436                  */

7437                 protected OfNonGenericType(TypeDescription typeDescription, Generic ownerType) {
7438                     this(typeDescription, ownerType, Collections.<AnnotationDescription>emptyList());
7439                 }
7440
7441                 /**
7442                  * Creates a builder for a non-generic type.
7443                  *
7444                  * @param typeDescription The type's erasure.
7445                  * @param ownerType       The raw type's (annotated) declaring type.
7446                  * @param annotations     The type's type annotations.
7447                  */

7448                 protected OfNonGenericType(TypeDescription typeDescription, Generic ownerType, List<? extends AnnotationDescription> annotations) {
7449                     super(annotations);
7450                     this.ownerType = ownerType;
7451                     this.typeDescription = typeDescription;
7452                 }
7453
7454                 @Override
7455                 protected Builder doAnnotate(List<? extends AnnotationDescription> annotations) {
7456                     return new OfNonGenericType(typeDescription, ownerType, CompoundList.of(this.annotations, annotations));
7457                 }
7458
7459                 @Override
7460                 protected Generic doBuild() {
7461                     if (typeDescription.represents(void.class) && !annotations.isEmpty()) {
7462                         throw new IllegalArgumentException("The void non-type cannot be annotated");
7463                     }
7464                     return new Generic.OfNonGenericType.Latent(typeDescription, ownerType, new Explicit(annotations));
7465                 }
7466             }
7467
7468             /**
7469              * A generic type builder for building a parameterized type.
7470              */

7471             @HashCodeAndEqualsPlugin.Enhance
7472             protected static class OfParameterizedType extends Builder {
7473
7474                 /**
7475                  * The raw base type.
7476                  */

7477                 private final TypeDescription rawType;
7478
7479                 /**
7480                  * The generic owner type.
7481                  */

7482                 private final Generic ownerType;
7483
7484                 /**
7485                  * The parameter types.
7486                  */

7487                 private final List<? extends Generic> parameterTypes;
7488
7489                 /**
7490                  * Creates a builder for a parameterized type.
7491                  *
7492                  * @param rawType        The raw base type.
7493                  * @param ownerType      The generic owner type.
7494                  * @param parameterTypes The parameter types.
7495                  */

7496                 protected OfParameterizedType(TypeDescription rawType, Generic ownerType, List<? extends Generic> parameterTypes) {
7497                     this(rawType, ownerType, parameterTypes, Collections.<AnnotationDescription>emptyList());
7498                 }
7499
7500                 /**
7501                  * Creates a builder for a parameterized type.
7502                  *
7503                  * @param rawType        The raw base type.
7504                  * @param ownerType      The generic owner type.
7505                  * @param parameterTypes The parameter types.
7506                  * @param annotations    The type's type annotations.
7507                  */

7508                 protected OfParameterizedType(TypeDescription rawType,
7509                                               Generic ownerType,
7510                                               List<? extends Generic> parameterTypes,
7511                                               List<? extends AnnotationDescription> annotations) {
7512                     super(annotations);
7513                     this.rawType = rawType;
7514                     this.ownerType = ownerType;
7515                     this.parameterTypes = parameterTypes;
7516                 }
7517
7518                 @Override
7519                 protected Builder doAnnotate(List<? extends AnnotationDescription> annotations) {
7520                     return new OfParameterizedType(rawType, ownerType, parameterTypes, CompoundList.of(this.annotations, annotations));
7521                 }
7522
7523                 @Override
7524                 protected Generic doBuild() {
7525                     return new Generic.OfParameterizedType.Latent(rawType, ownerType, parameterTypes, new Explicit(annotations));
7526                 }
7527             }
7528
7529             /**
7530              * A generic type builder building a generic array type.
7531              */

7532             @HashCodeAndEqualsPlugin.Enhance
7533             protected static class OfGenericArrayType extends Builder {
7534
7535                 /**
7536                  * The generic component type.
7537                  */

7538                 private final Generic componentType;
7539
7540                 /**
7541                  * Creates a type builder for building a generic array type.
7542                  *
7543                  * @param componentType The generic component type.
7544                  */

7545                 protected OfGenericArrayType(Generic componentType) {
7546                     this(componentType, Collections.<AnnotationDescription>emptyList());
7547                 }
7548
7549                 /**
7550                  * Creates a type builder for building a generic array type.
7551                  *
7552                  * @param componentType The generic component type.
7553                  * @param annotations   The type's type annotations.
7554                  */

7555                 protected OfGenericArrayType(Generic componentType, List<? extends AnnotationDescription> annotations) {
7556                     super(annotations);
7557                     this.componentType = componentType;
7558                 }
7559
7560                 @Override
7561                 protected Builder doAnnotate(List<? extends AnnotationDescription> annotations) {
7562                     return new OfGenericArrayType(componentType, CompoundList.of(this.annotations, annotations));
7563                 }
7564
7565                 @Override
7566                 protected Generic doBuild() {
7567                     return new Generic.OfGenericArray.Latent(componentType, new Explicit(annotations));
7568                 }
7569             }
7570
7571             /**
7572              * A generic type builder building a symbolic type variable.
7573              */

7574             @HashCodeAndEqualsPlugin.Enhance
7575             protected static class OfTypeVariable extends Builder {
7576
7577                 /**
7578                  * The variable's symbol.
7579                  */

7580                 private final String symbol;
7581
7582                 /**
7583                  * Creates a new builder for a symbolic type variable.
7584                  *
7585                  * @param symbol The variable's symbol.
7586                  */

7587                 protected OfTypeVariable(String symbol) {
7588                     this(symbol, Collections.<AnnotationDescription>emptyList());
7589                 }
7590
7591                 /**
7592                  * Creates a new builder for a symbolic type variable.
7593                  *
7594                  * @param symbol      The variable's symbol.
7595                  * @param annotations The type's type annotations.
7596                  */

7597                 protected OfTypeVariable(String symbol, List<? extends AnnotationDescription> annotations) {
7598                     super(annotations);
7599                     this.symbol = symbol;
7600                 }
7601
7602                 @Override
7603                 protected Builder doAnnotate(List<? extends AnnotationDescription> annotations) {
7604                     return new OfTypeVariable(symbol, CompoundList.of(this.annotations, annotations));
7605                 }
7606
7607                 @Override
7608                 protected Generic doBuild() {
7609                     return new Generic.OfTypeVariable.Symbolic(symbol, new Explicit(annotations));
7610                 }
7611             }
7612         }
7613     }
7614
7615     /**
7616      * An abstract base implementation of a type description.
7617      */

7618     abstract class AbstractBase extends TypeVariableSource.AbstractBase implements TypeDescription {
7619
7620         /**
7621          * The {@link TypeDefinition#RAW_TYPES_PROPERTY} property.
7622          */

7623         public static final boolean RAW_TYPES;
7624
7625         /*
7626          * Reads the raw type property.
7627          */

7628         static {
7629             boolean rawTypes;
7630             try {
7631                 rawTypes = Boolean.parseBoolean(AccessController.doPrivileged(new GetSystemPropertyAction(RAW_TYPES_PROPERTY)));
7632             } catch (Exception ignored) {
7633                 rawTypes = false;
7634             }
7635             RAW_TYPES = rawTypes;
7636         }
7637
7638         /**
7639          * Checks if a specific type is assignable to another type where the source type must be a super
7640          * type of the target type.
7641          *
7642          * @param sourceType The source type to which another type is to be assigned to.
7643          * @param targetType The target type that is to be assigned to the source type.
7644          * @return {@code trueif the target type is assignable to the source type.
7645          */

7646         private static boolean isAssignable(TypeDescription sourceType, TypeDescription targetType) {
7647             // Means that '[sourceType] var = ([targetType]) val;' is a valid assignment. This is trueif:
7648             // (1) Both types are equal (implies primitive types.)
7649             if (sourceType.equals(targetType)) {
7650                 return true;
7651             }
7652             // (2) For arrays, there are special assignment rules.
7653             if (targetType.isArray()) {
7654                 return sourceType.isArray()
7655                         ? isAssignable(sourceType.getComponentType(), targetType.getComponentType())
7656                         : sourceType.represents(Object.class) || ARRAY_INTERFACES.contains(sourceType.asGenericType());
7657             }
7658             // (3) Interfaces do not extend the Object type but are assignable to the Object type.
7659             if (sourceType.represents(Object.class)) {
7660                 return !targetType.isPrimitive();
7661             }
7662             // (4) The sub type has a super type and this super type is assignable to the super type.
7663             Generic superClass = targetType.getSuperClass();
7664             if (superClass != null && sourceType.isAssignableFrom(superClass.asErasure())) {
7665                 return true;
7666             }
7667             // (5) If the target type is an interface, any of this type's interfaces might be assignable to it.
7668             if (sourceType.isInterface()) {
7669                 for (TypeDescription interfaceType : targetType.getInterfaces().asErasures()) {
7670                     if (sourceType.isAssignableFrom(interfaceType)) {
7671                         return true;
7672                     }
7673                 }
7674             }
7675             // (6) None of these criteria are true, i.e. the types are not assignable.
7676             return false;
7677         }
7678
7679         /**
7680          * {@inheritDoc}
7681          */

7682         public boolean isAssignableFrom(Class<?> type) {
7683             return isAssignableFrom(ForLoadedType.of(type));
7684         }
7685
7686         /**
7687          * {@inheritDoc}
7688          */

7689         public boolean isAssignableFrom(TypeDescription typeDescription) {
7690             return isAssignable(this, typeDescription);
7691         }
7692
7693         /**
7694          * {@inheritDoc}
7695          */

7696         public boolean isAssignableTo(Class<?> type) {
7697             return isAssignableTo(ForLoadedType.of(type));
7698         }
7699
7700         /**
7701          * {@inheritDoc}
7702          */

7703         public boolean isAssignableTo(TypeDescription typeDescription) {
7704             return isAssignable(typeDescription, this);
7705         }
7706
7707         /**
7708          * {@inheritDoc}
7709          */

7710         public boolean isInHierarchyWith(Class<?> type) {
7711             return isAssignableTo(type) || isAssignableFrom(type);
7712         }
7713
7714         /**
7715          * {@inheritDoc}
7716          */

7717         public boolean isInHierarchyWith(TypeDescription typeDescription) {
7718             return isAssignableTo(typeDescription) || isAssignableFrom(typeDescription);
7719         }
7720
7721         /**
7722          * {@inheritDoc}
7723          */

7724         public TypeDescription asErasure() {
7725             return this;
7726         }
7727
7728         /**
7729          * {@inheritDoc}
7730          */

7731         public Generic asGenericType() {
7732             return new Generic.OfNonGenericType.ForErasure(this);
7733         }
7734
7735         /**
7736          * {@inheritDoc}
7737          */

7738         public Sort getSort() {
7739             return Sort.NON_GENERIC;
7740         }
7741
7742         /**
7743          * {@inheritDoc}
7744          */

7745         public boolean isInstance(Object value) {
7746             return isAssignableFrom(value.getClass());
7747         }
7748
7749         /**
7750          * {@inheritDoc}
7751          */

7752         public boolean isAnnotationValue(Object value) {
7753             if ((represents(Class.class) && value instanceof TypeDescription)
7754                     || (value instanceof AnnotationDescription && ((AnnotationDescription) value).getAnnotationType().equals(this))
7755                     || (value instanceof EnumerationDescription && ((EnumerationDescription) value).getEnumerationType().equals(this))
7756                     || (represents(String.class) && value instanceof String)
7757                     || (represents(boolean.class) && value instanceof Boolean)
7758                     || (represents(byte.class) && value instanceof Byte)
7759                     || (represents(short.class) && value instanceof Short)
7760                     || (represents(char.class) && value instanceof Character)
7761                     || (represents(int.class) && value instanceof Integer)
7762                     || (represents(long.class) && value instanceof Long)
7763                     || (represents(float.class) && value instanceof Float)
7764                     || (represents(double.class) && value instanceof Double)
7765                     || (represents(String[].class) && value instanceof String[])
7766                     || (represents(boolean[].class) && value instanceof boolean[])
7767                     || (represents(byte[].class) && value instanceof byte[])
7768                     || (represents(short[].class) && value instanceof short[])
7769                     || (represents(char[].class) && value instanceof char[])
7770                     || (represents(int[].class) && value instanceof int[])
7771                     || (represents(long[].class) && value instanceof long[])
7772                     || (represents(float[].class) && value instanceof float[])
7773                     || (represents(double[].class) && value instanceof double[])
7774                     || (represents(Class[].class) && value instanceof TypeDescription[])) {
7775                 return true;
7776             } else if (isAssignableTo(Annotation[].class) && value instanceof AnnotationDescription[]) {
7777                 for (AnnotationDescription annotationDescription : (AnnotationDescription[]) value) {
7778                     if (!annotationDescription.getAnnotationType().equals(getComponentType())) {
7779                         return false;
7780                     }
7781                 }
7782                 return true;
7783             } else if (isAssignableTo(Enum[].class) && value instanceof EnumerationDescription[]) {
7784                 for (EnumerationDescription enumerationDescription : (EnumerationDescription[]) value) {
7785                     if (!enumerationDescription.getEnumerationType().equals(getComponentType())) {
7786                         return false;
7787                     }
7788                 }
7789                 return true;
7790             } else {
7791                 return false;
7792             }
7793         }
7794
7795         /**
7796          * {@inheritDoc}
7797          */

7798         public String getInternalName() {
7799             return getName().replace('.', '/');
7800         }
7801
7802         /**
7803          * {@inheritDoc}
7804          */

7805         public int getActualModifiers(boolean superFlag) {
7806             int actualModifiers = getModifiers()
7807                     | (getDeclaredAnnotations().isAnnotationPresent(Deprecated.class) ? Opcodes.ACC_DEPRECATED : EMPTY_MASK)
7808                     | (isRecord() ? Opcodes.ACC_RECORD : EMPTY_MASK)
7809                     | (superFlag ? Opcodes.ACC_SUPER : EMPTY_MASK);
7810             if (isPrivate()) {
7811                 return actualModifiers & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
7812             } else if (isProtected()) {
7813                 return actualModifiers & ~(Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC) | Opcodes.ACC_PUBLIC;
7814             } else {
7815                 return actualModifiers & ~Opcodes.ACC_STATIC;
7816             }
7817         }
7818
7819         /**
7820          * {@inheritDoc}
7821          */

7822         public String getGenericSignature() {
7823             try {
7824                 SignatureWriter signatureWriter = new SignatureWriter();
7825                 boolean generic = false;
7826                 for (Generic typeVariable : getTypeVariables()) {
7827                     signatureWriter.visitFormalTypeParameter(typeVariable.getSymbol());
7828                     for (Generic upperBound : typeVariable.getUpperBounds()) {
7829                         upperBound.accept(new Generic.Visitor.ForSignatureVisitor(upperBound.asErasure().isInterface()
7830                                 ? signatureWriter.visitInterfaceBound()
7831                                 : signatureWriter.visitClassBound()));
7832                     }
7833                     generic = true;
7834                 }
7835                 Generic superClass = getSuperClass();
7836                 // The object type itself is non generic and implicitly returns a non-generic signature
7837                 if (superClass == null) {
7838                     superClass = TypeDescription.Generic.OBJECT;
7839                 }
7840                 superClass.accept(new Generic.Visitor.ForSignatureVisitor(signatureWriter.visitSuperclass()));
7841                 generic = generic || !superClass.getSort().isNonGeneric();
7842                 for (Generic interfaceType : getInterfaces()) {
7843                     interfaceType.accept(new Generic.Visitor.ForSignatureVisitor(signatureWriter.visitInterface()));
7844                     generic = generic || !interfaceType.getSort().isNonGeneric();
7845                 }
7846                 return generic
7847                         ? signatureWriter.toString()
7848                         : NON_GENERIC_SIGNATURE;
7849             } catch (GenericSignatureFormatError ignored) {
7850                 return NON_GENERIC_SIGNATURE;
7851             }
7852         }
7853
7854         /**
7855          * {@inheritDoc}
7856          */

7857         public boolean isSamePackage(TypeDescription typeDescription) {
7858             PackageDescription thisPackage = getPackage(), otherPackage = typeDescription.getPackage();
7859             return thisPackage == null || otherPackage == null
7860                     ? thisPackage == otherPackage
7861                     : thisPackage.equals(otherPackage);
7862         }
7863
7864         /**
7865          * {@inheritDoc}
7866          */

7867         public boolean isVisibleTo(TypeDescription typeDescription) {
7868             return isPrimitive() || (isArray()
7869                     ? getComponentType().isVisibleTo(typeDescription)
7870                     : isPublic() || isProtected() || isSamePackage(typeDescription)/* || equals(typeDescription.asErasure()) */);
7871         }
7872
7873         /**
7874          * {@inheritDoc}
7875          */

7876         public boolean isAccessibleTo(TypeDescription typeDescription) {
7877             return isPrimitive() || (isArray()
7878                     ? getComponentType().isVisibleTo(typeDescription)
7879                     : isPublic() || isSamePackage(typeDescription)/* || equals(typeDescription.asErasure()) */);
7880         }
7881
7882         /**
7883          * {@inheritDoc}
7884          */

7885         public AnnotationList getInheritedAnnotations() {
7886             Generic superClass = getSuperClass();
7887             AnnotationList declaredAnnotations = getDeclaredAnnotations();
7888             if (superClass == null) {
7889                 return declaredAnnotations;
7890             } else {
7891                 Set<TypeDescription> annotationTypes = new HashSet<TypeDescription>();
7892                 for (AnnotationDescription annotationDescription : declaredAnnotations) {
7893                     annotationTypes.add(annotationDescription.getAnnotationType());
7894                 }
7895                 return new AnnotationList.Explicit(CompoundList.of(declaredAnnotations, superClass.asErasure().getInheritedAnnotations().inherited(annotationTypes)));
7896             }
7897         }
7898
7899         /**
7900          * {@inheritDoc}
7901          */

7902         public String getActualName() {
7903             if (isArray()) {
7904                 TypeDescription typeDescription = this;
7905                 int dimensions = 0;
7906                 do {
7907                     dimensions++;
7908                     typeDescription = typeDescription.getComponentType();
7909                 } while (typeDescription.isArray());
7910                 StringBuilder stringBuilder = new StringBuilder();
7911                 stringBuilder.append(typeDescription.getActualName());
7912                 for (int i = 0; i < dimensions; i++) {
7913                     stringBuilder.append("[]");
7914                 }
7915                 return stringBuilder.toString();
7916             } else {
7917                 return getName();
7918             }
7919         }
7920
7921         /**
7922          * {@inheritDoc}
7923          */

7924         public boolean isPrimitiveWrapper() {
7925             return represents(Boolean.class)
7926                     || represents(Byte.class)
7927                     || represents(Short.class)
7928                     || represents(Character.class)
7929                     || represents(Integer.class)
7930                     || represents(Long.class)
7931                     || represents(Float.class)
7932                     || represents(Double.class);
7933         }
7934
7935         /**
7936          * {@inheritDoc}
7937          */

7938         public boolean isAnnotationReturnType() {
7939             return isPrimitive()
7940                     || represents(String.class)
7941                     || (isAssignableTo(Enum.class) && !represents(Enum.class))
7942                     || (isAssignableTo(Annotation.class) && !represents(Annotation.class))
7943                     || represents(Class.class)
7944                     || (isArray() && !getComponentType().isArray() && getComponentType().isAnnotationReturnType());
7945         }
7946
7947         /**
7948          * {@inheritDoc}
7949          */

7950         public boolean isAnnotationValue() {
7951             return isPrimitive()
7952                     || represents(String.class)
7953                     || isAssignableTo(TypeDescription.class)
7954                     || isAssignableTo(AnnotationDescription.class)
7955                     || isAssignableTo(EnumerationDescription.class)
7956                     || (isArray() && !getComponentType().isArray() && getComponentType().isAnnotationValue());
7957         }
7958
7959         /**
7960          * {@inheritDoc}
7961          */

7962         @SuppressFBWarnings(value = "EC_UNRELATED_CLASS_AND_INTERFACE", justification = "Fits equality contract for type definitions")
7963         public boolean represents(java.lang.reflect.Type type) {
7964             return equals(Sort.describe(type));
7965         }
7966
7967         /**
7968          * {@inheritDoc}
7969          */

7970         public String getTypeName() {
7971             return getName();
7972         }
7973
7974         /**
7975          * {@inheritDoc}
7976          */

7977         public TypeVariableSource getEnclosingSource() {
7978             MethodDescription enclosingMethod = getEnclosingMethod();
7979             return enclosingMethod == null
7980                     ? (isStatic() ? TypeVariableSource.UNDEFINED : getEnclosingType()) // Top-level classes (non-static) have no enclosing type.
7981                     : enclosingMethod;
7982         }
7983
7984         /**
7985          * {@inheritDoc}
7986          */

7987         public boolean isInferrable() {
7988             return false;
7989         }
7990
7991         /**
7992          * {@inheritDoc}
7993          */

7994         public <T> T accept(TypeVariableSource.Visitor<T> visitor) {
7995             return visitor.onType(this);
7996         }
7997
7998         /**
7999          * {@inheritDoc}
8000          */

8001         public boolean isPackageType() {
8002             return getSimpleName().equals(PackageDescription.PACKAGE_CLASS_NAME);
8003         }
8004
8005         /**
8006          * {@inheritDoc}
8007          */

8008         public boolean isGenerified() {
8009             if (!getTypeVariables().isEmpty()) {
8010                 return true;
8011             } else if (isStatic()) {
8012                 return false;
8013             }
8014             TypeDescription declaringType = getDeclaringType();
8015             return declaringType != null && declaringType.isGenerified();
8016         }
8017
8018         /**
8019          * {@inheritDoc}
8020          */

8021         public int getInnerClassCount() {
8022             if (isStatic()) {
8023                 return 0;
8024             }
8025             TypeDescription declaringType = getDeclaringType();
8026             return declaringType == null
8027                     ? 0
8028                     : declaringType.getInnerClassCount() + 1;
8029         }
8030
8031         /**
8032          * {@inheritDoc}
8033          */

8034         public boolean isInnerClass() {
8035             return !isStatic() && isNestedClass();
8036         }
8037
8038         /**
8039          * {@inheritDoc}
8040          */

8041         public boolean isNestedClass() {
8042             return getDeclaringType() != null;
8043         }
8044
8045         /**
8046          * {@inheritDoc}
8047          */

8048         public TypeDescription asBoxed() {
8049             if (represents(boolean.class)) {
8050                 return ForLoadedType.of(Boolean.class);
8051             } else if (represents(byte.class)) {
8052                 return ForLoadedType.of(Byte.class);
8053             } else if (represents(short.class)) {
8054                 return ForLoadedType.of(Short.class);
8055             } else if (represents(char.class)) {
8056                 return ForLoadedType.of(Character.class);
8057             } else if (represents(int.class)) {
8058                 return ForLoadedType.of(Integer.class);
8059             } else if (represents(long.class)) {
8060                 return ForLoadedType.of(Long.class);
8061             } else if (represents(float.class)) {
8062                 return ForLoadedType.of(Float.class);
8063             } else if (represents(double.class)) {
8064                 return ForLoadedType.of(Double.class);
8065             } else {
8066                 return this;
8067             }
8068         }
8069
8070         /**
8071          * {@inheritDoc}
8072          */

8073         public TypeDescription asUnboxed() {
8074             if (represents(Boolean.class)) {
8075                 return ForLoadedType.of(boolean.class);
8076             } else if (represents(Byte.class)) {
8077                 return ForLoadedType.of(byte.class);
8078             } else if (represents(Short.class)) {
8079                 return ForLoadedType.of(short.class);
8080             } else if (represents(Character.class)) {
8081                 return ForLoadedType.of(char.class);
8082             } else if (represents(Integer.class)) {
8083                 return ForLoadedType.of(int.class);
8084             } else if (represents(Long.class)) {
8085                 return ForLoadedType.of(long.class);
8086             } else if (represents(Float.class)) {
8087                 return ForLoadedType.of(float.class);
8088             } else if (represents(Double.class)) {
8089                 return ForLoadedType.of(double.class);
8090             } else {
8091                 return this;
8092             }
8093         }
8094
8095         /**
8096          * {@inheritDoc}
8097          */

8098         public Object getDefaultValue() {
8099             if (represents(boolean.class)) {
8100                 return false;
8101             } else if (represents(byte.class)) {
8102                 return (byte) 0;
8103             } else if (represents(short.class)) {
8104                 return (short) 0;
8105             } else if (represents(char.class)) {
8106                 return (char) 0;
8107             } else if (represents(int.class)) {
8108                 return 0;
8109             } else if (represents(long.class)) {
8110                 return 0L;
8111             } else if (represents(float.class)) {
8112                 return 0f;
8113             } else if (represents(double.class)) {
8114                 return 0d;
8115             } else {
8116                 return null;
8117             }
8118         }
8119
8120         /**
8121          * {@inheritDoc}
8122          */

8123         public boolean isNestHost() {
8124             return equals(getNestHost());
8125         }
8126
8127         /**
8128          * {@inheritDoc}
8129          */

8130         public boolean isNestMateOf(Class<?> type) {
8131             return isNestMateOf(ForLoadedType.of(type));
8132         }
8133
8134         /**
8135          * {@inheritDoc}
8136          */

8137         public boolean isNestMateOf(TypeDescription typeDescription) {
8138             return getNestHost().equals(typeDescription.getNestHost());
8139         }
8140
8141         /**
8142          * {@inheritDoc}
8143          */

8144         public boolean isMemberType() {
8145             return !isLocalType() && !isAnonymousType() && getDeclaringType() != null;
8146         }
8147
8148         /**
8149          * {@inheritDoc}
8150          */

8151         public boolean isCompileTimeConstant() {
8152             return represents(int.class)
8153                     || represents(long.class)
8154                     || represents(float.class)
8155                     || represents(double.class)
8156                     || represents(String.class)
8157                     || represents(Class.class)
8158                     || equals(JavaType.METHOD_TYPE.getTypeStub())
8159                     || equals(JavaType.METHOD_HANDLE.getTypeStub());
8160         }
8161
8162         /**
8163          * {@inheritDoc}
8164          */

8165         public boolean isSealed() {
8166             return !isPrimitive() && !isArray() && !getPermittedSubclasses().isEmpty();
8167         }
8168
8169         /**
8170          * {@inheritDoc}
8171          */

8172         public Iterator<TypeDefinition> iterator() {
8173             return new SuperClassIterator(this);
8174         }
8175
8176         @Override
8177         @CachedReturnPlugin.Enhance
8178         public int hashCode() {
8179             return getName().hashCode();
8180         }
8181
8182         @Override
8183         public boolean equals(Object other) {
8184             if (this == other) {
8185                 return true;
8186             } else if (!(other instanceof TypeDefinition)) {
8187                 return false;
8188             }
8189             TypeDefinition typeDefinition = (TypeDefinition) other;
8190             return typeDefinition.getSort().isNonGeneric() && getName().equals(typeDefinition.asErasure().getName());
8191         }
8192
8193         @Override
8194         public String toString() {
8195             return (isPrimitive() ? "" : (isInterface() ? "interface" : "class") + " ") + getName();
8196         }
8197
8198         /**
8199          * An adapter implementation of a {@link TypeDescription} that
8200          * describes any type that is not an array or a primitive type.
8201          */

8202         public abstract static class OfSimpleType extends TypeDescription.AbstractBase {
8203
8204             /**
8205              * {@inheritDoc}
8206              */

8207             public boolean isPrimitive() {
8208                 return false;
8209             }
8210
8211             /**
8212              * {@inheritDoc}
8213              */

8214             public boolean isArray() {
8215                 return false;
8216             }
8217
8218             /**
8219              * {@inheritDoc}
8220              */

8221             public TypeDescription getComponentType() {
8222                 return TypeDescription.UNDEFINED;
8223             }
8224
8225             /**
8226              * {@inheritDoc}
8227              */

8228             public String getDescriptor() {
8229                 return "L" + getInternalName() + ";";
8230             }
8231
8232             /**
8233              * {@inheritDoc}
8234              */

8235             public String getCanonicalName() {
8236                 if (isAnonymousType() || isLocalType()) {
8237                     return NO_NAME;
8238                 }
8239                 String internalName = getInternalName();
8240                 TypeDescription enclosingType = getEnclosingType();
8241                 if (enclosingType != null && internalName.startsWith(enclosingType.getInternalName() + "$")) {
8242                     return enclosingType.getCanonicalName() + "." + internalName.substring(enclosingType.getInternalName().length() + 1);
8243                 } else {
8244                     return getName();
8245                 }
8246             }
8247
8248             /**
8249              * {@inheritDoc}
8250              */

8251             public String getSimpleName() {
8252                 String internalName = getInternalName();
8253                 TypeDescription enclosingType = getEnclosingType();
8254                 int simpleNameIndex;
8255                 if (enclosingType != null && internalName.startsWith(enclosingType.getInternalName() + "$")) {
8256                     simpleNameIndex = enclosingType.getInternalName().length() + 1;
8257                 } else {
8258                     simpleNameIndex = internalName.lastIndexOf('/');
8259                     if (simpleNameIndex == -1) {
8260                         return internalName;
8261                     }
8262                 }
8263                 while (simpleNameIndex < internalName.length() && !Character.isLetter(internalName.charAt(simpleNameIndex))) {
8264                     simpleNameIndex += 1;
8265                 }
8266                 return internalName.substring(simpleNameIndex);
8267             }
8268
8269             /**
8270              * {@inheritDoc}
8271              */

8272             public StackSize getStackSize() {
8273                 return StackSize.SINGLE;
8274             }
8275
8276             /**
8277              * An implementation of a type description that delegates all properties but the type's name to a delegate.
8278              */

8279             public abstract static class WithDelegation extends OfSimpleType {
8280
8281                 /**
8282                  * Returns the delegate type description to this type instance.
8283                  *
8284                  * @return The delegate type description.
8285                  */

8286                 protected abstract TypeDescription delegate();
8287
8288                 /**
8289                  * {@inheritDoc}
8290                  */

8291                 public Generic getSuperClass() {
8292                     return delegate().getSuperClass();
8293                 }
8294
8295                 /**
8296                  * {@inheritDoc}
8297                  */

8298                 public TypeList.Generic getInterfaces() {
8299                     return delegate().getInterfaces();
8300                 }
8301
8302                 /**
8303                  * {@inheritDoc}
8304                  */

8305                 public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
8306                     return delegate().getDeclaredFields();
8307                 }
8308
8309                 /**
8310                  * {@inheritDoc}
8311                  */

8312                 public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
8313                     return delegate().getDeclaredMethods();
8314                 }
8315
8316                 /**
8317                  * {@inheritDoc}
8318                  */

8319                 public TypeDescription getDeclaringType() {
8320                     return delegate().getDeclaringType();
8321                 }
8322
8323                 /**
8324                  * {@inheritDoc}
8325                  */

8326                 public MethodDescription.InDefinedShape getEnclosingMethod() {
8327                     return delegate().getEnclosingMethod();
8328                 }
8329
8330                 /**
8331                  * {@inheritDoc}
8332                  */

8333                 public TypeDescription getEnclosingType() {
8334                     return delegate().getEnclosingType();
8335                 }
8336
8337                 /**
8338                  * {@inheritDoc}
8339                  */

8340                 public TypeList getDeclaredTypes() {
8341                     return delegate().getDeclaredTypes();
8342                 }
8343
8344                 /**
8345                  * {@inheritDoc}
8346                  */

8347                 public boolean isAnonymousType() {
8348                     return delegate().isAnonymousType();
8349                 }
8350
8351                 /**
8352                  * {@inheritDoc}
8353                  */

8354                 public boolean isLocalType() {
8355                     return delegate().isLocalType();
8356                 }
8357
8358                 /**
8359                  * {@inheritDoc}
8360                  */

8361                 public PackageDescription getPackage() {
8362                     return delegate().getPackage();
8363                 }
8364
8365                 /**
8366                  * {@inheritDoc}
8367                  */

8368                 public AnnotationList getDeclaredAnnotations() {
8369                     return delegate().getDeclaredAnnotations();
8370                 }
8371
8372                 /**
8373                  * {@inheritDoc}
8374                  */

8375                 public TypeList.Generic getTypeVariables() {
8376                     return delegate().getTypeVariables();
8377                 }
8378
8379                 /**
8380                  * {@inheritDoc}
8381                  */

8382                 public int getModifiers() {
8383                     return delegate().getModifiers();
8384                 }
8385
8386                 @Override
8387                 public String getGenericSignature() {
8388                     // Embrace use of native generic signature by direct delegation.
8389                     return delegate().getGenericSignature();
8390                 }
8391
8392                 @Override
8393                 public int getActualModifiers(boolean superFlag) {
8394                     // Embrace use of native actual modifiers by direct delegation.
8395                     return delegate().getActualModifiers(superFlag);
8396                 }
8397
8398                 /**
8399                  * {@inheritDoc}
8400                  */

8401                 public TypeDescription getNestHost() {
8402                     return delegate().getNestHost();
8403                 }
8404
8405                 /**
8406                  * {@inheritDoc}
8407                  */

8408                 public TypeList getNestMembers() {
8409                     return delegate().getNestMembers();
8410                 }
8411
8412                 /**
8413                  * {@inheritDoc}
8414                  */

8415                 public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
8416                     return delegate().getRecordComponents();
8417                 }
8418
8419                 /**
8420                  * {@inheritDoc}
8421                  */

8422                 public boolean isRecord() {
8423                     return delegate().isRecord();
8424                 }
8425
8426                 /**
8427                  * {@inheritDoc}
8428                  */

8429                 public TypeList getPermittedSubclasses() {
8430                     return delegate().getPermittedSubclasses();
8431                 }
8432             }
8433         }
8434     }
8435
8436     /**
8437      * A type description implementation that represents a loaded type.
8438      */

8439     @SuppressFBWarnings(value = "SE_TRANSIENT_FIELD_NOT_RESTORED", justification = "Field is only used as a cache store and is implicitly recomputed")
8440     class ForLoadedType extends AbstractBase implements Serializable {
8441
8442         /**
8443          * The class's serial version UID.
8444          */

8445         private static final long serialVersionUID = 1L;
8446
8447         /**
8448          * A dispatcher for invking methods on {@link Class} reflectively.
8449          */

8450         private static final Dispatcher DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE);
8451
8452         /**
8453          * A cache of type descriptions for commonly used types to avoid unnecessary allocations.
8454          */

8455         @SuppressFBWarnings(value = "MS_MUTABLE_COLLECTION_PKGPROTECT", justification = "This collection is not exposed.")
8456         private static final Map<Class<?>, TypeDescription> TYPE_CACHE;
8457
8458         /*
8459          * Initializes the type cache.
8460          */

8461         static {
8462             TYPE_CACHE = new HashMap<Class<?>, TypeDescription>();
8463             TYPE_CACHE.put(TargetType.classnew ForLoadedType(TargetType.class));
8464             TYPE_CACHE.put(Object.classnew ForLoadedType(Object.class));
8465             TYPE_CACHE.put(String.classnew ForLoadedType(String.class));
8466             TYPE_CACHE.put(Boolean.classnew ForLoadedType(Boolean.class));
8467             TYPE_CACHE.put(Byte.classnew ForLoadedType(Byte.class));
8468             TYPE_CACHE.put(Short.classnew ForLoadedType(Short.class));
8469             TYPE_CACHE.put(Character.classnew ForLoadedType(Character.class));
8470             TYPE_CACHE.put(Integer.classnew ForLoadedType(Integer.class));
8471             TYPE_CACHE.put(Long.classnew ForLoadedType(Long.class));
8472             TYPE_CACHE.put(Float.classnew ForLoadedType(Float.class));
8473             TYPE_CACHE.put(Double.classnew ForLoadedType(Double.class));
8474             TYPE_CACHE.put(void.classnew ForLoadedType(void.class));
8475             TYPE_CACHE.put(boolean.classnew ForLoadedType(boolean.class));
8476             TYPE_CACHE.put(byte.classnew ForLoadedType(byte.class));
8477             TYPE_CACHE.put(short.classnew ForLoadedType(short.class));
8478             TYPE_CACHE.put(char.classnew ForLoadedType(char.class));
8479             TYPE_CACHE.put(int.classnew ForLoadedType(int.class));
8480             TYPE_CACHE.put(long.classnew ForLoadedType(long.class));
8481             TYPE_CACHE.put(float.classnew ForLoadedType(float.class));
8482             TYPE_CACHE.put(double.classnew ForLoadedType(double.class));
8483         }
8484
8485         /**
8486          * The loaded type this instance represents.
8487          */

8488         private final Class<?> type;
8489
8490         /**
8491          * Creates a new immutable type description for a loaded type. This constructor should not normally be used.
8492          * Use {@link ForLoadedType#of(Class)} instead.
8493          *
8494          * @param type The type to be represented by this type description.
8495          */

8496         public ForLoadedType(Class<?> type) {
8497             this.type = type;
8498         }
8499
8500         /**
8501          * Returns the type's actual name where it is taken into consideration that this type might be loaded anonymously.
8502          * In this case, the remainder of the types name is suffixed by {@code /<id>} which is removed when using this method
8503          * but is retained when calling {@link Class#getName()}.
8504          *
8505          * @param type The type for which to resolve its name.
8506          * @return The type's actual name.
8507          */

8508         public static String getName(Class<?> type) {
8509             String name = type.getName();
8510             int anonymousLoaderIndex = name.indexOf('/');
8511             return anonymousLoaderIndex == -1
8512                     ? name
8513                     : name.substring(0, anonymousLoaderIndex);
8514         }
8515
8516         /**
8517          * Returns a new immutable type description for a loaded type.
8518          *
8519          * @param type The type to be represented by this type description.
8520          * @return The type description representing the given type.
8521          */

8522         public static TypeDescription of(Class<?> type) {
8523             TypeDescription typeDescription = TYPE_CACHE.get(type);
8524             return typeDescription == null
8525                     ? new ForLoadedType(type)
8526                     : typeDescription;
8527         }
8528
8529         @Override
8530         public boolean isAssignableFrom(Class<?> type) {
8531             return this.type.isAssignableFrom(type) || super.isAssignableFrom(type);
8532         }
8533
8534         @Override
8535         public boolean isAssignableFrom(TypeDescription typeDescription) {
8536             return typeDescription instanceof ForLoadedType && type.isAssignableFrom(((ForLoadedType) typeDescription).type) || super.isAssignableFrom(typeDescription);
8537         }
8538
8539         @Override
8540         public boolean isAssignableTo(Class<?> type) {
8541             return type.isAssignableFrom(this.type) || super.isAssignableTo(type);
8542         }
8543
8544         @Override
8545         public boolean isAssignableTo(TypeDescription typeDescription) {
8546             return typeDescription instanceof ForLoadedType && ((ForLoadedType) typeDescription).type.isAssignableFrom(type) || super.isAssignableTo(typeDescription);
8547         }
8548
8549         @Override
8550         public boolean isInHierarchyWith(Class<?> type) {
8551             return type.isAssignableFrom(this.type) || this.type.isAssignableFrom(type) || super.isInHierarchyWith(type);
8552         }
8553
8554         @Override
8555         public boolean isInHierarchyWith(TypeDescription typeDescription) {
8556             return typeDescription instanceof ForLoadedType && (((ForLoadedType) typeDescription).type.isAssignableFrom(type)
8557                     || type.isAssignableFrom(((ForLoadedType) typeDescription).type)) || super.isInHierarchyWith(typeDescription);
8558         }
8559
8560         @Override
8561         public boolean represents(java.lang.reflect.Type type) {
8562             return type == this.type || super.represents(type);
8563         }
8564
8565         /**
8566          * {@inheritDoc}
8567          */

8568         public TypeDescription getComponentType() {
8569             Class<?> componentType = type.getComponentType();
8570             return componentType == null
8571                     ? TypeDescription.UNDEFINED
8572                     : ForLoadedType.of(componentType);
8573         }
8574
8575         /**
8576          * {@inheritDoc}
8577          */

8578         public boolean isArray() {
8579             return type.isArray();
8580         }
8581
8582         /**
8583          * {@inheritDoc}
8584          */

8585         public boolean isPrimitive() {
8586             return type.isPrimitive();
8587         }
8588
8589         @Override
8590         public boolean isAnnotation() {
8591             return type.isAnnotation();
8592         }
8593
8594         /**
8595          * {@inheritDoc}
8596          */

8597         public Generic getSuperClass() {
8598             if (RAW_TYPES) {
8599                 return type.getSuperclass() == null
8600                         ? TypeDescription.Generic.UNDEFINED
8601                         : Generic.OfNonGenericType.ForLoadedType.of(type.getSuperclass());
8602             }
8603             return type.getSuperclass() == null
8604                     ? TypeDescription.Generic.UNDEFINED
8605                     : new Generic.LazyProjection.ForLoadedSuperClass(type);
8606         }
8607
8608         /**
8609          * {@inheritDoc}
8610          */

8611         public TypeList.Generic getInterfaces() {
8612             if (RAW_TYPES) {
8613                 return isArray()
8614                         ? ARRAY_INTERFACES
8615                         : new TypeList.Generic.ForLoadedTypes(type.getInterfaces());
8616             }
8617             return isArray()
8618                     ? ARRAY_INTERFACES
8619                     : new TypeList.Generic.OfLoadedInterfaceTypes(type);
8620         }
8621
8622         /**
8623          * {@inheritDoc}
8624          */

8625         public TypeDescription getDeclaringType() {
8626             Class<?> declaringType = type.getDeclaringClass();
8627             return declaringType == null
8628                     ? TypeDescription.UNDEFINED
8629                     : ForLoadedType.of(declaringType);
8630         }
8631
8632         /**
8633          * {@inheritDoc}
8634          */

8635         public MethodDescription.InDefinedShape getEnclosingMethod() {
8636             Method enclosingMethod = type.getEnclosingMethod();
8637             Constructor<?> enclosingConstructor = type.getEnclosingConstructor();
8638             if (enclosingMethod != null) {
8639                 return new MethodDescription.ForLoadedMethod(enclosingMethod);
8640             } else if (enclosingConstructor != null) {
8641                 return new MethodDescription.ForLoadedConstructor(enclosingConstructor);
8642             } else {
8643                 return MethodDescription.UNDEFINED;
8644             }
8645         }
8646
8647         /**
8648          * {@inheritDoc}
8649          */

8650         public TypeDescription getEnclosingType() {
8651             Class<?> enclosingType = type.getEnclosingClass();
8652             return enclosingType == null
8653                     ? TypeDescription.UNDEFINED
8654                     : ForLoadedType.of(enclosingType);
8655         }
8656
8657         /**
8658          * {@inheritDoc}
8659          */

8660         public TypeList getDeclaredTypes() {
8661             return new TypeList.ForLoadedTypes(type.getDeclaredClasses());
8662         }
8663
8664         /**
8665          * {@inheritDoc}
8666          */

8667         public String getSimpleName() {
8668             String simpleName = type.getSimpleName();
8669             int anonymousLoaderIndex = simpleName.indexOf('/');
8670             if (anonymousLoaderIndex == -1) {
8671                 return simpleName;
8672             } else {
8673                 StringBuilder normalized = new StringBuilder(simpleName.substring(0, anonymousLoaderIndex));
8674                 Class<?> type = this.type;
8675                 while (type.isArray()) {
8676                     normalized.append("[]");
8677                     type = type.getComponentType();
8678                 }
8679                 return normalized.toString();
8680             }
8681         }
8682
8683         /**
8684          * {@inheritDoc}
8685          */

8686         public boolean isAnonymousType() {
8687             return type.isAnonymousClass();
8688         }
8689
8690         /**
8691          * {@inheritDoc}
8692          */

8693         public boolean isLocalType() {
8694             return type.isLocalClass();
8695         }
8696
8697         @Override
8698         public boolean isMemberType() {
8699             return type.isMemberClass();
8700         }
8701
8702         /**
8703          * {@inheritDoc}
8704          */

8705         @CachedReturnPlugin.Enhance("declaredFields")
8706         public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
8707             return new FieldList.ForLoadedFields(type.getDeclaredFields());
8708         }
8709
8710         /**
8711          * {@inheritDoc}
8712          */

8713         @CachedReturnPlugin.Enhance("declaredMethods")
8714         public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
8715             return new MethodList.ForLoadedMethods(type);
8716         }
8717
8718         /**
8719          * {@inheritDoc}
8720          */

8721         public PackageDescription getPackage() {
8722             if (type.isArray() || type.isPrimitive()) {
8723                 return PackageDescription.UNDEFINED;
8724             } else {
8725                 Package aPackage = type.getPackage();
8726                 if (aPackage == null) {
8727                     String name = type.getName();
8728                     int index = name.lastIndexOf('.');
8729                     return index == -1
8730                             ? new PackageDescription.Simple(EMPTY_NAME)
8731                             : new PackageDescription.Simple(name.substring(0, index));
8732                 } else {
8733                     return new PackageDescription.ForLoadedPackage(aPackage);
8734                 }
8735             }
8736         }
8737
8738         /**
8739          * {@inheritDoc}
8740          */

8741         public StackSize getStackSize() {
8742             return StackSize.of(type);
8743         }
8744
8745         /**
8746          * {@inheritDoc}
8747          */

8748         public String getName() {
8749             return getName(type);
8750         }
8751
8752         /**
8753          * {@inheritDoc}
8754          */

8755         public String getCanonicalName() {
8756             String canonicalName = type.getCanonicalName();
8757             if (canonicalName == null) {
8758                 return NO_NAME;
8759             }
8760             int anonymousLoaderIndex = canonicalName.indexOf('/');
8761             if (anonymousLoaderIndex == -1) {
8762                 return canonicalName;
8763             } else {
8764                 StringBuilder normalized = new StringBuilder(canonicalName.substring(0, anonymousLoaderIndex));
8765                 Class<?> type = this.type;
8766                 while (type.isArray()) {
8767                     normalized.append("[]");
8768                     type = type.getComponentType();
8769                 }
8770                 return normalized.toString();
8771             }
8772         }
8773
8774         /**
8775          * {@inheritDoc}
8776          */

8777         public String getDescriptor() {
8778             String name = type.getName();
8779             int anonymousLoaderIndex = name.indexOf('/');
8780             return anonymousLoaderIndex == -1
8781                     ? Type.getDescriptor(type)
8782                     : "L" + name.substring(0, anonymousLoaderIndex).replace('.', '/') + ";";
8783         }
8784
8785         /**
8786          * {@inheritDoc}
8787          */

8788         public int getModifiers() {
8789             return type.getModifiers();
8790         }
8791
8792         /**
8793          * {@inheritDoc}
8794          */

8795         public TypeList.Generic getTypeVariables() {
8796             if (RAW_TYPES) {
8797                 return new TypeList.Generic.Empty();
8798             }
8799             return TypeList.Generic.ForLoadedTypes.OfTypeVariables.of(type);
8800         }
8801
8802         /**
8803          * {@inheritDoc}
8804          */

8805         @CachedReturnPlugin.Enhance("declaredAnnotations")
8806         public AnnotationList getDeclaredAnnotations() {
8807             return new AnnotationList.ForLoadedAnnotations(type.getDeclaredAnnotations());
8808         }
8809
8810         /**
8811          * {@inheritDoc}
8812          */

8813         public Generic asGenericType() {
8814             return Generic.OfNonGenericType.ForLoadedType.of(type);
8815         }
8816
8817         /**
8818          * {@inheritDoc}
8819          */

8820         public TypeDescription getNestHost() {
8821             return TypeDescription.ForLoadedType.of(DISPATCHER.getNestHost(type));
8822         }
8823
8824         /**
8825          * {@inheritDoc}
8826          */

8827         public TypeList getNestMembers() {
8828             return new TypeList.ForLoadedTypes(DISPATCHER.getNestMembers(type));
8829         }
8830
8831         @Override
8832         public boolean isNestHost() {
8833             return DISPATCHER.getNestHost(type) == type;
8834         }
8835
8836         @Override
8837         public boolean isNestMateOf(Class<?> type) {
8838             return DISPATCHER.isNestmateOf(this.type, type) || super.isNestMateOf(ForLoadedType.of(type));
8839         }
8840
8841         @Override
8842         public boolean isNestMateOf(TypeDescription typeDescription) {
8843             return typeDescription instanceof ForLoadedType && DISPATCHER.isNestmateOf(type, ((ForLoadedType) typeDescription).type) || super.isNestMateOf(typeDescription);
8844         }
8845
8846         /**
8847          * {@inheritDoc}
8848          */

8849         public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
8850             Object[] recordComponent = RecordComponentDescription.ForLoadedRecordComponent.DISPATCHER.getRecordComponents(type);
8851             return recordComponent == null
8852                     ? new RecordComponentList.Empty<RecordComponentDescription.InDefinedShape>()
8853                     : new RecordComponentList.ForLoadedRecordComponents();
8854         }
8855
8856         /**
8857          * {@inheritDoc}
8858          */

8859         public boolean isRecord() {
8860             return RecordComponentDescription.ForLoadedRecordComponent.DISPATCHER.isRecord(type);
8861         }
8862
8863         /**
8864          * {@inheritDoc}
8865          */

8866         public TypeList getPermittedSubclasses() {
8867             return new ClassDescriptionTypeList(type.getClassLoader(), DISPATCHER.getPermittedSubclasses(type));
8868         }
8869
8870         /**
8871          * A dispatcher for using methods of {@link Class} that are not declared for Java 6.
8872          */

8873         protected interface Dispatcher {
8874
8875             /**
8876              * Returns the specified class's nest host.
8877              *
8878              * @param type The class for which to locate the nest host.
8879              * @return The nest host of the specified class.
8880              */

8881             Class<?> getNestHost(Class<?> type);
8882
8883             /**
8884              * Returns the nest members of the other class.
8885              *
8886              * @param type The type to get the nest members for.
8887              * @return An array containing all nest members of the specified type's nest group.
8888              */

8889             Class<?>[] getNestMembers(Class<?> type);
8890
8891             /**
8892              * Returns {@code trueif the specified type is a nest mate of the other type.
8893              *
8894              * @param type      The type to evaluate for being a nest mate of another type.
8895              * @param candidate The candidate type.
8896              * @return {@code trueif the specified type is a nest mate of the other class.
8897              */

8898             boolean isNestmateOf(Class<?> type, Class<?> candidate);
8899
8900             /**
8901              * Returns the permitted subclasses of the supplied type.
8902              *
8903              * @param type The type for which to check the permitted subclasses.
8904              * @return An array of descriptors of permitted subclasses.
8905              */

8906             Object[] getPermittedSubclasses(Class<?> type);
8907
8908             /**
8909              * Returns the internal name of a permitted subclass.
8910              *
8911              * @param permittedSubclass The permitted subclass descriptor.
8912              * @return The permitted subclasses internal name.
8913              */

8914             String getInternalName(Object permittedSubclass);
8915
8916             /**
8917              * An action to resolve the dispatcher for invoking methods of {@link Class} reflectively.
8918              */

8919             enum CreationAction implements PrivilegedAction<Dispatcher> {
8920
8921                 /**
8922                  * The singleton instance.
8923                  */

8924                 INSTANCE;
8925
8926                 /**
8927                  * {@inheritDoc}
8928                  */

8929                 @SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Exception should not be rethrown but trigger a fallback")
8930                 public Dispatcher run() {
8931                     try {
8932                         try {
8933                             return new ForJava16CapableVm(Class.class.getMethod("getNestHost"),
8934                                     Class.class.getMethod("getNestMembers"),
8935                                     Class.class.getMethod("isNestmateOf", Class.class),
8936                                     Class.class.getMethod("permittedSubclasses"),
8937                                     Class.forName("java.lang.constant.ClassDesc").getMethod("descriptorString"));
8938                         } catch (Exception ignored) {
8939                             return new ForJava11CapableVm(Class.class.getMethod("getNestHost"),
8940                                     Class.class.getMethod("getNestMembers"),
8941                                     Class.class.getMethod("isNestmateOf", Class.class));
8942                         }
8943                     } catch (NoSuchMethodException ignored) {
8944                         return ForLegacyVm.INSTANCE;
8945                     }
8946                 }
8947             }
8948
8949             /**
8950              * A dispatcher for a legacy VM.
8951              */

8952             enum ForLegacyVm implements Dispatcher {
8953
8954                 /**
8955                  * The singleton instance.
8956                  */

8957                 INSTANCE;
8958
8959                 /**
8960                  * {@inheritDoc}
8961                  */

8962                 public Class<?> getNestHost(Class<?> type) {
8963                     return type;
8964                 }
8965
8966                 /**
8967                  * {@inheritDoc}
8968                  */

8969                 public Class<?>[] getNestMembers(Class<?> type) {
8970                     return new Class<?>[]{type};
8971                 }
8972
8973                 /**
8974                  * {@inheritDoc}
8975                  */

8976                 public boolean isNestmateOf(Class<?> type, Class<?> candidate) {
8977                     return type == candidate;
8978                 }
8979
8980                 /**
8981                  * {@inheritDoc}
8982                  */

8983                 public Object[] getPermittedSubclasses(Class<?> type) {
8984                     return new Object[0];
8985                 }
8986
8987                 /**
8988                  * {@inheritDoc}
8989                  */

8990                 public String getInternalName(Object permittedSubclass) {
8991                     throw new IllegalStateException("Not supported on the current VM");
8992                 }
8993             }
8994
8995             /**
8996              * A dispatcher for a Java 11-capable VM.
8997              */

8998             class ForJava11CapableVm implements Dispatcher {
8999
9000                 /**
9001                  * The {@code java.lang.Class#getNestHost} method.
9002                  */

9003                 private final Method getNestHost;
9004
9005                 /**
9006                  * The {@code java.lang.Class#getNestMembers} method.
9007                  */

9008                 private final Method getNestMembers;
9009
9010                 /**
9011                  * The {@code java.lang.Class#isNestmateOf} method.
9012                  */

9013                 private final Method isNestmateOf;
9014
9015                 /**
9016                  * Creates a dispatcher for a Java 11-capable VM.
9017                  *
9018                  * @param getNestHost    The {@code java.lang.Class#getNestHost} method.
9019                  * @param getNestMembers The {@code java.lang.Class#getNestMembers} method.
9020                  * @param isNestmateOf   The {@code java.lang.Class#isNestmateOf} method.
9021                  */

9022                 protected ForJava11CapableVm(Method getNestHost, Method getNestMembers, Method isNestmateOf) {
9023                     this.getNestHost = getNestHost;
9024                     this.getNestMembers = getNestMembers;
9025                     this.isNestmateOf = isNestmateOf;
9026                 }
9027
9028                 /**
9029                  * {@inheritDoc}
9030                  */

9031                 public Class<?> getNestHost(Class<?> type) {
9032                     try {
9033                         return (Class<?>) getNestHost.invoke(type);
9034                     } catch (IllegalAccessException exception) {
9035                         throw new IllegalStateException("Could not access Class::getNestHost", exception);
9036                     } catch (InvocationTargetException exception) {
9037                         throw new IllegalStateException("Could not invoke Class::getNestHost", exception.getCause());
9038                     }
9039                 }
9040
9041                 /**
9042                  * {@inheritDoc}
9043                  */

9044                 public Class<?>[] getNestMembers(Class<?> type) {
9045                     try {
9046                         return (Class<?>[]) getNestMembers.invoke(type);
9047                     } catch (IllegalAccessException exception) {
9048                         throw new IllegalStateException("Could not access Class::getNestMembers", exception);
9049                     } catch (InvocationTargetException exception) {
9050                         throw new IllegalStateException("Could not invoke Class::getNestMembers", exception.getCause());
9051                     }
9052                 }
9053
9054                 /**
9055                  * {@inheritDoc}
9056                  */

9057                 public boolean isNestmateOf(Class<?> type, Class<?> candidate) {
9058                     try {
9059                         return (Boolean) isNestmateOf.invoke(type, candidate);
9060                     } catch (IllegalAccessException exception) {
9061                         throw new IllegalStateException("Could not access Class::isNestmateOf", exception);
9062                     } catch (InvocationTargetException exception) {
9063                         throw new IllegalStateException("Could not invoke Class::isNestmateOf", exception.getCause());
9064                     }
9065                 }
9066
9067                 /**
9068                  * {@inheritDoc}
9069                  */

9070                 public Object[] getPermittedSubclasses(Class<?> type) {
9071                     return new Object[0];
9072                 }
9073
9074                 /**
9075                  * {@inheritDoc}
9076                  */

9077                 public String getInternalName(Object permittedSubclass) {
9078                     throw new IllegalStateException("Not supported on the current VM");
9079                 }
9080             }
9081
9082             /**
9083              * A dispatcher for a Java 16-capable VM.
9084              */

9085             class ForJava16CapableVm implements Dispatcher {
9086
9087                 /**
9088                  * The {@code java.lang.Class#getNestHost} method.
9089                  */

9090                 private final Method getNestHost;
9091
9092                 /**
9093                  * The {@code java.lang.Class#getNestMembers} method.
9094                  */

9095                 private final Method getNestMembers;
9096
9097                 /**
9098                  * The {@code java.lang.Class#isNestmateOf} method.
9099                  */

9100                 private final Method isNestmateOf;
9101
9102                 /**
9103                  * The {@code java.lang.Class#permittedSubclasses} method.
9104                  */

9105                 private final Method permittedSubclasses;
9106
9107                 /**
9108                  * The {@code java.lang.constant.ClassDesc#descriptorString} method.
9109                  */

9110                 private final Method descriptorString;
9111
9112                 /**
9113                  * Creates a dispatcher for a Java 11-capable VM.
9114                  *
9115                  * @param getNestHost         The {@code java.lang.Class#getNestHost} method.
9116                  * @param getNestMembers      The {@code java.lang.Class#getNestMembers} method.
9117                  * @param isNestmateOf        The {@code java.lang.Class#isNestmateOf} method.
9118                  * @param permittedSubclasses The {@code java.lang.Class#permittedSubclasses} method.
9119                  * @param descriptorString    The {@code java.lang.constant.ClassDesc#descriptorString} method.
9120                  */

9121                 protected ForJava16CapableVm(Method getNestHost, Method getNestMembers, Method isNestmateOf, Method permittedSubclasses, Method descriptorString) {
9122                     this.getNestHost = getNestHost;
9123                     this.getNestMembers = getNestMembers;
9124                     this.isNestmateOf = isNestmateOf;
9125                     this.permittedSubclasses = permittedSubclasses;
9126                     this.descriptorString = descriptorString;
9127                 }
9128
9129                 /**
9130                  * {@inheritDoc}
9131                  */

9132                 public Class<?> getNestHost(Class<?> type) {
9133                     try {
9134                         return (Class<?>) getNestHost.invoke(type);
9135                     } catch (IllegalAccessException exception) {
9136                         throw new IllegalStateException("Could not access Class::getNestHost", exception);
9137                     } catch (InvocationTargetException exception) {
9138                         throw new IllegalStateException("Could not invoke Class::getNestHost", exception.getCause());
9139                     }
9140                 }
9141
9142                 /**
9143                  * {@inheritDoc}
9144                  */

9145                 public Class<?>[] getNestMembers(Class<?> type) {
9146                     try {
9147                         return (Class<?>[]) getNestMembers.invoke(type);
9148                     } catch (IllegalAccessException exception) {
9149                         throw new IllegalStateException("Could not access Class::getNestMembers", exception);
9150                     } catch (InvocationTargetException exception) {
9151                         throw new IllegalStateException("Could not invoke Class::getNestMembers", exception.getCause());
9152                     }
9153                 }
9154
9155                 /**
9156                  * {@inheritDoc}
9157                  */

9158                 public boolean isNestmateOf(Class<?> type, Class<?> candidate) {
9159                     try {
9160                         return (Boolean) isNestmateOf.invoke(type, candidate);
9161                     } catch (IllegalAccessException exception) {
9162                         throw new IllegalStateException("Could not access Class::isNestmateOf", exception);
9163                     } catch (InvocationTargetException exception) {
9164                         throw new IllegalStateException("Could not invoke Class::isNestmateOf", exception.getCause());
9165                     }
9166                 }
9167
9168                 /**
9169                  * {@inheritDoc}
9170                  */

9171                 public Object[] getPermittedSubclasses(Class<?> type) {
9172                     try {
9173                         return (Object[]) permittedSubclasses.invoke(type);
9174                     } catch (IllegalAccessException exception) {
9175                         throw new IllegalStateException("Could not access Class::permittedSubclasses", exception);
9176                     } catch (InvocationTargetException exception) {
9177                         throw new IllegalStateException("Could not invoke Class::permittedSubclasses", exception.getCause());
9178                     }
9179                 }
9180
9181                 /**
9182                  * {@inheritDoc}
9183                  */

9184                 public String getInternalName(Object permittedSubclass) {
9185                     try {
9186                         return (String) descriptorString.invoke(permittedSubclass);
9187                     } catch (IllegalAccessException exception) {
9188                         throw new IllegalStateException("Could not access ClassDesc::descriptorString", exception);
9189                     } catch (InvocationTargetException exception) {
9190                         throw new IllegalStateException("Could not invoke ClassDesc::descriptorString", exception.getCause());
9191                     }
9192                 }
9193             }
9194         }
9195
9196         /**
9197          * A list of type descriptions represented by class descriptions.
9198          */

9199         protected static class ClassDescriptionTypeList extends TypeList.AbstractBase {
9200
9201             /**
9202              * The represented class loader.
9203              */

9204             private final ClassLoader classLoader;
9205
9206             /**
9207              * An array of represented permitted subclasses.
9208              */

9209             private final Object[] permittedSubclass;
9210
9211             /**
9212              * Creates a new list of type descriptions.
9213              *
9214              * @param classLoader       The represented class loader.
9215              * @param permittedSubclass An array of represented permitted subclasses.
9216              */

9217             protected ClassDescriptionTypeList(ClassLoader classLoader, Object[] permittedSubclass) {
9218                 this.classLoader = classLoader;
9219                 this.permittedSubclass = permittedSubclass;
9220             }
9221
9222             /**
9223              * {@inheritDoc}
9224              */

9225             public TypeDescription get(int index) {
9226                 return new InternalNameLazyType(classLoader, DISPATCHER.getInternalName(permittedSubclass[index]));
9227             }
9228
9229             /**
9230              * {@inheritDoc}
9231              */

9232             public int size() {
9233                 return permittedSubclass.length;
9234             }
9235
9236             /**
9237              * A lazy representation of an internal name for a given class loader.
9238              */

9239             protected static class InternalNameLazyType extends OfSimpleType.WithDelegation {
9240
9241                 /**
9242                  * The represented class loader.
9243                  */

9244                 private final ClassLoader classLoader;
9245
9246                 /**
9247                  * The represented internal name.
9248                  */

9249                 private final String internalName;
9250
9251                 /**
9252                  * Creates a new lazy representation of an internal name.
9253                  *
9254                  * @param classLoader  The represented class loader.
9255                  * @param internalName The represented internal name.
9256                  */

9257                 protected InternalNameLazyType(ClassLoader classLoader, String internalName) {
9258                     this.classLoader = classLoader;
9259                     this.internalName = internalName;
9260                 }
9261
9262                 @Override
9263                 @CachedReturnPlugin.Enhance
9264                 protected TypeDescription delegate() {
9265                     try {
9266                         return ForLoadedType.of(Class.forName(getName(), false, classLoader));
9267                     } catch (ClassNotFoundException exception) {
9268                         throw new IllegalStateException(exception);
9269                     }
9270                 }
9271
9272                 /**
9273                  * {@inheritDoc}
9274                  */

9275                 public String getName() {
9276                     return internalName.replace('/', '.');
9277                 }
9278             }
9279         }
9280     }
9281
9282     /**
9283      * A projection for an array type based on an existing {@link TypeDescription}.
9284      */

9285     class ArrayProjection extends AbstractBase {
9286
9287         /**
9288          * Modifiers that every array in Java implies.
9289          */

9290         private static final int ARRAY_IMPLIED = Opcodes.ACC_FINAL | Opcodes.ACC_ABSTRACT;
9291
9292         /**
9293          * Modifiers that no array in Java displays.
9294          */

9295         private static final int ARRAY_EXCLUDED = Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION | Opcodes.ACC_STATIC;
9296
9297         /**
9298          * The base component type which is itself not an array.
9299          */

9300         private final TypeDescription componentType;
9301
9302         /**
9303          * The arity of this array.
9304          */

9305         private final int arity;
9306
9307         /**
9308          * Creates a new array projection.
9309          *
9310          * @param componentType The base component type of the array which is itself not an array.
9311          * @param arity         The arity of this array.
9312          */

9313         protected ArrayProjection(TypeDescription componentType, int arity) {
9314             this.componentType = componentType;
9315             this.arity = arity;
9316         }
9317
9318         /**
9319          * Creates an array projection of an arity of one.
9320          *
9321          * @param componentType The component type of the array.
9322          * @return A projection of the component type as an array of the given value with an arity of one.
9323          */

9324         public static TypeDescription of(TypeDescription componentType) {
9325             return of(componentType, 1);
9326         }
9327
9328         /**
9329          * Creates an array projection.
9330          *
9331          * @param componentType The component type of the array.
9332          * @param arity         The arity of this array.
9333          * @return A projection of the component type as an array of the given value with the supplied arity.
9334          */

9335         public static TypeDescription of(TypeDescription componentType, int arity) {
9336             if (arity < 0) {
9337                 throw new IllegalArgumentException("Arrays cannot have a negative arity");
9338             }
9339             while (componentType.isArray()) {
9340                 componentType = componentType.getComponentType();
9341                 arity++;
9342             }
9343             return arity == 0
9344                     ? componentType
9345                     : new ArrayProjection(componentType, arity);
9346         }
9347
9348         /**
9349          * {@inheritDoc}
9350          */

9351         public boolean isArray() {
9352             return true;
9353         }
9354
9355         /**
9356          * {@inheritDoc}
9357          */

9358         public TypeDescription getComponentType() {
9359             return arity == 1
9360                     ? componentType
9361                     : new ArrayProjection(componentType, arity - 1);
9362         }
9363
9364         /**
9365          * {@inheritDoc}
9366          */

9367         public boolean isPrimitive() {
9368             return false;
9369         }
9370
9371         /**
9372          * {@inheritDoc}
9373          */

9374         public Generic getSuperClass() {
9375             return TypeDescription.Generic.OBJECT;
9376         }
9377
9378         /**
9379          * {@inheritDoc}
9380          */

9381         public TypeList.Generic getInterfaces() {
9382             return ARRAY_INTERFACES;
9383         }
9384
9385         /**
9386          * {@inheritDoc}
9387          */

9388         public MethodDescription.InDefinedShape getEnclosingMethod() {
9389             return MethodDescription.UNDEFINED;
9390         }
9391
9392         /**
9393          * {@inheritDoc}
9394          */

9395         public TypeDescription getEnclosingType() {
9396             return TypeDescription.UNDEFINED;
9397         }
9398
9399         /**
9400          * {@inheritDoc}
9401          */

9402         public TypeList getDeclaredTypes() {
9403             return new TypeList.Empty();
9404         }
9405
9406         /**
9407          * {@inheritDoc}
9408          */

9409         public String getSimpleName() {
9410             StringBuilder stringBuilder = new StringBuilder(componentType.getSimpleName());
9411             for (int i = 0; i < arity; i++) {
9412                 stringBuilder.append("[]");
9413             }
9414             return stringBuilder.toString();
9415         }
9416
9417         /**
9418          * {@inheritDoc}
9419          */

9420         public String getCanonicalName() {
9421             String canonicalName = componentType.getCanonicalName();
9422             if (canonicalName == null) {
9423                 return NO_NAME;
9424             }
9425             StringBuilder stringBuilder = new StringBuilder(canonicalName);
9426             for (int i = 0; i < arity; i++) {
9427                 stringBuilder.append("[]");
9428             }
9429             return stringBuilder.toString();
9430         }
9431
9432         /**
9433          * {@inheritDoc}
9434          */

9435         public boolean isAnonymousType() {
9436             return false;
9437         }
9438
9439         /**
9440          * {@inheritDoc}
9441          */

9442         public boolean isLocalType() {
9443             return false;
9444         }
9445
9446         @Override
9447         public boolean isMemberType() {
9448             return false;
9449         }
9450
9451         /**
9452          * {@inheritDoc}
9453          */

9454         public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
9455             return new FieldList.Empty<FieldDescription.InDefinedShape>();
9456         }
9457
9458         /**
9459          * {@inheritDoc}
9460          */

9461         public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
9462             return new MethodList.Empty<MethodDescription.InDefinedShape>();
9463         }
9464
9465         /**
9466          * {@inheritDoc}
9467          */

9468         public StackSize getStackSize() {
9469             return StackSize.SINGLE;
9470         }
9471
9472         /**
9473          * {@inheritDoc}
9474          */

9475         public AnnotationList getDeclaredAnnotations() {
9476             return new AnnotationList.Empty();
9477         }
9478
9479         /**
9480          * {@inheritDoc}
9481          */

9482         public AnnotationList getInheritedAnnotations() {
9483             return new AnnotationList.Empty();
9484         }
9485
9486         /**
9487          * {@inheritDoc}
9488          */

9489         public PackageDescription getPackage() {
9490             return PackageDescription.UNDEFINED;
9491         }
9492
9493         /**
9494          * {@inheritDoc}
9495          */

9496         public String getName() {
9497             String descriptor = componentType.getDescriptor();
9498             StringBuilder stringBuilder = new StringBuilder(descriptor.length() + arity);
9499             for (int index = 0; index < arity; index++) {
9500                 stringBuilder.append('[');
9501             }
9502             for (int index = 0; index < descriptor.length(); index++) {
9503                 char character = descriptor.charAt(index);
9504                 stringBuilder.append(character == '/' ? '.' : character);
9505             }
9506             return stringBuilder.toString();
9507         }
9508
9509         /**
9510          * {@inheritDoc}
9511          */

9512         public String getDescriptor() {
9513             StringBuilder stringBuilder = new StringBuilder();
9514             for (int i = 0; i < arity; i++) {
9515                 stringBuilder.append('[');
9516             }
9517             return stringBuilder.append(componentType.getDescriptor()).toString();
9518         }
9519
9520         /**
9521          * {@inheritDoc}
9522          */

9523         public TypeDescription getDeclaringType() {
9524             return TypeDescription.UNDEFINED;
9525         }
9526
9527         /**
9528          * {@inheritDoc}
9529          */

9530         public int getModifiers() {
9531             return (getComponentType().getModifiers() & ~ARRAY_EXCLUDED) | ARRAY_IMPLIED;
9532         }
9533
9534         /**
9535          * {@inheritDoc}
9536          */

9537         public TypeList.Generic getTypeVariables() {
9538             return new TypeList.Generic.Empty();
9539         }
9540
9541         /**
9542          * {@inheritDoc}
9543          */

9544         public TypeDescription getNestHost() {
9545             return this;
9546         }
9547
9548         /**
9549          * {@inheritDoc}
9550          */

9551         public TypeList getNestMembers() {
9552             return new TypeList.Explicit(this);
9553         }
9554
9555         /**
9556          * {@inheritDoc}
9557          */

9558         public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
9559             return new RecordComponentList.Empty<RecordComponentDescription.InDefinedShape>();
9560         }
9561
9562         /**
9563          * {@inheritDoc}
9564          */

9565         public boolean isRecord() {
9566             return false;
9567         }
9568
9569         /**
9570          * {@inheritDoc}
9571          */

9572         public TypeList getPermittedSubclasses() {
9573             return new TypeList.Empty();
9574         }
9575     }
9576
9577     /**
9578      * <p>
9579      * A latent type description for a type without methods or fields.
9580      * </p>
9581      * <p>
9582      * <b>Important</b>: This type does not define most of its properties and should only be used as a simple placeholder. For more
9583      * complex placeholders, use an {@link net.bytebuddy.dynamic.scaffold.InstrumentedType.Default}.
9584      * </p>
9585      */

9586     class Latent extends AbstractBase.OfSimpleType {
9587
9588         /**
9589          * The name of the type.
9590          */

9591         private final String name;
9592
9593         /**
9594          * The modifiers of the type.
9595          */

9596         private final int modifiers;
9597
9598         /**
9599          * The super type or {@code nullif no such type exists.
9600          */

9601         private final Generic superClass;
9602
9603         /**
9604          * The interfaces that this type implements.
9605          */

9606         private final List<? extends Generic> interfaces;
9607
9608         /**
9609          * Creates a new latent type.
9610          *
9611          * @param name        The name of the type.
9612          * @param modifiers   The modifiers of the type.
9613          * @param superClass  The super type or {@code nullif no such type exists.
9614          * @param anInterface The interfaces that this type implements.
9615          */

9616         public Latent(String name, int modifiers, Generic superClass, Generic... anInterface) {
9617             this(name, modifiers, superClass, Arrays.asList(anInterface));
9618         }
9619
9620         /**
9621          * Creates a new latent type.
9622          *
9623          * @param name       The name of the type.
9624          * @param modifiers  The modifiers of the type.
9625          * @param superClass The super type or {@code nullif no such type exists.
9626          * @param interfaces The interfaces that this type implements.
9627          */

9628         public Latent(String name, int modifiers, Generic superClass, List<? extends Generic> interfaces) {
9629             this.name = name;
9630             this.modifiers = modifiers;
9631             this.superClass = superClass;
9632             this.interfaces = interfaces;
9633         }
9634
9635         /**
9636          * {@inheritDoc}
9637          */

9638         public Generic getSuperClass() {
9639             return superClass;
9640         }
9641
9642         /**
9643          * {@inheritDoc}
9644          */

9645         public TypeList.Generic getInterfaces() {
9646             return new TypeList.Generic.Explicit(interfaces);
9647         }
9648
9649         /**
9650          * {@inheritDoc}
9651          */

9652         public MethodDescription.InDefinedShape getEnclosingMethod() {
9653             throw new IllegalStateException("Cannot resolve enclosing method of a latent type description: " + this);
9654         }
9655
9656         /**
9657          * {@inheritDoc}
9658          */

9659         public TypeDescription getEnclosingType() {
9660             throw new IllegalStateException("Cannot resolve enclosing type of a latent type description: " + this);
9661         }
9662
9663         /**
9664          * {@inheritDoc}
9665          */

9666         public TypeList getDeclaredTypes() {
9667             throw new IllegalStateException("Cannot resolve inner types of a latent type description: " + this);
9668         }
9669
9670         /**
9671          * {@inheritDoc}
9672          */

9673         public boolean isAnonymousType() {
9674             throw new IllegalStateException("Cannot resolve anonymous type property of a latent type description: " + this);
9675         }
9676
9677         /**
9678          * {@inheritDoc}
9679          */

9680         public boolean isLocalType() {
9681             throw new IllegalStateException("Cannot resolve local class property of a latent type description: " + this);
9682         }
9683
9684         /**
9685          * {@inheritDoc}
9686          */

9687         public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
9688             throw new IllegalStateException("Cannot resolve declared fields of a latent type description: " + this);
9689         }
9690
9691         /**
9692          * {@inheritDoc}
9693          */

9694         public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
9695             throw new IllegalStateException("Cannot resolve declared methods of a latent type description: " + this);
9696         }
9697
9698         /**
9699          * {@inheritDoc}
9700          */

9701         public PackageDescription getPackage() {
9702             String name = getName();
9703             int index = name.lastIndexOf('.');
9704             return new PackageDescription.Simple(index == -1
9705                     ? EMPTY_NAME
9706                     : name.substring(0, index));
9707         }
9708
9709         /**
9710          * {@inheritDoc}
9711          */

9712         public AnnotationList getDeclaredAnnotations() {
9713             throw new IllegalStateException("Cannot resolve declared annotations of a latent type description: " + this);
9714         }
9715
9716         /**
9717          * {@inheritDoc}
9718          */

9719         public TypeDescription getDeclaringType() {
9720             throw new IllegalStateException("Cannot resolve declared type of a latent type description: " + this);
9721         }
9722
9723         /**
9724          * {@inheritDoc}
9725          */

9726         public int getModifiers() {
9727             return modifiers;
9728         }
9729
9730         /**
9731          * {@inheritDoc}
9732          */

9733         public String getName() {
9734             return name;
9735         }
9736
9737         /**
9738          * {@inheritDoc}
9739          */

9740         public TypeList.Generic getTypeVariables() {
9741             throw new IllegalStateException("Cannot resolve type variables of a latent type description: " + this);
9742         }
9743
9744         /**
9745          * {@inheritDoc}
9746          */

9747         public TypeDescription getNestHost() {
9748             throw new IllegalStateException("Cannot resolve nest host of a latent type description: " + this);
9749         }
9750
9751         /**
9752          * {@inheritDoc}
9753          */

9754         public TypeList getNestMembers() {
9755             throw new IllegalStateException("Cannot resolve nest mates of a latent type description: " + this);
9756         }
9757
9758         /**
9759          * {@inheritDoc}
9760          */

9761         public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
9762             throw new IllegalStateException("Cannot resolve record components of a latent type description: " + this);
9763         }
9764
9765         /**
9766          * {@inheritDoc}
9767          */

9768         public boolean isRecord() {
9769             throw new IllegalStateException("Cannot resolve record attribute of a latent type description: " + this);
9770         }
9771
9772         /**
9773          * {@inheritDoc}
9774          */

9775         public TypeList getPermittedSubclasses() {
9776             throw new IllegalStateException("Cannot resolve permitted subclasses of a latent type description: " + this);
9777         }
9778     }
9779
9780     /**
9781      * A type representation of a package description.
9782      */

9783     class ForPackageDescription extends AbstractBase.OfSimpleType {
9784
9785         /**
9786          * The package to be described as a type.
9787          */

9788         private final PackageDescription packageDescription;
9789
9790         /**
9791          * Creates a new type description of a package description.
9792          *
9793          * @param packageDescription The package to be described as a type.
9794          */

9795         public ForPackageDescription(PackageDescription packageDescription) {
9796             this.packageDescription = packageDescription;
9797         }
9798
9799         /**
9800          * {@inheritDoc}
9801          */

9802         public Generic getSuperClass() {
9803             return TypeDescription.Generic.OBJECT;
9804         }
9805
9806         /**
9807          * {@inheritDoc}
9808          */

9809         public TypeList.Generic getInterfaces() {
9810             return new TypeList.Generic.Empty();
9811         }
9812
9813         /**
9814          * {@inheritDoc}
9815          */

9816         public MethodDescription.InDefinedShape getEnclosingMethod() {
9817             return MethodDescription.UNDEFINED;
9818         }
9819
9820         /**
9821          * {@inheritDoc}
9822          */

9823         public TypeDescription getEnclosingType() {
9824             return TypeDescription.UNDEFINED;
9825         }
9826
9827         /**
9828          * {@inheritDoc}
9829          */

9830         public boolean isAnonymousType() {
9831             return false;
9832         }
9833
9834         /**
9835          * {@inheritDoc}
9836          */

9837         public boolean isLocalType() {
9838             return false;
9839         }
9840
9841         /**
9842          * {@inheritDoc}
9843          */

9844         public TypeList getDeclaredTypes() {
9845             return new TypeList.Empty();
9846         }
9847
9848         /**
9849          * {@inheritDoc}
9850          */

9851         public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
9852             return new FieldList.Empty<FieldDescription.InDefinedShape>();
9853         }
9854
9855         /**
9856          * {@inheritDoc}
9857          */

9858         public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
9859             return new MethodList.Empty<MethodDescription.InDefinedShape>();
9860         }
9861
9862         /**
9863          * {@inheritDoc}
9864          */

9865         public PackageDescription getPackage() {
9866             return packageDescription;
9867         }
9868
9869         /**
9870          * {@inheritDoc}
9871          */

9872         public AnnotationList getDeclaredAnnotations() {
9873             return packageDescription.getDeclaredAnnotations();
9874         }
9875
9876         /**
9877          * {@inheritDoc}
9878          */

9879         public TypeDescription getDeclaringType() {
9880             return TypeDescription.UNDEFINED;
9881         }
9882
9883         /**
9884          * {@inheritDoc}
9885          */

9886         public TypeList.Generic getTypeVariables() {
9887             return new TypeList.Generic.Empty();
9888         }
9889
9890         /**
9891          * {@inheritDoc}
9892          */

9893         public int getModifiers() {
9894             return PackageDescription.PACKAGE_MODIFIERS;
9895         }
9896
9897         /**
9898          * {@inheritDoc}
9899          */

9900         public String getName() {
9901             return packageDescription.getName() + "." + PackageDescription.PACKAGE_CLASS_NAME;
9902         }
9903
9904         /**
9905          * {@inheritDoc}
9906          */

9907         public TypeDescription getNestHost() {
9908             return this;
9909         }
9910
9911         /**
9912          * {@inheritDoc}
9913          */

9914         public TypeList getNestMembers() {
9915             return new TypeList.Explicit(this);
9916         }
9917
9918         /**
9919          * {@inheritDoc}
9920          */

9921         public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
9922             return new RecordComponentList.Empty<RecordComponentDescription.InDefinedShape>();
9923         }
9924
9925         /**
9926          * {@inheritDoc}
9927          */

9928         public boolean isRecord() {
9929             return false;
9930         }
9931
9932         /**
9933          * {@inheritDoc}
9934          */

9935         public TypeList getPermittedSubclasses() {
9936             return new TypeList.Empty();
9937         }
9938     }
9939
9940     /**
9941      * A delegating type description that always attempts to load the super types of a delegate type.
9942      */

9943     class SuperTypeLoading extends AbstractBase {
9944
9945         /**
9946          * The delegate type description.
9947          */

9948         private final TypeDescription delegate;
9949
9950         /**
9951          * The class loader to use for loading a super type.
9952          */

9953         private final ClassLoader classLoader;
9954
9955         /**
9956          * A delegate for loading a type.
9957          */

9958         private final ClassLoadingDelegate classLoadingDelegate;
9959
9960         /**
9961          * Creates a super type loading type description.
9962          *
9963          * @param delegate    The delegate type description.
9964          * @param classLoader The class loader to use for loading a super type.
9965          */

9966         public SuperTypeLoading(TypeDescription delegate, ClassLoader classLoader) {
9967             this(delegate, classLoader, ClassLoadingDelegate.Simple.INSTANCE);
9968         }
9969
9970         /**
9971          * Creates a super type loading type description.
9972          *
9973          * @param delegate             The delegate type description.
9974          * @param classLoader          The class loader to use for loading a super type.
9975          * @param classLoadingDelegate A delegate for loading a type.
9976          */

9977         public SuperTypeLoading(TypeDescription delegate, ClassLoader classLoader, ClassLoadingDelegate classLoadingDelegate) {
9978             this.delegate = delegate;
9979             this.classLoader = classLoader;
9980             this.classLoadingDelegate = classLoadingDelegate;
9981         }
9982
9983         /**
9984          * {@inheritDoc}
9985          */

9986         public AnnotationList getDeclaredAnnotations() {
9987             return delegate.getDeclaredAnnotations();
9988         }
9989
9990         /**
9991          * {@inheritDoc}
9992          */

9993         public int getModifiers() {
9994             return delegate.getModifiers();
9995         }
9996
9997         /**
9998          * {@inheritDoc}
9999          */

10000         public TypeList.Generic getTypeVariables() {
10001             return delegate.getTypeVariables();
10002         }
10003
10004         /**
10005          * {@inheritDoc}
10006          */

10007         public String getDescriptor() {
10008             return delegate.getDescriptor();
10009         }
10010
10011         /**
10012          * {@inheritDoc}
10013          */

10014         public String getName() {
10015             return delegate.getName();
10016         }
10017
10018         /**
10019          * {@inheritDoc}
10020          */

10021         public Generic getSuperClass() {
10022             Generic superClass = delegate.getSuperClass();
10023             return superClass == null
10024                     ? Generic.UNDEFINED
10025                     : new ClassLoadingTypeProjection(superClass, classLoader, classLoadingDelegate);
10026         }
10027
10028         /**
10029          * {@inheritDoc}
10030          */

10031         public TypeList.Generic getInterfaces() {
10032             return new ClassLoadingTypeList(delegate.getInterfaces(), classLoader, classLoadingDelegate);
10033         }
10034
10035         /**
10036          * {@inheritDoc}
10037          */

10038         public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
10039             return delegate.getDeclaredFields();
10040         }
10041
10042         /**
10043          * {@inheritDoc}
10044          */

10045         public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
10046             return delegate.getDeclaredMethods();
10047         }
10048
10049         /**
10050          * {@inheritDoc}
10051          */

10052         public StackSize getStackSize() {
10053             return delegate.getStackSize();
10054         }
10055
10056         /**
10057          * {@inheritDoc}
10058          */

10059         public boolean isArray() {
10060             return delegate.isArray();
10061         }
10062
10063         /**
10064          * {@inheritDoc}
10065          */

10066         public boolean isPrimitive() {
10067             return delegate.isPrimitive();
10068         }
10069
10070         /**
10071          * {@inheritDoc}
10072          */

10073         public TypeDescription getComponentType() {
10074             return delegate.getComponentType();
10075         }
10076
10077         /**
10078          * {@inheritDoc}
10079          */

10080         public TypeDescription getDeclaringType() {
10081             return delegate.getDeclaringType();
10082         }
10083
10084         /**
10085          * {@inheritDoc}
10086          */

10087         public TypeList getDeclaredTypes() {
10088             return delegate.getDeclaredTypes();
10089         }
10090
10091         /**
10092          * {@inheritDoc}
10093          */

10094         public MethodDescription.InDefinedShape getEnclosingMethod() {
10095             return delegate.getEnclosingMethod();
10096         }
10097
10098         /**
10099          * {@inheritDoc}
10100          */

10101         public TypeDescription getEnclosingType() {
10102             return delegate.getEnclosingType();
10103         }
10104
10105         /**
10106          * {@inheritDoc}
10107          */

10108         public String getSimpleName() {
10109             return delegate.getSimpleName();
10110         }
10111
10112         /**
10113          * {@inheritDoc}
10114          */

10115         public String getCanonicalName() {
10116             return delegate.getCanonicalName();
10117         }
10118
10119         /**
10120          * {@inheritDoc}
10121          */

10122         public boolean isAnonymousType() {
10123             return delegate.isAnonymousType();
10124         }
10125
10126         /**
10127          * {@inheritDoc}
10128          */

10129         public boolean isLocalType() {
10130             return delegate.isLocalType();
10131         }
10132
10133         /**
10134          * {@inheritDoc}
10135          */

10136         public PackageDescription getPackage() {
10137             return delegate.getPackage();
10138         }
10139
10140         /**
10141          * {@inheritDoc}
10142          */

10143         public TypeDescription getNestHost() {
10144             return delegate.getNestHost();
10145         }
10146
10147         /**
10148          * {@inheritDoc}
10149          */

10150         public TypeList getNestMembers() {
10151             return delegate.getNestMembers();
10152         }
10153
10154         /**
10155          * {@inheritDoc}
10156          */

10157         public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
10158             return delegate.getRecordComponents();
10159         }
10160
10161         /**
10162          * {@inheritDoc}
10163          */

10164         public boolean isRecord() {
10165             return delegate.isRecord();
10166         }
10167
10168         /**
10169          * {@inheritDoc}
10170          */

10171         public TypeList getPermittedSubclasses() {
10172             return delegate.getPermittedSubclasses();
10173         }
10174
10175         /**
10176          * A class loading delegate is responsible for resolving a type given a class loader and a type name.
10177          */

10178         public interface ClassLoadingDelegate {
10179
10180             /**
10181              * Loads a type.
10182              *
10183              * @param name        The type's name,
10184              * @param classLoader The class loader to load the type from which might be {@code null} to represent the bootstrap class loader.
10185              * @return The loaded type.
10186              * @throws ClassNotFoundException If the type could not be found.
10187              */

10188             Class<?> load(String name, ClassLoader classLoader) throws ClassNotFoundException;
10189
10190             /**
10191              * A simple class loading delegate that simply loads a type.
10192              */

10193             enum Simple implements ClassLoadingDelegate {
10194
10195                 /**
10196                  * The singleton instance.
10197                  */

10198                 INSTANCE;
10199
10200                 /**
10201                  * {@inheritDoc}
10202                  */

10203                 public Class<?> load(String name, ClassLoader classLoader) throws ClassNotFoundException {
10204                     return Class.forName(name, false, classLoader);
10205                 }
10206             }
10207         }
10208
10209         /**
10210          * A type projection that attempts to load any super type of the delegate type.
10211          */

10212         protected static class ClassLoadingTypeProjection extends TypeDescription.Generic.LazyProjection {
10213
10214             /**
10215              * The delegate type description.
10216              */

10217             private final Generic delegate;
10218
10219             /**
10220              * The class loader to use for loading types which might be {@code null} to represent the bootstrap class loader.
10221              */

10222             private final ClassLoader classLoader;
10223
10224             /**
10225              * A delegate for loading a type.
10226              */

10227             private final ClassLoadingDelegate classLoadingDelegate;
10228
10229             /**
10230              * Creates a class loading type description.
10231              *
10232              * @param delegate             The delegate type description.
10233              * @param classLoader          The class loader to use for loading types which might be {@code null} to represent the bootstrap class loader.
10234              * @param classLoadingDelegate A delegate for loading a type.
10235              */

10236             protected ClassLoadingTypeProjection(Generic delegate, ClassLoader classLoader, ClassLoadingDelegate classLoadingDelegate) {
10237                 this.delegate = delegate;
10238                 this.classLoader = classLoader;
10239                 this.classLoadingDelegate = classLoadingDelegate;
10240             }
10241
10242             /**
10243              * {@inheritDoc}
10244              */

10245             public AnnotationList getDeclaredAnnotations() {
10246                 return delegate.getDeclaredAnnotations();
10247             }
10248
10249             /**
10250              * {@inheritDoc}
10251              */

10252             @CachedReturnPlugin.Enhance("erasure")
10253             public TypeDescription asErasure() {
10254                 try {
10255                     return ForLoadedType.of(classLoadingDelegate.load(delegate.asErasure().getName(), classLoader));
10256                 } catch (ClassNotFoundException ignored) {
10257                     return delegate.asErasure();
10258                 }
10259             }
10260
10261             @Override
10262             protected Generic resolve() {
10263                 return delegate;
10264             }
10265
10266             /**
10267              * {@inheritDoc}
10268              */

10269             @CachedReturnPlugin.Enhance("superClass")
10270             public Generic getSuperClass() {
10271                 Generic superClass = delegate.getSuperClass();
10272                 if (superClass == null) {
10273                     return Generic.UNDEFINED;
10274                 } else {
10275                     try {
10276                         return new ClassLoadingTypeProjection(superClass,
10277                                 classLoadingDelegate.load(delegate.asErasure().getName(), classLoader).getClassLoader(),
10278                                 classLoadingDelegate);
10279                     } catch (ClassNotFoundException ignored) {
10280                         return superClass;
10281                     }
10282                 }
10283             }
10284
10285             /**
10286              * {@inheritDoc}
10287              */

10288             @CachedReturnPlugin.Enhance("interfaces")
10289             public TypeList.Generic getInterfaces() {
10290                 TypeList.Generic interfaces = delegate.getInterfaces();
10291                 try {
10292                     return new ClassLoadingTypeList(interfaces,
10293                             classLoadingDelegate.load(delegate.asErasure().getName(), classLoader).getClassLoader(),
10294                             classLoadingDelegate);
10295                 } catch (ClassNotFoundException ignored) {
10296                     return interfaces;
10297                 }
10298             }
10299
10300             /**
10301              * {@inheritDoc}
10302              */

10303             public Iterator<TypeDefinition> iterator() {
10304                 return new SuperClassIterator(this);
10305             }
10306         }
10307
10308         /**
10309          * A type list that attempts loading any type.
10310          */

10311         protected static class ClassLoadingTypeList extends TypeList.Generic.AbstractBase {
10312
10313             /**
10314              * The delegate type list.
10315              */

10316             private final TypeList.Generic delegate;
10317
10318             /**
10319              * The class loader to use for loading types which might be {@code null} to represent the bootstrap class loader.
10320              */

10321             private final ClassLoader classLoader;
10322
10323             /**
10324              * A delegate for loading a type.
10325              */

10326             private final ClassLoadingDelegate classLoadingDelegate;
10327
10328             /**
10329              * Creates a class loading type list.
10330              *
10331              * @param delegate             The delegate type list.
10332              * @param classLoader          The class loader to use for loading types which might be {@code null} to represent the bootstrap class loader.
10333              * @param classLoadingDelegate A delegate for loading a type.
10334              */

10335             protected ClassLoadingTypeList(TypeList.Generic delegate, ClassLoader classLoader, ClassLoadingDelegate classLoadingDelegate) {
10336                 this.delegate = delegate;
10337                 this.classLoader = classLoader;
10338                 this.classLoadingDelegate = classLoadingDelegate;
10339             }
10340
10341             /**
10342              * {@inheritDoc}
10343              */

10344             public Generic get(int index) {
10345                 return new ClassLoadingTypeProjection(delegate.get(index), classLoader, classLoadingDelegate);
10346             }
10347
10348             /**
10349              * {@inheritDoc}
10350              */

10351             public int size() {
10352                 return delegate.size();
10353             }
10354         }
10355     }
10356 }
10357