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.pool;
17
18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 import net.bytebuddy.build.CachedReturnPlugin;
20 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
21 import net.bytebuddy.description.TypeVariableSource;
22 import net.bytebuddy.description.annotation.AnnotationDescription;
23 import net.bytebuddy.description.annotation.AnnotationList;
24 import net.bytebuddy.description.annotation.AnnotationValue;
25 import net.bytebuddy.description.enumeration.EnumerationDescription;
26 import net.bytebuddy.description.field.FieldDescription;
27 import net.bytebuddy.description.field.FieldList;
28 import net.bytebuddy.description.method.MethodDescription;
29 import net.bytebuddy.description.method.MethodList;
30 import net.bytebuddy.description.method.ParameterDescription;
31 import net.bytebuddy.description.method.ParameterList;
32 import net.bytebuddy.description.type.*;
33 import net.bytebuddy.dynamic.ClassFileLocator;
34 import net.bytebuddy.implementation.bytecode.StackSize;
35 import net.bytebuddy.utility.JavaType;
36 import net.bytebuddy.utility.OpenedClassReader;
37 import net.bytebuddy.jar.asm.*;
38 import net.bytebuddy.jar.asm.signature.SignatureReader;
39 import net.bytebuddy.jar.asm.signature.SignatureVisitor;
40
41 import java.io.IOException;
42 import java.lang.annotation.Annotation;
43 import java.lang.reflect.GenericSignatureFormatError;
44 import java.util.*;
45 import java.util.concurrent.ConcurrentHashMap;
46 import java.util.concurrent.ConcurrentMap;
47
48 import static net.bytebuddy.matcher.ElementMatchers.*;
49
50 /**
51  * A type pool allows the retrieval of {@link TypeDescription} by its name.
52  */

53 public interface TypePool {
54
55     /**
56      * Locates and describes the given type by its name.
57      *
58      * @param name The name of the type to describe. The name is to be written as when calling {@link Object#toString()}
59      *             on a loaded {@link java.lang.Class}.
60      * @return A resolution of the type to describe. If the type to be described was found, the returned
61      * {@link net.bytebuddy.pool.TypePool.Resolution} represents this type. Otherwise, an illegal resolution is returned.
62      */

63     Resolution describe(String name);
64
65     /**
66      * Clears this type pool's cache.
67      */

68     void clear();
69
70     /**
71      * A resolution of a {@link net.bytebuddy.pool.TypePool} which was queried for a description.
72      */

73     interface Resolution {
74
75         /**
76          * Determines if this resolution represents a fully-resolved {@link TypeDescription}.
77          *
78          * @return {@code trueif the queried type could be resolved.
79          */

80         boolean isResolved();
81
82         /**
83          * Resolves this resolution to a {@link TypeDescription}. If this resolution is unresolved, this
84          * method throws an exception either upon invoking this method or upon invoking at least one method
85          * of the returned type description.
86          *
87          * @return The type description that is represented by this resolution.
88          */

89         TypeDescription resolve();
90
91         /**
92          * A simple resolution that represents a given {@link TypeDescription}.
93          */

94         @HashCodeAndEqualsPlugin.Enhance
95         class Simple implements Resolution {
96
97             /**
98              * The represented type description.
99              */

100             private final TypeDescription typeDescription;
101
102             /**
103              * Creates a new successful resolution of a given type description.
104              *
105              * @param typeDescription The represented type description.
106              */

107             public Simple(TypeDescription typeDescription) {
108                 this.typeDescription = typeDescription;
109             }
110
111             /**
112              * {@inheritDoc}
113              */

114             public boolean isResolved() {
115                 return true;
116             }
117
118             /**
119              * {@inheritDoc}
120              */

121             public TypeDescription resolve() {
122                 return typeDescription;
123             }
124         }
125
126         /**
127          * A canonical representation of a non-successful resolution of a {@link net.bytebuddy.pool.TypePool}.
128          */

129         @HashCodeAndEqualsPlugin.Enhance
130         class Illegal implements Resolution {
131
132             /**
133              * The name of the unresolved type.
134              */

135             private final String name;
136
137             /**
138              * Creates a new illegal resolution.
139              *
140              * @param name The name of the unresolved type.
141              */

142             public Illegal(String name) {
143                 this.name = name;
144             }
145
146             /**
147              * {@inheritDoc}
148              */

149             public boolean isResolved() {
150                 return false;
151             }
152
153             /**
154              * {@inheritDoc}
155              */

156             public TypeDescription resolve() {
157                 throw new IllegalStateException("Cannot resolve type description for " + name);
158             }
159         }
160     }
161
162     /**
163      * A cache provider for a {@link net.bytebuddy.pool.TypePool}.
164      */

165     interface CacheProvider {
166
167         /**
168          * The value that is returned on a cache-miss.
169          */

170         Resolution UNRESOLVED = null;
171
172         /**
173          * Attempts to find a resolution in this cache.
174          *
175          * @param name The name of the type to describe.
176          * @return A resolution of the type or {@code nullif no such resolution can be found in the cache..
177          */

178         Resolution find(String name);
179
180         /**
181          * Registers a resolution in this cache. If a resolution to the given name already exists in the
182          * cache, it should be discarded.
183          *
184          * @param name       The name of the type that is to be registered.
185          * @param resolution The resolution to register.
186          * @return The oldest version of a resolution that is currently registered in the cache which might
187          * be the given resolution or another resolution that was previously registered.
188          */

189         Resolution register(String name, Resolution resolution);
190
191         /**
192          * Clears this cache.
193          */

194         void clear();
195
196         /**
197          * A non-operational cache that does not store any type descriptions.
198          */

199         enum NoOp implements CacheProvider {
200
201             /**
202              * The singleton instance.
203              */

204             INSTANCE;
205
206             /**
207              * {@inheritDoc}
208              */

209             public Resolution find(String name) {
210                 return UNRESOLVED;
211             }
212
213             /**
214              * {@inheritDoc}
215              */

216             public Resolution register(String name, Resolution resolution) {
217                 return resolution;
218             }
219
220             /**
221              * {@inheritDoc}
222              */

223             public void clear() {
224                 /* do nothing */
225             }
226         }
227
228         /**
229          * A simple, thread-safe type cache based on a {@link java.util.concurrent.ConcurrentHashMap}.
230          */

231         class Simple implements CacheProvider {
232
233             /**
234              * A map containing all cached resolutions by their names.
235              */

236             private final ConcurrentMap<String, Resolution> storage;
237
238             /**
239              * Creates a new simple cache.
240              */

241             public Simple() {
242                 this(new ConcurrentHashMap<String, Resolution>());
243             }
244
245             /**
246              * Creates a new simple cache.
247              *
248              * @param storage A map that is used for locating and storing resolutions.
249              */

250             public Simple(ConcurrentMap<String, Resolution> storage) {
251                 this.storage = storage;
252             }
253
254             /**
255              * Returns a simple cache provider that is prepopulated with the {@link Object} type.
256              *
257              * @return A simple cache provider that is prepopulated with the {@link Object} type.
258              */

259             public static CacheProvider withObjectType() {
260                 CacheProvider cacheProvider = new Simple();
261                 cacheProvider.register(Object.class.getName(), new Resolution.Simple(TypeDescription.OBJECT));
262                 return cacheProvider;
263             }
264
265             /**
266              * {@inheritDoc}
267              */

268             public Resolution find(String name) {
269                 return storage.get(name);
270             }
271
272             /**
273              * {@inheritDoc}
274              */

275             public Resolution register(String name, Resolution resolution) {
276                 Resolution cached = storage.putIfAbsent(name, resolution);
277                 return cached == null
278                         ? resolution
279                         : cached;
280             }
281
282             /**
283              * {@inheritDoc}
284              */

285             public void clear() {
286                 storage.clear();
287             }
288
289             /**
290              * Returns the underlying storage map of this simple cache provider.
291              *
292              * @return A map containing all cached resolutions by their names.
293              */

294             public ConcurrentMap<String, Resolution> getStorage() {
295                 return storage;
296             }
297         }
298     }
299
300     /**
301      * An empty type pool that cannot describe any type.
302      */

303     enum Empty implements TypePool {
304
305         /**
306          * The singleton instance.
307          */

308         INSTANCE;
309
310         /**
311          * {@inheritDoc}
312          */

313         public Resolution describe(String name) {
314             return new Resolution.Illegal(name);
315         }
316
317         /**
318          * {@inheritDoc}
319          */

320         public void clear() {
321             /* do nothing */
322         }
323     }
324
325     /**
326      * A base implementation of a {@link net.bytebuddy.pool.TypePool} that is managing a cache provider and
327      * that handles the description of array and primitive types.
328      */

329     @HashCodeAndEqualsPlugin.Enhance
330     abstract class AbstractBase implements TypePool {
331
332         /**
333          * A map of primitive types by their name.
334          */

335         protected static final Map<String, TypeDescription> PRIMITIVE_TYPES;
336
337         /**
338          * A map of primitive types by their descriptor.
339          */

340         protected static final Map<String, String> PRIMITIVE_DESCRIPTORS;
341
342         /**
343          * The array symbol as used by Java descriptors.
344          */

345         private static final String ARRAY_SYMBOL = "[";
346
347         /*
348          * Initializes the maps of primitive type names and descriptors.
349          */

350         static {
351             Map<String, TypeDescription> primitiveTypes = new HashMap<String, TypeDescription>();
352             Map<String, String> primitiveDescriptors = new HashMap<String, String>();
353             for (Class<?> primitiveType : new Class<?>[]{boolean.class,
354                     byte.class,
355                     short.class,
356                     char.class,
357                     int.class,
358                     long.class,
359                     float.class,
360                     double.class,
361                     void.class}) {
362                 primitiveTypes.put(primitiveType.getName(), TypeDescription.ForLoadedType.of(primitiveType));
363                 primitiveDescriptors.put(Type.getDescriptor(primitiveType), primitiveType.getName());
364             }
365             PRIMITIVE_TYPES = Collections.unmodifiableMap(primitiveTypes);
366             PRIMITIVE_DESCRIPTORS = Collections.unmodifiableMap(primitiveDescriptors);
367         }
368
369         /**
370          * The cache provider of this instance.
371          */

372         protected final CacheProvider cacheProvider;
373
374         /**
375          * Creates a new instance.
376          *
377          * @param cacheProvider The cache provider to be used.
378          */

379         protected AbstractBase(CacheProvider cacheProvider) {
380             this.cacheProvider = cacheProvider;
381         }
382
383         /**
384          * {@inheritDoc}
385          */

386         public Resolution describe(String name) {
387             if (name.contains("/")) {
388                 throw new IllegalArgumentException(name + " contains the illegal character '/'");
389             }
390             int arity = 0;
391             while (name.startsWith(ARRAY_SYMBOL)) {
392                 arity++;
393                 name = name.substring(1);
394             }
395             if (arity > 0) {
396                 String primitiveName = PRIMITIVE_DESCRIPTORS.get(name);
397                 name = primitiveName == null
398                         ? name.substring(1, name.length() - 1)
399                         : primitiveName;
400             }
401             TypeDescription typeDescription = PRIMITIVE_TYPES.get(name);
402             Resolution resolution = typeDescription == null
403                     ? cacheProvider.find(name)
404                     : new Resolution.Simple(typeDescription);
405             if (resolution == null) {
406                 resolution = doCache(name, doDescribe(name));
407             }
408             return ArrayTypeResolution.of(resolution, arity);
409         }
410
411         /**
412          * Writes the resolution to the cache. This method should be overridden if the directly
413          * resolved instance should not be added to the cache.
414          *
415          * @param name       The name of the type.
416          * @param resolution The resolution for this type.
417          * @return The actual resolution for the type of this name that is stored in the cache.
418          */

419         protected Resolution doCache(String name, Resolution resolution) {
420             return cacheProvider.register(name, resolution);
421         }
422
423         /**
424          * {@inheritDoc}
425          */

426         public void clear() {
427             cacheProvider.clear();
428         }
429
430         /**
431          * Determines a resolution to a non-primitive, non-array type.
432          *
433          * @param name The name of the type to describe.
434          * @return A resolution to the type to describe.
435          */

436         protected abstract Resolution doDescribe(String name);
437
438         /**
439          * A lazy representation of the component type of an array.
440          */

441         protected interface ComponentTypeReference {
442
443             /**
444              * Lazily returns the binary name of the array component type of an annotation value.
445              *
446              * @return The binary name of the component type.
447              */

448             String lookup();
449         }
450
451         /**
452          * Implements a hierarchical view of type pools, similarly to class loader hierarchies. For every lookup, the parent type pool
453          * is asked first if it can resolve a type. Only if the parent (and potentially its parents) are unable to resolve a type,
454          * this instance is queried for a type description.
455          */

456         @HashCodeAndEqualsPlugin.Enhance
457         public abstract static class Hierarchical extends AbstractBase {
458
459             /**
460              * The parent type pool.
461              */

462             private final TypePool parent;
463
464             /**
465              * Creates a hierarchical type pool.
466              *
467              * @param cacheProvider The cache provider to be used.
468              * @param parent        The parent type pool to be used.
469              */

470             protected Hierarchical(CacheProvider cacheProvider, TypePool parent) {
471                 super(cacheProvider);
472                 this.parent = parent;
473             }
474
475             /**
476              * {@inheritDoc}
477              */

478             public Resolution describe(String name) {
479                 Resolution resolution = parent.describe(name);
480                 return resolution.isResolved()
481                         ? resolution
482                         : super.describe(name);
483             }
484
485             /**
486              * {@inheritDoc}
487              */

488             public void clear() {
489                 try {
490                     parent.clear();
491                 } finally {
492                     super.clear();
493                 }
494             }
495         }
496
497         /**
498          * A resolution for a type that, if resolved, represents an array type.
499          */

500         @HashCodeAndEqualsPlugin.Enhance
501         protected static class ArrayTypeResolution implements Resolution {
502
503             /**
504              * The underlying resolution that is represented by this instance.
505              */

506             private final Resolution resolution;
507
508             /**
509              * The arity of the represented array.
510              */

511             private final int arity;
512
513             /**
514              * Creates a wrapper for another resolution that, if resolved, represents an array type.
515              *
516              * @param resolution The underlying resolution that is represented by this instance.
517              * @param arity      The arity of the represented array.
518              */

519             protected ArrayTypeResolution(Resolution resolution, int arity) {
520                 this.resolution = resolution;
521                 this.arity = arity;
522             }
523
524             /**
525              * Creates a wrapper for another resolution that, if resolved, represents an array type. The wrapper
526              * is only created if the arity is not zero. If the arity is zero, the given resolution is simply
527              * returned instead.
528              *
529              * @param resolution The underlying resolution that is represented by this instance.
530              * @param arity      The arity of the represented array.
531              * @return A wrapper for another resolution that, if resolved, represents an array type or the
532              * given resolution if the given arity is zero.
533              */

534             protected static Resolution of(Resolution resolution, int arity) {
535                 return arity == 0
536                         ? resolution
537                         : new ArrayTypeResolution(resolution, arity);
538             }
539
540             /**
541              * {@inheritDoc}
542              */

543             public boolean isResolved() {
544                 return resolution.isResolved();
545             }
546
547             /**
548              * {@inheritDoc}
549              */

550             public TypeDescription resolve() {
551                 return TypeDescription.ArrayProjection.of(resolution.resolve(), arity);
552             }
553         }
554     }
555
556     /**
557      * <p>
558      * A default implementation of a {@link net.bytebuddy.pool.TypePool} that models binary data in the Java byte code format
559      * into a {@link TypeDescription}. The data lookup is delegated to a {@link net.bytebuddy.dynamic.ClassFileLocator}.
560      * </p>
561      * <p>
562      * {@link Resolution}s that are produced by this type pool are either fully resolved or not resolved at all.
563      * </p>
564      */

565     @HashCodeAndEqualsPlugin.Enhance
566     class Default extends AbstractBase.Hierarchical {
567
568         /**
569          * Indicates that a visited method should be ignored.
570          */

571         private static final MethodVisitor IGNORE_METHOD = null;
572
573         /**
574          * The locator to query for finding binary data of a type.
575          */

576         protected final ClassFileLocator classFileLocator;
577
578         /**
579          * The reader mode to apply by this default type pool.
580          */

581         protected final ReaderMode readerMode;
582
583         /**
584          * Creates a new default type pool without a parent pool.
585          *
586          * @param cacheProvider    The cache provider to be used.
587          * @param classFileLocator The class file locator to be used.
588          * @param readerMode       The reader mode to apply by this default type pool.
589          */

590         public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode) {
591             this(cacheProvider, classFileLocator, readerMode, Empty.INSTANCE);
592         }
593
594         /**
595          * Creates a new default type pool.
596          *
597          * @param cacheProvider    The cache provider to be used.
598          * @param classFileLocator The class file locator to be used.
599          * @param readerMode       The reader mode to apply by this default type pool.
600          * @param parentPool       The parent type pool.
601          */

602         public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, TypePool parentPool) {
603             super(cacheProvider, parentPool);
604             this.classFileLocator = classFileLocator;
605             this.readerMode = readerMode;
606         }
607
608         /**
609          * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the system class
610          * loader. The returned instance is configured to use a fast reading mode and a simple cache.
611          *
612          * @return A type pool that reads its data from the system class loader.
613          */

614         public static TypePool ofSystemLoader() {
615             return of(ClassFileLocator.ForClassLoader.ofSystemLoader());
616         }
617
618         /**
619          * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the plaform class
620          * loader. The returned instance is configured to use a fast reading mode and a simple cache. If the current
621          * VM is of version 8 or older, the extension class loader is represented instead.
622          *
623          * @return A type pool that reads its data from the platform class path.
624          */

625         public static TypePool ofPlatformLoader() {
626             return of(ClassFileLocator.ForClassLoader.ofPlatformLoader());
627         }
628
629         /**
630          * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the boot class
631          * loader. The returned instance is configured to use a fast reading mode and a simple cache.
632          *
633          * @return A type pool that reads its data from the boot class loader.
634          */

635         public static TypePool ofBootLoader() {
636             return of(ClassFileLocator.ForClassLoader.ofBootLoader());
637         }
638
639         /**
640          * Returns a type pool for the provided class loader.
641          *
642          * @param classLoader The class loader for which this class pool is representing types.
643          * @return An appropriate type pool.
644          */

645         public static TypePool of(ClassLoader classLoader) {
646             return of(ClassFileLocator.ForClassLoader.of(classLoader));
647         }
648
649         /**
650          * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the supplied class
651          * file locator. The returned instance is configured to use a fast reading mode and a simple cache.
652          *
653          * @param classFileLocator The class file locator to use.
654          * @return A type pool that reads its data from the system class path.
655          */

656         public static TypePool of(ClassFileLocator classFileLocator) {
657             return new Default(new CacheProvider.Simple(), classFileLocator, ReaderMode.FAST);
658         }
659
660         @Override
661         protected Resolution doDescribe(String name) {
662             try {
663                 ClassFileLocator.Resolution resolution = classFileLocator.locate(name);
664                 return resolution.isResolved()
665                         ? new Resolution.Simple(parse(resolution.resolve()))
666                         : new Resolution.Illegal(name);
667             } catch (IOException exception) {
668                 throw new IllegalStateException("Error while reading class file", exception);
669             }
670         }
671
672         /**
673          * Parses a binary representation and transforms it into a type description.
674          *
675          * @param binaryRepresentation The binary data to be parsed.
676          * @return A type description of the binary data.
677          */

678         private TypeDescription parse(byte[] binaryRepresentation) {
679             ClassReader classReader = OpenedClassReader.of(binaryRepresentation);
680             TypeExtractor typeExtractor = new TypeExtractor();
681             classReader.accept(typeExtractor, readerMode.getFlags());
682             return typeExtractor.toTypeDescription();
683         }
684
685         /**
686          * Determines the granularity of the class file parsing that is conducted by a {@link net.bytebuddy.pool.TypePool.Default}.
687          */

688         public enum ReaderMode {
689
690             /**
691              * The extended reader mode parses the code segment of each method in order to detect parameter names
692              * that are only stored in a method's debugging information but are not explicitly included.
693              */

694             EXTENDED(ClassReader.SKIP_FRAMES),
695
696             /**
697              * The fast reader mode skips the code segment of each method and cannot detect parameter names that are
698              * only contained within the debugging information. This mode still detects explicitly included method
699              * parameter names.
700              */

701             FAST(ClassReader.SKIP_CODE);
702
703             /**
704              * The flags to provide to a {@link ClassReader} for parsing a file.
705              */

706             private final int flags;
707
708             /**
709              * Creates a new reader mode constant.
710              *
711              * @param flags The flags to provide to a {@link ClassReader} for parsing a file.
712              */

713             ReaderMode(int flags) {
714                 this.flags = flags;
715             }
716
717             /**
718              * Returns the flags to provide to a {@link ClassReader} for parsing a file.
719              *
720              * @return The flags to provide to a {@link ClassReader} for parsing a file.
721              */

722             protected int getFlags() {
723                 return flags;
724             }
725
726             /**
727              * Determines if this reader mode represents extended reading.
728              *
729              * @return {@code trueif this reader mode represents extended reading.
730              */

731             public boolean isExtended() {
732                 return this == EXTENDED;
733             }
734         }
735
736         /**
737          * <p>
738          * A variant of {@link TypePool.Default} that resolves type descriptions lazily. A lazy resolution respects this type
739          * pool's {@link CacheProvider} but requeries this cache pool for every access of a property of a {@link TypeDescription}.
740          * </p>
741          * <p>
742          * {@link Resolution}s of this type pool are only fully resolved if a property that is not the type's name is required.
743          * </p>
744          */

745         public static class WithLazyResolution extends Default {
746
747             /**
748              * Creates a new default type pool with lazy resolution and without a parent pool.
749              *
750              * @param cacheProvider    The cache provider to be used.
751              * @param classFileLocator The class file locator to be used.
752              * @param readerMode       The reader mode to apply by this default type pool.
753              */

754             public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode) {
755                 this(cacheProvider, classFileLocator, readerMode, Empty.INSTANCE);
756             }
757
758             /**
759              * Creates a new default type pool with lazy resolution.
760              *
761              * @param cacheProvider    The cache provider to be used.
762              * @param classFileLocator The class file locator to be used.
763              * @param readerMode       The reader mode to apply by this default type pool.
764              * @param parentPool       The parent type pool.
765              */

766             public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, TypePool parentPool) {
767                 super(cacheProvider, classFileLocator, readerMode, parentPool);
768             }
769
770             /**
771              * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the system class
772              * loader. The returned instance is configured to use a fast reading mode and a simple cache.
773              *
774              * @return A type pool that reads its data from the system class loader.
775              */

776             public static TypePool ofSystemLoader() {
777                 return of(ClassFileLocator.ForClassLoader.ofSystemLoader());
778             }
779
780             /**
781              * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the platform class
782              * loader. The returned instance is configured to use a fast reading mode and a simple cache. If the current VM is Java 8 or older,
783              * the type pool represents the extension class loader.
784              *
785              * @return A type pool that reads its data from the boot class loader.
786              */

787             public static TypePool ofPlatformLoader() {
788                 return of(ClassFileLocator.ForClassLoader.ofPlatformLoader());
789             }
790
791             /**
792              * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the boot class
793              * loader. The returned instance is configured to use a fast reading mode and a simple cache.
794              *
795              * @return A type pool that reads its data from the boot class loader.
796              */

797             public static TypePool ofBootLoader() {
798                 return of(ClassFileLocator.ForClassLoader.ofBootLoader());
799             }
800
801             /**
802              * Returns a default {@link TypePool} with lazy resolution for the provided class loader.
803              *
804              * @param classLoader The class loader for which this class pool is representing types.
805              * @return An appropriate type pool.
806              */

807             public static TypePool of(ClassLoader classLoader) {
808                 return of(ClassFileLocator.ForClassLoader.of(classLoader));
809             }
810
811             /**
812              * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the supplied class
813              * file locator. The returned instance is configured to use a fast reading mode and a simple cache.
814              *
815              * @param classFileLocator The class file locator to use.
816              * @return A type pool that reads its data from the system class path.
817              */

818             public static TypePool of(ClassFileLocator classFileLocator) {
819                 return new WithLazyResolution(new CacheProvider.Simple(), classFileLocator, ReaderMode.FAST);
820             }
821
822             @Override
823             protected Resolution doDescribe(String name) {
824                 return new LazyResolution(name);
825             }
826
827             /**
828              * {@inheritDoc}
829              */

830             protected Resolution doCache(String name, Resolution resolution) {
831                 return resolution;
832             }
833
834             /**
835              * Non-lazily resolves a type name.
836              *
837              * @param name The name of the type to resolve.
838              * @return The resolution for the type of this name.
839              */

840             protected Resolution doResolve(String name) {
841                 Resolution resolution = cacheProvider.find(name);
842                 if (resolution == null) {
843                     resolution = cacheProvider.register(name, WithLazyResolution.super.doDescribe(name));
844                 }
845                 return resolution;
846             }
847
848             /**
849              * A lazy resolution of a type that the enclosing type pool attempts to resolve.
850              */

851             @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
852             protected class LazyResolution implements Resolution {
853
854                 /**
855                  * The type's name.
856                  */

857                 private final String name;
858
859                 /**
860                  * Creates a new lazy resolution.
861                  *
862                  * @param name The type's name.
863                  */

864                 protected LazyResolution(String name) {
865                     this.name = name;
866                 }
867
868                 /**
869                  * {@inheritDoc}
870                  */

871                 public boolean isResolved() {
872                     return doResolve(name).isResolved();
873                 }
874
875                 /**
876                  * {@inheritDoc}
877                  */

878                 public TypeDescription resolve() {
879                     return new LazyTypeDescription(name);
880                 }
881             }
882
883             /**
884              * A lazy type description that resolves any property that is not the name only when requested.
885              */

886             protected class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType.WithDelegation {
887
888                 /**
889                  * The type's name.
890                  */

891                 private final String name;
892
893                 /**
894                  * Creates a new lazy type description.
895                  *
896                  * @param name The type's name.
897                  */

898                 protected LazyTypeDescription(String name) {
899                     this.name = name;
900                 }
901
902                 /**
903                  * {@inheritDoc}
904                  */

905                 public String getName() {
906                     return name;
907                 }
908
909                 @Override
910                 @CachedReturnPlugin.Enhance("delegate")
911                 protected TypeDescription delegate() {
912                     return doResolve(name).resolve();
913                 }
914             }
915         }
916
917         /**
918          * An annotation registrant implements a visitor pattern for reading an unknown amount of values of annotations.
919          */

920         protected interface AnnotationRegistrant {
921
922             /**
923              * Registers an annotation value.
924              *
925              * @param name            The name of the annotation value.
926              * @param annotationValue The value of the annotation.
927              */

928             void register(String name, AnnotationValue<?, ?> annotationValue);
929
930             /**
931              * Called once all annotation values are visited.
932              */

933             void onComplete();
934
935             /**
936              * An abstract base implementation of an annotation registrant.
937              */

938             abstract class AbstractBase implements AnnotationRegistrant {
939
940                 /**
941                  * The annotation descriptor.
942                  */

943                 private final String descriptor;
944
945                 /**
946                  * The values that were collected so far.
947                  */

948                 private final Map<String, AnnotationValue<?, ?>> values;
949
950                 /**
951                  * Creates a new annotation registrant.
952                  *
953                  * @param descriptor The annotation descriptor.
954                  */

955                 protected AbstractBase(String descriptor) {
956                     this.descriptor = descriptor;
957                     values = new HashMap<String, AnnotationValue<?, ?>>();
958                 }
959
960                 /**
961                  * {@inheritDoc}
962                  */

963                 public void register(String name, AnnotationValue<?, ?> annotationValue) {
964                     values.put(name, annotationValue);
965                 }
966
967                 /**
968                  * {@inheritDoc}
969                  */

970                 public void onComplete() {
971                     getTokens().add(new LazyTypeDescription.AnnotationToken(descriptor, values));
972                 }
973
974                 /**
975                  * Returns the token list for this collector.
976                  *
977                  * @return The token list for this collector.
978                  */

979                 protected abstract List<LazyTypeDescription.AnnotationToken> getTokens();
980
981                 /**
982                  * A base implementation for a collector for a type variable.
983                  */

984                 protected abstract static class ForTypeVariable extends AbstractBase {
985
986                     /**
987                      * The type variable's type path.
988                      */

989                     private final String typePath;
990
991                     /**
992                      * Creates a new annotation collector.
993                      *
994                      * @param descriptor The annotation descriptor.
995                      * @param typePath   The type variable's type path.
996                      */

997                     protected ForTypeVariable(String descriptor, TypePath typePath) {
998                         super(descriptor);
999                         this.typePath = typePath == null
1000                                 ? LazyTypeDescription.GenericTypeToken.EMPTY_TYPE_PATH
1001                                 : typePath.toString();
1002                     }
1003
1004                     @Override
1005                     protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1006                         Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap = getPathMap();
1007                         List<LazyTypeDescription.AnnotationToken> tokens = pathMap.get(typePath);
1008                         if (tokens == null) {
1009                             tokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1010                             pathMap.put(typePath, tokens);
1011                         }
1012                         return tokens;
1013                     }
1014
1015                     /**
1016                      * Returns this collector's path map.
1017                      *
1018                      * @return This collector's path map.
1019                      */

1020                     protected abstract Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap();
1021
1022                     /**
1023                      * A base implementation for a collector for a type variable with an index.
1024                      */

1025                     protected abstract static class WithIndex extends AbstractBase.ForTypeVariable {
1026
1027                         /**
1028                          * The type variable's index.
1029                          */

1030                         private final int index;
1031
1032                         /**
1033                          * Creates a new annotation collector.
1034                          *
1035                          * @param descriptor The annotation descriptor.
1036                          * @param typePath   The type variable's type path.
1037                          * @param index      The type variable's index.
1038                          */

1039                         protected WithIndex(String descriptor, TypePath typePath, int index) {
1040                             super(descriptor, typePath);
1041                             this.index = index;
1042                         }
1043
1044                         @Override
1045                         protected Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap() {
1046                             Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap = getIndexedPathMap();
1047                             Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap = indexedPathMap.get(index);
1048                             if (pathMap == null) {
1049                                 pathMap = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1050                                 indexedPathMap.put(index, pathMap);
1051                             }
1052                             return pathMap;
1053                         }
1054
1055                         /**
1056                          * Returns this collector's indexed path map.
1057                          *
1058                          * @return This collector's indexed path map.
1059                          */

1060                         protected abstract Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap();
1061
1062                         /**
1063                          * A base implementation for a collector for a type variable with two indices.
1064                          */

1065                         protected abstract static class DoubleIndexed extends WithIndex {
1066
1067                             /**
1068                              * The type variable's first index.
1069                              */

1070                             private final int preIndex;
1071
1072                             /**
1073                              * Creates a new annotation collector.
1074                              *
1075                              * @param descriptor The annotation descriptor.
1076                              * @param typePath   The type variable's type path.
1077                              * @param index      The type variable's index.
1078                              * @param preIndex   The type variable's first index.
1079                              */

1080                             protected DoubleIndexed(String descriptor, TypePath typePath, int index, int preIndex) {
1081                                 super(descriptor, typePath, index);
1082                                 this.preIndex = preIndex;
1083                             }
1084
1085                             @Override
1086                             protected Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap() {
1087                                 Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexPathMap = getDoubleIndexedPathMap();
1088                                 Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap = doubleIndexPathMap.get(preIndex);
1089                                 if (indexedPathMap == null) {
1090                                     indexedPathMap = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1091                                     doubleIndexPathMap.put(preIndex, indexedPathMap);
1092                                 }
1093                                 return indexedPathMap;
1094                             }
1095
1096                             /**
1097                              * Returns this collector's double indexed path map.
1098                              *
1099                              * @return This collector's double indexed path map.
1100                              */

1101                             protected abstract Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> getDoubleIndexedPathMap();
1102                         }
1103                     }
1104                 }
1105             }
1106
1107             /**
1108              * An annotation collector for a byte code element.
1109              */

1110             class ForByteCodeElement extends AbstractBase {
1111
1112                 /**
1113                  * The target collection.
1114                  */

1115                 private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
1116
1117                 /**
1118                  * Creates a new annotation collector for a byte code element.
1119                  *
1120                  * @param descriptor       The annotation descriptor.
1121                  * @param annotationTokens The target collection.
1122                  */

1123                 protected ForByteCodeElement(String descriptor, List<LazyTypeDescription.AnnotationToken> annotationTokens) {
1124                     super(descriptor);
1125                     this.annotationTokens = annotationTokens;
1126                 }
1127
1128                 @Override
1129                 protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1130                     return annotationTokens;
1131                 }
1132
1133                 /**
1134                  * An annotation collector for a byte code element with an index.
1135                  */

1136                 public static class WithIndex extends AbstractBase {
1137
1138                     /**
1139                      * The byte code element's index.
1140                      */

1141                     private final int index;
1142
1143                     /**
1144                      * The target collection.
1145                      */

1146                     private final Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens;
1147
1148                     /**
1149                      * Creates a new annotation collector for a byte code element with an index.
1150                      *
1151                      * @param descriptor       The annotation descriptor.
1152                      * @param index            The byte code element's index.
1153                      * @param annotationTokens The target collection.
1154                      */

1155                     protected WithIndex(String descriptor, int index, Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens) {
1156                         super(descriptor);
1157                         this.index = index;
1158                         this.annotationTokens = annotationTokens;
1159                     }
1160
1161                     @Override
1162                     protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1163                         List<LazyTypeDescription.AnnotationToken> annotationTokens = this.annotationTokens.get(index);
1164                         if (annotationTokens == null) {
1165                             annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1166                             this.annotationTokens.put(index, annotationTokens);
1167                         }
1168                         return annotationTokens;
1169                     }
1170                 }
1171             }
1172
1173             /**
1174              * An annotation collector for a type variable.
1175              */

1176             class ForTypeVariable extends AbstractBase.ForTypeVariable {
1177
1178                 /**
1179                  * The target collection.
1180                  */

1181                 private final Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap;
1182
1183                 /**
1184                  * Creates a new annotation collector.
1185                  *
1186                  * @param descriptor The annotation descriptor.
1187                  * @param typePath   The type variable's type path.
1188                  * @param pathMap    The target collection.
1189                  */

1190                 protected ForTypeVariable(String descriptor, TypePath typePath, Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap) {
1191                     super(descriptor, typePath);
1192                     this.pathMap = pathMap;
1193                 }
1194
1195                 @Override
1196                 protected Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap() {
1197                     return pathMap;
1198                 }
1199
1200                 /**
1201                  * An annotation collector for a type variable with an index.
1202                  */

1203                 public static class WithIndex extends AbstractBase.ForTypeVariable.WithIndex {
1204
1205                     /**
1206                      * The target collection.
1207                      */

1208                     private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap;
1209
1210                     /**
1211                      * Creates a new annotation collector.
1212                      *
1213                      * @param descriptor     The annotation descriptor.
1214                      * @param typePath       The type variable's type path.
1215                      * @param index          The target index.
1216                      * @param indexedPathMap The target collection.
1217                      */

1218                     protected WithIndex(String descriptor,
1219                                         TypePath typePath,
1220                                         int index,
1221                                         Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap) {
1222                         super(descriptor, typePath, index);
1223                         this.indexedPathMap = indexedPathMap;
1224                     }
1225
1226                     @Override
1227                     protected Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap() {
1228                         return indexedPathMap;
1229                     }
1230
1231                     /**
1232                      * An annotation collector for a type variable with two indices.
1233                      */

1234                     public static class DoubleIndexed extends AbstractBase.ForTypeVariable.WithIndex.DoubleIndexed {
1235
1236                         /**
1237                          * The target collection.
1238                          */

1239                         private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexedPathMap;
1240
1241                         /**
1242                          * Creates a new annotation collector.
1243                          *
1244                          * @param descriptor           The annotation descriptor.
1245                          * @param typePath             The type variable's type path.
1246                          * @param index                The target index.
1247                          * @param preIndex             The initial target index.
1248                          * @param doubleIndexedPathMap The target collection.
1249                          */

1250                         protected DoubleIndexed(String descriptor,
1251                                                 TypePath typePath,
1252                                                 int index,
1253                                                 int preIndex,
1254                                                 Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexedPathMap) {
1255                             super(descriptor, typePath, index, preIndex);
1256                             this.doubleIndexedPathMap = doubleIndexedPathMap;
1257                         }
1258
1259                         @Override
1260                         protected Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> getDoubleIndexedPathMap() {
1261                             return doubleIndexedPathMap;
1262                         }
1263                     }
1264                 }
1265             }
1266         }
1267
1268         /**
1269          * A component type locator allows for the lazy location of an array's component type.
1270          */

1271         protected interface ComponentTypeLocator {
1272
1273             /**
1274              * Binds this component type to a given property name of an annotation.
1275              *
1276              * @param name The name of an annotation property which the returned component type reference should
1277              *             query for resolving an array's component type.
1278              * @return A component type reference to an annotation value's component type.
1279              */

1280             ComponentTypeReference bind(String name);
1281
1282             /**
1283              * A component type locator which cannot legally resolve an array's component type.
1284              */

1285             enum Illegal implements ComponentTypeLocator {
1286
1287                 /**
1288                  * The singleton instance.
1289                  */

1290                 INSTANCE;
1291
1292                 /**
1293                  * {@inheritDoc}
1294                  */

1295                 public ComponentTypeReference bind(String name) {
1296                     throw new IllegalStateException("Unexpected lookup of component type for " + name);
1297                 }
1298             }
1299
1300             /**
1301              * A component type locator that lazily analyses an annotation for resolving an annotation property's
1302              * array value's component type.
1303              */

1304             @HashCodeAndEqualsPlugin.Enhance
1305             class ForAnnotationProperty implements ComponentTypeLocator {
1306
1307                 /**
1308                  * The type pool to query for type descriptions.
1309                  */

1310                 private final TypePool typePool;
1311
1312                 /**
1313                  * The name of the annotation to analyze.
1314                  */

1315                 private final String annotationName;
1316
1317                 /**
1318                  * Creates a new component type locator for an array value.
1319                  *
1320                  * @param typePool             The type pool to be used for looking up linked types.
1321                  * @param annotationDescriptor A descriptor of the annotation to analyze.
1322                  */

1323                 public ForAnnotationProperty(TypePool typePool, String annotationDescriptor) {
1324                     this.typePool = typePool;
1325                     annotationName = annotationDescriptor.substring(1, annotationDescriptor.length() - 1).replace('/', '.');
1326                 }
1327
1328                 /**
1329                  * {@inheritDoc}
1330                  */

1331                 public ComponentTypeReference bind(String name) {
1332                     return new Bound(name);
1333                 }
1334
1335                 /**
1336                  * A bound representation of a
1337                  * {@link net.bytebuddy.pool.TypePool.Default.ComponentTypeLocator.ForAnnotationProperty}.
1338                  */

1339                 @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
1340                 protected class Bound implements ComponentTypeReference {
1341
1342                     /**
1343                      * The name of the annotation property.
1344                      */

1345                     private final String name;
1346
1347                     /**
1348                      * Creates a new bound component type locator for an annotation property.
1349                      *
1350                      * @param name The name of the annotation property.
1351                      */

1352                     protected Bound(String name) {
1353                         this.name = name;
1354                     }
1355
1356                     /**
1357                      * {@inheritDoc}
1358                      */

1359                     public String lookup() {
1360                         return typePool.describe(annotationName)
1361                                 .resolve()
1362                                 .getDeclaredMethods()
1363                                 .filter(named(name))
1364                                 .getOnly()
1365                                 .getReturnType()
1366                                 .asErasure()
1367                                 .getComponentType()
1368                                 .getName();
1369                     }
1370                 }
1371             }
1372
1373             /**
1374              * A component type locator that locates an array type by a method's return value from its method descriptor.
1375              */

1376             @HashCodeAndEqualsPlugin.Enhance
1377             class ForArrayType implements ComponentTypeLocator, ComponentTypeReference {
1378
1379                 /**
1380                  * The resolved component type's binary name.
1381                  */

1382                 private final String componentType;
1383
1384                 /**
1385                  * Creates a new component type locator for an array type.
1386                  *
1387                  * @param methodDescriptor The method descriptor to resolve.
1388                  */

1389                 public ForArrayType(String methodDescriptor) {
1390                     String arrayType = Type.getMethodType(methodDescriptor).getReturnType().getClassName();
1391                     componentType = arrayType.substring(0, arrayType.length() - 2);
1392                 }
1393
1394                 /**
1395                  * {@inheritDoc}
1396                  */

1397                 public ComponentTypeReference bind(String name) {
1398                     return this;
1399                 }
1400
1401                 /**
1402                  * {@inheritDoc}
1403                  */

1404                 public String lookup() {
1405                     return componentType;
1406                 }
1407             }
1408         }
1409
1410         /**
1411          * A type registrant allows to register a generic type token.
1412          */

1413         protected interface GenericTypeRegistrant {
1414
1415             /**
1416              * Registers a discovered generic type token.
1417              *
1418              * @param token The token to be registered.
1419              */

1420             void register(LazyTypeDescription.GenericTypeToken token);
1421
1422             /**
1423              * A signature visitor that rejects any discovered generic type.
1424              */

1425             class RejectingSignatureVisitor extends SignatureVisitor {
1426
1427                 /**
1428                  * The message of the error message.
1429                  */

1430                 private static final String MESSAGE = "Unexpected token in generic signature";
1431
1432                 /**
1433                  * Creates a new rejecting signature visitor.
1434                  */

1435                 public RejectingSignatureVisitor() {
1436                     super(OpenedClassReader.ASM_API);
1437                 }
1438
1439                 /**
1440                  * {@inheritDoc}
1441                  */

1442                 public void visitFormalTypeParameter(String name) {
1443                     throw new IllegalStateException(MESSAGE);
1444                 }
1445
1446                 /**
1447                  * {@inheritDoc}
1448                  */

1449                 public SignatureVisitor visitClassBound() {
1450                     throw new IllegalStateException(MESSAGE);
1451                 }
1452
1453                 /**
1454                  * {@inheritDoc}
1455                  */

1456                 public SignatureVisitor visitInterfaceBound() {
1457                     throw new IllegalStateException(MESSAGE);
1458                 }
1459
1460                 /**
1461                  * {@inheritDoc}
1462                  */

1463                 public SignatureVisitor visitSuperclass() {
1464                     throw new IllegalStateException(MESSAGE);
1465                 }
1466
1467                 /**
1468                  * {@inheritDoc}
1469                  */

1470                 public SignatureVisitor visitInterface() {
1471                     throw new IllegalStateException(MESSAGE);
1472                 }
1473
1474                 /**
1475                  * {@inheritDoc}
1476                  */

1477                 public SignatureVisitor visitParameterType() {
1478                     throw new IllegalStateException(MESSAGE);
1479                 }
1480
1481                 /**
1482                  * {@inheritDoc}
1483                  */

1484                 public SignatureVisitor visitReturnType() {
1485                     throw new IllegalStateException(MESSAGE);
1486                 }
1487
1488                 /**
1489                  * {@inheritDoc}
1490                  */

1491                 public SignatureVisitor visitExceptionType() {
1492                     throw new IllegalStateException(MESSAGE);
1493                 }
1494
1495                 /**
1496                  * {@inheritDoc}
1497                  */

1498                 public void visitBaseType(char descriptor) {
1499                     throw new IllegalStateException(MESSAGE);
1500                 }
1501
1502                 /**
1503                  * {@inheritDoc}
1504                  */

1505                 public void visitTypeVariable(String name) {
1506                     throw new IllegalStateException(MESSAGE);
1507                 }
1508
1509                 /**
1510                  * {@inheritDoc}
1511                  */

1512                 public SignatureVisitor visitArrayType() {
1513                     throw new IllegalStateException(MESSAGE);
1514                 }
1515
1516                 /**
1517                  * {@inheritDoc}
1518                  */

1519                 public void visitClassType(String name) {
1520                     throw new IllegalStateException(MESSAGE);
1521                 }
1522
1523                 /**
1524                  * {@inheritDoc}
1525                  */

1526                 public void visitInnerClassType(String name) {
1527                     throw new IllegalStateException(MESSAGE);
1528                 }
1529
1530                 /**
1531                  * {@inheritDoc}
1532                  */

1533                 public void visitTypeArgument() {
1534                     throw new IllegalStateException(MESSAGE);
1535                 }
1536
1537                 /**
1538                  * {@inheritDoc}
1539                  */

1540                 public SignatureVisitor visitTypeArgument(char wildcard) {
1541                     throw new IllegalStateException(MESSAGE);
1542                 }
1543
1544                 /**
1545                  * {@inheritDoc}
1546                  */

1547                 public void visitEnd() {
1548                     throw new IllegalStateException(MESSAGE);
1549                 }
1550             }
1551         }
1552
1553         /**
1554          * A bag for collecting parameter meta information that is stored as debug information for implemented
1555          * methods.
1556          */

1557         protected static class ParameterBag {
1558
1559             /**
1560              * An array of the method's parameter types.
1561              */

1562             private final Type[] parameterType;
1563
1564             /**
1565              * A map containing the tokens that were collected until now.
1566              */

1567             private final Map<Integer, String> parameterRegistry;
1568
1569             /**
1570              * Creates a new bag.
1571              *
1572              * @param parameterType An array of parameter types for the method on which this parameter bag
1573              *                      is used.
1574              */

1575             protected ParameterBag(Type[] parameterType) {
1576                 this.parameterType = parameterType;
1577                 parameterRegistry = new HashMap<Integer, String>();
1578             }
1579
1580             /**
1581              * Registers a new parameter.
1582              *
1583              * @param offset The offset of the registered entry on the local variable array of the method.
1584              * @param name   The name of the parameter.
1585              */

1586             protected void register(int offset, String name) {
1587                 parameterRegistry.put(offset, name);
1588             }
1589
1590             /**
1591              * Resolves the collected parameters as a list of parameter tokens.
1592              *
1593              * @param isStatic {@code trueif the analyzed method is static.
1594              * @return A list of parameter tokens based on the collected information.
1595              */

1596             protected List<LazyTypeDescription.MethodToken.ParameterToken> resolve(boolean isStatic) {
1597                 List<LazyTypeDescription.MethodToken.ParameterToken> parameterTokens = new ArrayList<LazyTypeDescription.MethodToken.ParameterToken>(parameterType.length);
1598                 int offset = isStatic
1599                         ? StackSize.ZERO.getSize()
1600                         : StackSize.SINGLE.getSize();
1601                 for (Type aParameterType : parameterType) {
1602                     String name = this.parameterRegistry.get(offset);
1603                     parameterTokens.add(name == null
1604                             ? new LazyTypeDescription.MethodToken.ParameterToken()
1605                             : new LazyTypeDescription.MethodToken.ParameterToken(name));
1606                     offset += aParameterType.getSize();
1607                 }
1608                 return parameterTokens;
1609             }
1610         }
1611
1612         /**
1613          * A generic type extractor allows for an iterative extraction of generic type information.
1614          */

1615         protected static class GenericTypeExtractor extends GenericTypeRegistrant.RejectingSignatureVisitor implements GenericTypeRegistrant {
1616
1617             /**
1618              * A registrant that receives any discovered type.
1619              */

1620             private final GenericTypeRegistrant genericTypeRegistrant;
1621
1622             /**
1623              * The current token that is in the process of creation.
1624              */

1625             private IncompleteToken incompleteToken;
1626
1627             /**
1628              * Creates a new generic type extractor.
1629              *
1630              * @param genericTypeRegistrant The target to receive the complete type.
1631              */

1632             protected GenericTypeExtractor(GenericTypeRegistrant genericTypeRegistrant) {
1633                 this.genericTypeRegistrant = genericTypeRegistrant;
1634             }
1635
1636             /**
1637              * {@inheritDoc}
1638              */

1639             public void visitBaseType(char descriptor) {
1640                 genericTypeRegistrant.register(LazyTypeDescription.GenericTypeToken.ForPrimitiveType.of(descriptor));
1641             }
1642
1643             /**
1644              * {@inheritDoc}
1645              */

1646             public void visitTypeVariable(String name) {
1647                 genericTypeRegistrant.register(new LazyTypeDescription.GenericTypeToken.ForTypeVariable(name));
1648             }
1649
1650             /**
1651              * {@inheritDoc}
1652              */

1653             public SignatureVisitor visitArrayType() {
1654                 return new GenericTypeExtractor(this);
1655             }
1656
1657             /**
1658              * {@inheritDoc}
1659              */

1660             public void register(LazyTypeDescription.GenericTypeToken componentTypeToken) {
1661                 genericTypeRegistrant.register(new LazyTypeDescription.GenericTypeToken.ForGenericArray(componentTypeToken));
1662             }
1663
1664             /**
1665              * {@inheritDoc}
1666              */

1667             public void visitClassType(String name) {
1668                 incompleteToken = new IncompleteToken.ForTopLevelType(name);
1669             }
1670
1671             /**
1672              * {@inheritDoc}
1673              */

1674             public void visitInnerClassType(String name) {
1675                 incompleteToken = new IncompleteToken.ForInnerClass(name, incompleteToken);
1676             }
1677
1678             /**
1679              * {@inheritDoc}
1680              */

1681             public void visitTypeArgument() {
1682                 incompleteToken.appendPlaceholder();
1683             }
1684
1685             /**
1686              * {@inheritDoc}
1687              */

1688             public SignatureVisitor visitTypeArgument(char wildcard) {
1689                 switch (wildcard) {
1690                     case SignatureVisitor.SUPER:
1691                         return incompleteToken.appendLowerBound();
1692                     case SignatureVisitor.EXTENDS:
1693                         return incompleteToken.appendUpperBound();
1694                     case SignatureVisitor.INSTANCEOF:
1695                         return incompleteToken.appendDirectBound();
1696                     default:
1697                         throw new IllegalArgumentException("Unknown wildcard: " + wildcard);
1698                 }
1699             }
1700
1701             /**
1702              * {@inheritDoc}
1703              */

1704             public void visitEnd() {
1705                 genericTypeRegistrant.register(incompleteToken.toToken());
1706             }
1707
1708             /**
1709              * An incomplete {@link LazyTypeDescription.GenericTypeToken}.
1710              */

1711             protected interface IncompleteToken {
1712
1713                 /**
1714                  * Appends a lower bound to this token.
1715                  *
1716                  * @return A signature visitor for visiting the lower bound's type.
1717                  */

1718                 SignatureVisitor appendLowerBound();
1719
1720                 /**
1721                  * Appends an upper bound to this token.
1722                  *
1723                  * @return A signature visitor for visiting the upper bound's type.
1724                  */

1725                 SignatureVisitor appendUpperBound();
1726
1727                 /**
1728                  * Appends a direct bound to this token.
1729                  *
1730                  * @return A signature visitor for visiting the direct bound's type.
1731                  */

1732                 SignatureVisitor appendDirectBound();
1733
1734                 /**
1735                  * Appends a placeholder to this token.
1736                  */

1737                 void appendPlaceholder();
1738
1739                 /**
1740                  * Returns {@code trueif this token describes a type with parameters.
1741                  *
1742                  * @return {@code trueif this token describes a type with parameters.
1743                  */

1744                 boolean isParameterized();
1745
1746                 /**
1747                  * Returns the name of this token.
1748                  *
1749                  * @return The name of this token.
1750                  */

1751                 String getName();
1752
1753                 /**
1754                  * Converts this incomplete token to a completed token.
1755                  *
1756                  * @return The finalized token.
1757                  */

1758                 LazyTypeDescription.GenericTypeToken toToken();
1759
1760                 /**
1761                  * An abstract base implementation of an incomplete token.
1762                  */

1763                 abstract class AbstractBase implements IncompleteToken {
1764
1765                     /**
1766                      * The parameters of this token.
1767                      */

1768                     protected final List<LazyTypeDescription.GenericTypeToken> parameters;
1769
1770                     /**
1771                      * Creates a new base implementation of an incomplete token.
1772                      */

1773                     public AbstractBase() {
1774                         parameters = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1775                     }
1776
1777                     /**
1778                      * {@inheritDoc}
1779                      */

1780                     public SignatureVisitor appendDirectBound() {
1781                         return new GenericTypeExtractor(new ForDirectBound());
1782                     }
1783
1784                     /**
1785                      * {@inheritDoc}
1786                      */

1787                     public SignatureVisitor appendUpperBound() {
1788                         return new GenericTypeExtractor(new ForUpperBound());
1789                     }
1790
1791                     /**
1792                      * {@inheritDoc}
1793                      */

1794                     public SignatureVisitor appendLowerBound() {
1795                         return new GenericTypeExtractor(new ForLowerBound());
1796                     }
1797
1798                     /**
1799                      * {@inheritDoc}
1800                      */

1801                     public void appendPlaceholder() {
1802                         parameters.add(LazyTypeDescription.GenericTypeToken.ForUnboundWildcard.INSTANCE);
1803                     }
1804
1805                     /**
1806                      * A token for registering a direct bound.
1807                      */

1808                     protected class ForDirectBound implements GenericTypeRegistrant {
1809
1810                         /**
1811                          * {@inheritDoc}
1812                          */

1813                         public void register(LazyTypeDescription.GenericTypeToken token) {
1814                             parameters.add(token);
1815                         }
1816                     }
1817
1818                     /**
1819                      * A token for registering a wildcard with an upper bound.
1820                      */

1821                     protected class ForUpperBound implements GenericTypeRegistrant {
1822
1823                         /**
1824                          * {@inheritDoc}
1825                          */

1826                         public void register(LazyTypeDescription.GenericTypeToken token) {
1827                             parameters.add(new LazyTypeDescription.GenericTypeToken.ForUpperBoundWildcard(token));
1828                         }
1829                     }
1830
1831                     /**
1832                      * A token for registering a wildcard with a lower bound.
1833                      */

1834                     protected class ForLowerBound implements GenericTypeRegistrant {
1835
1836                         /**
1837                          * {@inheritDoc}
1838                          */

1839                         public void register(LazyTypeDescription.GenericTypeToken token) {
1840                             parameters.add(new LazyTypeDescription.GenericTypeToken.ForLowerBoundWildcard(token));
1841                         }
1842                     }
1843                 }
1844
1845                 /**
1846                  * An incomplete token representing a generic type without an outer type.
1847                  */

1848                 @HashCodeAndEqualsPlugin.Enhance
1849                 class ForTopLevelType extends AbstractBase {
1850
1851                     /**
1852                      * The internal name of the type.
1853                      */

1854                     private final String internalName;
1855
1856                     /**
1857                      * Creates a new incomplete token representing a type without an outer type.
1858                      *
1859                      * @param internalName The internal name of the type.
1860                      */

1861                     public ForTopLevelType(String internalName) {
1862                         this.internalName = internalName;
1863                     }
1864
1865                     /**
1866                      * {@inheritDoc}
1867                      */

1868                     public LazyTypeDescription.GenericTypeToken toToken() {
1869                         return isParameterized()
1870                                 ? new LazyTypeDescription.GenericTypeToken.ForParameterizedType(getName(), parameters)
1871                                 : new LazyTypeDescription.GenericTypeToken.ForRawType(getName());
1872                     }
1873
1874                     /**
1875                      * {@inheritDoc}
1876                      */

1877                     public boolean isParameterized() {
1878                         return !parameters.isEmpty();
1879                     }
1880
1881                     /**
1882                      * {@inheritDoc}
1883                      */

1884                     public String getName() {
1885                         return internalName.replace('/', '.');
1886                     }
1887                 }
1888
1889                 /**
1890                  * An incomplete generic type token representing a type with an outer type.
1891                  */

1892                 @HashCodeAndEqualsPlugin.Enhance
1893                 class ForInnerClass extends AbstractBase {
1894
1895                     /**
1896                      * The separator that indicates an inner type.
1897                      */

1898                     private static final char INNER_CLASS_SEPARATOR = '$';
1899
1900                     /**
1901                      * The internal name of the type.
1902                      */

1903                     private final String internalName;
1904
1905                     /**
1906                      * The token representing the outer type.
1907                      */

1908                     private final IncompleteToken outerTypeToken;
1909
1910                     /**
1911                      * Creates a new incomplete token representing a type without an outer type.
1912                      *
1913                      * @param internalName   The internal name of the type.
1914                      * @param outerTypeToken The incomplete token representing the outer type.
1915                      */

1916                     public ForInnerClass(String internalName, IncompleteToken outerTypeToken) {
1917                         this.internalName = internalName;
1918                         this.outerTypeToken = outerTypeToken;
1919                     }
1920
1921                     /**
1922                      * {@inheritDoc}
1923                      */

1924                     public LazyTypeDescription.GenericTypeToken toToken() {
1925                         return isParameterized() || outerTypeToken.isParameterized()
1926                                 ? new LazyTypeDescription.GenericTypeToken.ForParameterizedType.Nested(getName(), parameters, outerTypeToken.toToken())
1927                                 : new LazyTypeDescription.GenericTypeToken.ForRawType(getName());
1928                     }
1929
1930                     /**
1931                      * {@inheritDoc}
1932                      */

1933                     public boolean isParameterized() {
1934                         return !parameters.isEmpty() || !outerTypeToken.isParameterized();
1935                     }
1936
1937                     /**
1938                      * {@inheritDoc}
1939                      */

1940                     public String getName() {
1941                         return outerTypeToken.getName() + INNER_CLASS_SEPARATOR + internalName.replace('/', '.');
1942                     }
1943                 }
1944             }
1945
1946             /**
1947              * A signature visitor for extracting a generic type resolution.
1948              *
1949              * @param <T> The type of the resolution this visitor extracts.
1950              */

1951             protected abstract static class ForSignature<T extends LazyTypeDescription.GenericTypeToken.Resolution>
1952                     extends RejectingSignatureVisitor
1953                     implements GenericTypeRegistrant {
1954
1955                 /**
1956                  * The resolved type variable tokens.
1957                  */

1958                 protected final List<LazyTypeDescription.GenericTypeToken.OfFormalTypeVariable> typeVariableTokens;
1959
1960                 /**
1961                  * The name of the currently constructed type.
1962                  */

1963                 protected String currentTypeParameter;
1964
1965                 /**
1966                  * The bounds of the currently constructed type.
1967                  */

1968                 protected List<LazyTypeDescription.GenericTypeToken> currentBounds;
1969
1970                 /**
1971                  * Creates a new signature visitor.
1972                  */

1973                 public ForSignature() {
1974                     typeVariableTokens = new ArrayList<LazyTypeDescription.GenericTypeToken.OfFormalTypeVariable>();
1975                 }
1976
1977                 /**
1978                  * Applies an extraction of a generic signature given the supplied visitor.
1979                  *
1980                  * @param genericSignature The generic signature to interpret.
1981                  * @param visitor          The visitor to apply.
1982                  * @param <S>              The type of the generated resolution.
1983                  * @return The resolution of the supplied signature.
1984                  */

1985                 protected static <S extends LazyTypeDescription.GenericTypeToken.Resolution> S extract(String genericSignature, ForSignature<S> visitor) {
1986                     SignatureReader signatureReader = new SignatureReader(genericSignature);
1987                     signatureReader.accept(visitor);
1988                     return visitor.resolve();
1989                 }
1990
1991                 /**
1992                  * {@inheritDoc}
1993                  */

1994                 public void visitFormalTypeParameter(String name) {
1995                     collectTypeParameter();
1996                     currentTypeParameter = name;
1997                     currentBounds = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1998                 }
1999
2000                 /**
2001                  * {@inheritDoc}
2002                  */

2003                 public SignatureVisitor visitClassBound() {
2004                     return new GenericTypeExtractor(this);
2005                 }
2006
2007                 /**
2008                  * {@inheritDoc}
2009                  */

2010                 public SignatureVisitor visitInterfaceBound() {
2011                     return new GenericTypeExtractor(this);
2012                 }
2013
2014                 /**
2015                  * {@inheritDoc}
2016                  */

2017                 public void register(LazyTypeDescription.GenericTypeToken token) {
2018                     if (currentBounds == null) {
2019                         throw new IllegalStateException("Did not expect " + token + " before finding formal parameter");
2020                     }
2021                     currentBounds.add(token);
2022                 }
2023
2024                 /**
2025                  * Collects the currently constructed type.
2026                  */

2027                 protected void collectTypeParameter() {
2028                     if (currentTypeParameter != null) {
2029                         typeVariableTokens.add(new LazyTypeDescription.GenericTypeToken.ForTypeVariable.Formal(currentTypeParameter, currentBounds));
2030                     }
2031                 }
2032
2033                 /**
2034                  * Completes the current resolution.
2035                  *
2036                  * @return The resolved generic signature.
2037                  */

2038                 public abstract T resolve();
2039
2040                 /**
2041                  * A parser for a generic type signature.
2042                  */

2043                 protected static class OfType extends ForSignature<LazyTypeDescription.GenericTypeToken.Resolution.ForType> {
2044
2045                     /**
2046                      * The interface type's generic signatures.
2047                      */

2048                     private final List<LazyTypeDescription.GenericTypeToken> interfaceTypeTokens;
2049
2050                     /**
2051                      * The super type's generic signature.
2052                      */

2053                     private LazyTypeDescription.GenericTypeToken superClassToken;
2054
2055                     /**
2056                      * Creates a new parser for a type signature.
2057                      */

2058                     protected OfType() {
2059                         interfaceTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
2060                     }
2061
2062                     /**
2063                      * Extracts a generic type resolution of a type signature.
2064                      *
2065                      * @param genericSignature The signature to interpret.
2066                      * @return The interpreted type signature.
2067                      */

2068                     public static LazyTypeDescription.GenericTypeToken.Resolution.ForType extract(String genericSignature) {
2069                         try {
2070                             return genericSignature == null
2071                                     ? LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE
2072                                     : ForSignature.extract(genericSignature, new OfType());
2073                         } catch (RuntimeException ignored) {
2074                             return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
2075                         }
2076                     }
2077
2078                     /**
2079                      * {@inheritDoc}
2080                      */

2081                     public SignatureVisitor visitSuperclass() {
2082                         collectTypeParameter();
2083                         return new GenericTypeExtractor(new SuperClassRegistrant());
2084                     }
2085
2086                     /**
2087                      * {@inheritDoc}
2088                      */

2089                     public SignatureVisitor visitInterface() {
2090                         return new GenericTypeExtractor(new InterfaceTypeRegistrant());
2091                     }
2092
2093                     /**
2094                      * {@inheritDoc}
2095                      */

2096                     public LazyTypeDescription.GenericTypeToken.Resolution.ForType resolve() {
2097                         return new LazyTypeDescription.GenericTypeToken.Resolution.ForType.Tokenized(superClassToken, interfaceTypeTokens, typeVariableTokens);
2098                     }
2099
2100                     /**
2101                      * A registrant for the super type.
2102                      */

2103                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2104                     protected class SuperClassRegistrant implements GenericTypeRegistrant {
2105
2106                         /**
2107                          * {@inheritDoc}
2108                          */

2109                         public void register(LazyTypeDescription.GenericTypeToken token) {
2110                             superClassToken = token;
2111                         }
2112                     }
2113
2114                     /**
2115                      * A registrant for the interface types.
2116                      */

2117                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2118                     protected class InterfaceTypeRegistrant implements GenericTypeRegistrant {
2119
2120                         /**
2121                          * {@inheritDoc}
2122                          */

2123                         public void register(LazyTypeDescription.GenericTypeToken token) {
2124                             interfaceTypeTokens.add(token);
2125                         }
2126                     }
2127                 }
2128
2129                 /**
2130                  * A parser for a generic field signature.
2131                  */

2132                 protected static class OfField implements GenericTypeRegistrant {
2133
2134                     /**
2135                      * The generic field type.
2136                      */

2137                     private LazyTypeDescription.GenericTypeToken fieldTypeToken;
2138
2139                     /**
2140                      * Extracts a generic field resolution of a field signature.
2141                      *
2142                      * @param genericSignature The signature to interpret.
2143                      * @return The interpreted field signature.
2144                      */

2145                     public static LazyTypeDescription.GenericTypeToken.Resolution.ForField extract(String genericSignature) {
2146                         if (genericSignature == null) {
2147                             return LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE;
2148                         } else {
2149                             SignatureReader signatureReader = new SignatureReader(genericSignature);
2150                             OfField visitor = new OfField();
2151                             try {
2152                                 signatureReader.acceptType(new GenericTypeExtractor(visitor));
2153                                 return visitor.resolve();
2154                             } catch (RuntimeException ignored) {
2155                                 return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
2156                             }
2157                         }
2158                     }
2159
2160                     /**
2161                      * {@inheritDoc}
2162                      */

2163                     public void register(LazyTypeDescription.GenericTypeToken token) {
2164                         fieldTypeToken = token;
2165                     }
2166
2167                     /**
2168                      * Completes the current resolution.
2169                      *
2170                      * @return The resolved generic signature.
2171                      */

2172                     protected LazyTypeDescription.GenericTypeToken.Resolution.ForField resolve() {
2173                         return new LazyTypeDescription.GenericTypeToken.Resolution.ForField.Tokenized(fieldTypeToken);
2174                     }
2175                 }
2176
2177                 /**
2178                  * A parser for a generic method signature.
2179                  */

2180                 protected static class OfMethod extends ForSignature<LazyTypeDescription.GenericTypeToken.Resolution.ForMethod> {
2181
2182                     /**
2183                      * The generic parameter types.
2184                      */

2185                     private final List<LazyTypeDescription.GenericTypeToken> parameterTypeTokens;
2186
2187                     /**
2188                      * The generic exception types.
2189                      */

2190                     private final List<LazyTypeDescription.GenericTypeToken> exceptionTypeTokens;
2191
2192                     /**
2193                      * The generic return type.
2194                      */

2195                     private LazyTypeDescription.GenericTypeToken returnTypeToken;
2196
2197                     /**
2198                      * Creates a parser for a generic method signature.
2199                      */

2200                     public OfMethod() {
2201                         parameterTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
2202                         exceptionTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
2203                     }
2204
2205                     /**
2206                      * Extracts a generic method resolution of a method signature.
2207                      *
2208                      * @param genericSignature The signature to interpret.
2209                      * @return The interpreted method signature.
2210                      */

2211                     public static LazyTypeDescription.GenericTypeToken.Resolution.ForMethod extract(String genericSignature) {
2212                         try {
2213                             return genericSignature == null
2214                                     ? LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE
2215                                     : ForSignature.extract(genericSignature, new OfMethod());
2216                         } catch (RuntimeException ignored) {
2217                             return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
2218                         }
2219                     }
2220
2221                     /**
2222                      * {@inheritDoc}
2223                      */

2224                     public SignatureVisitor visitParameterType() {
2225                         return new GenericTypeExtractor(new ParameterTypeRegistrant());
2226                     }
2227
2228                     /**
2229                      * {@inheritDoc}
2230                      */

2231                     public SignatureVisitor visitReturnType() {
2232                         collectTypeParameter();
2233                         return new GenericTypeExtractor(new ReturnTypeTypeRegistrant());
2234                     }
2235
2236                     /**
2237                      * {@inheritDoc}
2238                      */

2239                     public SignatureVisitor visitExceptionType() {
2240                         return new GenericTypeExtractor(new ExceptionTypeRegistrant());
2241                     }
2242
2243                     /**
2244                      * {@inheritDoc}
2245                      */

2246                     public LazyTypeDescription.GenericTypeToken.Resolution.ForMethod resolve() {
2247                         return new LazyTypeDescription.GenericTypeToken.Resolution.ForMethod.Tokenized(returnTypeToken,
2248                                 parameterTypeTokens,
2249                                 exceptionTypeTokens,
2250                                 typeVariableTokens);
2251                     }
2252
2253                     /**
2254                      * A registrant for a parameter type.
2255                      */

2256                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2257                     protected class ParameterTypeRegistrant implements GenericTypeRegistrant {
2258
2259                         /**
2260                          * {@inheritDoc}
2261                          */

2262                         public void register(LazyTypeDescription.GenericTypeToken token) {
2263                             parameterTypeTokens.add(token);
2264                         }
2265                     }
2266
2267                     /**
2268                      * A registrant for a return type.
2269                      */

2270                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2271                     protected class ReturnTypeTypeRegistrant implements GenericTypeRegistrant {
2272
2273                         /**
2274                          * {@inheritDoc}
2275                          */

2276                         public void register(LazyTypeDescription.GenericTypeToken token) {
2277                             returnTypeToken = token;
2278                         }
2279                     }
2280
2281                     /**
2282                      * A registrant for an exception type.
2283                      */

2284                     @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2285                     protected class ExceptionTypeRegistrant implements GenericTypeRegistrant {
2286
2287                         /**
2288                          * {@inheritDoc}
2289                          */

2290                         public void register(LazyTypeDescription.GenericTypeToken token) {
2291                             exceptionTypeTokens.add(token);
2292                         }
2293                     }
2294                 }
2295
2296                 /**
2297                  * A parser for a generic field signature.
2298                  */

2299                 protected static class OfRecordComponent implements GenericTypeRegistrant {
2300
2301                     /**
2302                      * The generic field type.
2303                      */

2304                     private LazyTypeDescription.GenericTypeToken recordComponentType;
2305
2306                     /**
2307                      * Extracts a generic field resolution of a field signature.
2308                      *
2309                      * @param genericSignature The signature to interpret.
2310                      * @return The interpreted field signature.
2311                      */

2312                     public static LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent extract(String genericSignature) {
2313                         if (genericSignature == null) {
2314                             return LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE;
2315                         } else {
2316                             SignatureReader signatureReader = new SignatureReader(genericSignature);
2317                             OfRecordComponent visitor = new OfRecordComponent();
2318                             try {
2319                                 signatureReader.acceptType(new GenericTypeExtractor(visitor));
2320                                 return visitor.resolve();
2321                             } catch (RuntimeException ignored) {
2322                                 return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
2323                             }
2324                         }
2325                     }
2326
2327                     /**
2328                      * {@inheritDoc}
2329                      */

2330                     public void register(LazyTypeDescription.GenericTypeToken token) {
2331                         recordComponentType = token;
2332                     }
2333
2334                     /**
2335                      * Completes the current resolution.
2336                      *
2337                      * @return The resolved generic signature.
2338                      */

2339                     protected LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent resolve() {
2340                         return new LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent.Tokenized(recordComponentType);
2341                     }
2342                 }
2343             }
2344         }
2345
2346         /**
2347          * A type description that looks up any referenced {@link net.bytebuddy.description.ByteCodeElement} or
2348          * {@link AnnotationDescription} by querying a type pool at lookup time.
2349          */

2350         protected static class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType {
2351
2352             /**
2353              * The index of a super class's type annotations.
2354              */

2355             private static final int SUPER_CLASS_INDEX = -1;
2356
2357             /**
2358              * Indicates that a type does not exist and does therefore not have a name.
2359              */

2360             private static final String NO_TYPE = null;
2361
2362             /**
2363              * The type pool to be used for looking up linked types.
2364              */

2365             private final TypePool typePool;
2366
2367             /**
2368              * The actual modifiers of this type.
2369              */

2370             private final int actualModifiers;
2371
2372             /**
2373              * The modifiers of this type.
2374              */

2375             private final int modifiers;
2376
2377             /**
2378              * The binary name of this type.
2379              */

2380             private final String name;
2381
2382             /**
2383              * The type's super type's descriptor or {@code nullif this type does not define a super type.
2384              */

2385             private final String superClassDescriptor;
2386
2387             /**
2388              * The type's generic signature as found in the class file or {@code nullif the type is not generic.
2389              */

2390             private final String genericSignature;
2391
2392             /**
2393              * The resolution of this type's generic type.
2394              */

2395             private final GenericTypeToken.Resolution.ForType signatureResolution;
2396
2397             /**
2398              * The descriptor of this type's interfaces.
2399              */

2400             private final List<String> interfaceTypeDescriptors;
2401
2402             /**
2403              * A definition of this type's containment within another type or method.
2404              */

2405             private final TypeContainment typeContainment;
2406
2407             /**
2408              * The binary name of this type's declaring type or {@code nullif no such type exists.
2409              */

2410             private final String declaringTypeName;
2411
2412             /**
2413              * A list of descriptors representing the types that are declared by this type.
2414              */

2415             private final List<String> declaredTypes;
2416
2417             /**
2418              * {@code trueif this type is an anonymous type.
2419              */

2420             private final boolean anonymousType;
2421
2422             /**
2423              * The binary name of the nest host or {@code nullif no nest host was specified.
2424              */

2425             private final String nestHost;
2426
2427             /**
2428              * A list of binary names of all specified nest members.
2429              */

2430             private final List<String> nestMembers;
2431
2432             /**
2433              * A mapping of type annotations for this type's super type and interface types by their indices.
2434              */

2435             private final Map<Integer, Map<String, List<AnnotationToken>>> superTypeAnnotationTokens;
2436
2437             /**
2438              * A mapping of type annotations of the type variables' type annotations by their indices.
2439              */

2440             private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
2441
2442             /**
2443              * A mapping of type annotations of the type variables' bounds' type annotations by their indices and each variable's index.
2444              */

2445             private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundsAnnotationTokens;
2446
2447             /**
2448              * A list of tokens that represent the annotations of this type.
2449              */

2450             private final List<AnnotationToken> annotationTokens;
2451
2452             /**
2453              * A list of field tokens describing the field's of this type.
2454              */

2455             private final List<FieldToken> fieldTokens;
2456
2457             /**
2458              * A list of method tokens describing the method's of this type.
2459              */

2460             private final List<MethodToken> methodTokens;
2461
2462             /**
2463              * A list of record component tokens describing the record components of this type.
2464              */

2465             private final List<RecordComponentToken> recordComponentTokens;
2466
2467             /**
2468              * A list of internal names of permitted subclasses.
2469              */

2470             private final List<String> permittedSubclasses;
2471
2472             /**
2473              * Creates a new lazy type description.
2474              *
2475              * @param typePool                           The type pool to be used for looking up linked types.
2476              * @param actualModifiers                    The actual modifiers of this type.
2477              * @param modifiers                          The modifiers of this type.
2478              * @param name                               The binary name of this type.
2479              * @param superClassInternalName             The internal name of this type's super type or {@code nullif no such super type is defined.
2480              * @param interfaceInternalName              An array of this type's interfaces or {@code nullif this type does not define any interfaces.
2481              * @param genericSignature                   The type's generic signature as found in the class file or {@code nullif the type is not generic.
2482              * @param typeContainment                    A definition of this type's containment within another type or method.
2483              * @param declaringTypeInternalName          The internal name of this type's declaring type or {@code nullif no such type exists.
2484              * @param declaredTypes                      A list of descriptors representing the types that are declared by this type.
2485              * @param anonymousType                      {@code trueif this type is an anonymous type.
2486              * @param nestHostInternalName               The internal name of the nest host or {@code nullif no nest host was specified.
2487              * @param nestMemberInternalNames            A list of internal names of the nest members.
2488              * @param superTypeAnnotationTokens          A mapping of type annotations for this type's super type and interface types by their indices.
2489              * @param typeVariableAnnotationTokens       A mapping of type annotations of the type variables' type annotations by their indices.
2490              * @param typeVariableBoundsAnnotationTokens A mapping of type annotations of the type variables' bounds' type annotations by their indices
2491              *                                           and each variable's index.
2492              * @param annotationTokens                   A list of tokens that represent the annotations of this type.
2493              * @param fieldTokens                        A list of field tokens describing the field's of this type.
2494              * @param methodTokens                       A list of method tokens describing the method's of this type.
2495              * @param recordComponentTokens              A list of record component tokens describing the record components of this type.
2496              * @param permittedSubclasses                A list of internal names of permitted subclasses.
2497              */

2498             protected LazyTypeDescription(TypePool typePool,
2499                                           int actualModifiers,
2500                                           int modifiers,
2501                                           String name,
2502                                           String superClassInternalName,
2503                                           String[] interfaceInternalName,
2504                                           String genericSignature,
2505                                           TypeContainment typeContainment,
2506                                           String declaringTypeInternalName,
2507                                           List<String> declaredTypes,
2508                                           boolean anonymousType,
2509                                           String nestHostInternalName,
2510                                           List<String> nestMemberInternalNames,
2511                                           Map<Integer, Map<String, List<AnnotationToken>>> superTypeAnnotationTokens,
2512                                           Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
2513                                           Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundsAnnotationTokens,
2514                                           List<AnnotationToken> annotationTokens,
2515                                           List<FieldToken> fieldTokens,
2516                                           List<MethodToken> methodTokens,
2517                                           List<RecordComponentToken> recordComponentTokens,
2518                                           List<String> permittedSubclasses) {
2519                 this.typePool = typePool;
2520                 this.actualModifiers = actualModifiers & ~Opcodes.ACC_SUPER;
2521                 this.modifiers = modifiers & ~(Opcodes.ACC_SUPER | Opcodes.ACC_DEPRECATED);
2522                 this.name = Type.getObjectType(name).getClassName();
2523                 this.superClassDescriptor = superClassInternalName == null
2524                         ? NO_TYPE
2525                         : Type.getObjectType(superClassInternalName).getDescriptor();
2526                 this.genericSignature = genericSignature;
2527                 signatureResolution = RAW_TYPES
2528                         ? GenericTypeToken.Resolution.Raw.INSTANCE
2529                         : GenericTypeExtractor.ForSignature.OfType.extract(genericSignature);
2530                 if (interfaceInternalName == null) {
2531                     interfaceTypeDescriptors = Collections.emptyList();
2532                 } else {
2533                     interfaceTypeDescriptors = new ArrayList<String>(interfaceInternalName.length);
2534                     for (String internalName : interfaceInternalName) {
2535                         interfaceTypeDescriptors.add(Type.getObjectType(internalName).getDescriptor());
2536                     }
2537                 }
2538                 this.typeContainment = typeContainment;
2539                 declaringTypeName = declaringTypeInternalName == null
2540                         ? NO_TYPE
2541                         : declaringTypeInternalName.replace('/', '.');
2542                 this.declaredTypes = declaredTypes;
2543                 this.anonymousType = anonymousType;
2544                 nestHost = nestHostInternalName == null
2545                         ? NO_TYPE
2546                         : Type.getObjectType(nestHostInternalName).getClassName();
2547                 nestMembers = new ArrayList<String>(nestMemberInternalNames.size());
2548                 for (String nestMemberInternalName : nestMemberInternalNames) {
2549                     nestMembers.add(Type.getObjectType(nestMemberInternalName).getClassName());
2550                 }
2551                 this.superTypeAnnotationTokens = superTypeAnnotationTokens;
2552                 this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
2553                 this.typeVariableBoundsAnnotationTokens = typeVariableBoundsAnnotationTokens;
2554                 this.annotationTokens = annotationTokens;
2555                 this.fieldTokens = fieldTokens;
2556                 this.methodTokens = methodTokens;
2557                 this.recordComponentTokens = recordComponentTokens;
2558                 this.permittedSubclasses = new ArrayList<String>(permittedSubclasses.size());
2559                 for (String internalName : permittedSubclasses) {
2560                     this.permittedSubclasses.add(Type.getObjectType(internalName).getDescriptor());
2561                 }
2562             }
2563
2564             /**
2565              * {@inheritDoc}
2566              */

2567             public Generic getSuperClass() {
2568                 return superClassDescriptor == null || isInterface()
2569                         ? Generic.UNDEFINED
2570                         : signatureResolution.resolveSuperClass(superClassDescriptor, typePool, superTypeAnnotationTokens.get(SUPER_CLASS_INDEX), this);
2571             }
2572
2573             /**
2574              * {@inheritDoc}
2575              */

2576             public TypeList.Generic getInterfaces() {
2577                 return signatureResolution.resolveInterfaceTypes(interfaceTypeDescriptors, typePool, superTypeAnnotationTokens, this);
2578             }
2579
2580             /**
2581              * {@inheritDoc}
2582              */

2583             public MethodDescription.InDefinedShape getEnclosingMethod() {
2584                 return typeContainment.getEnclosingMethod(typePool);
2585             }
2586
2587             /**
2588              * {@inheritDoc}
2589              */

2590             public TypeDescription getEnclosingType() {
2591                 return typeContainment.getEnclosingType(typePool);
2592             }
2593
2594             /**
2595              * {@inheritDoc}
2596              */

2597             public TypeList getDeclaredTypes() {
2598                 return new LazyTypeList(typePool, declaredTypes);
2599             }
2600
2601             /**
2602              * {@inheritDoc}
2603              */

2604             public boolean isAnonymousType() {
2605                 return anonymousType;
2606             }
2607
2608             /**
2609              * {@inheritDoc}
2610              */

2611             public boolean isLocalType() {
2612                 return !anonymousType && typeContainment.isLocalType();
2613             }
2614
2615             /**
2616              * {@inheritDoc}
2617              */

2618             public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
2619                 return new FieldTokenList();
2620             }
2621
2622             /**
2623              * {@inheritDoc}
2624              */

2625             public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
2626                 return new MethodTokenList();
2627             }
2628
2629             /**
2630              * {@inheritDoc}
2631              */

2632             public PackageDescription getPackage() {
2633                 String name = getName();
2634                 int index = name.lastIndexOf('.');
2635                 return new LazyPackageDescription(typePool, index == -1
2636                         ? EMPTY_NAME
2637                         : name.substring(0, index));
2638             }
2639
2640             /**
2641              * {@inheritDoc}
2642              */

2643             public String getName() {
2644                 return name;
2645             }
2646
2647             /**
2648              * {@inheritDoc}
2649              */

2650             public TypeDescription getDeclaringType() {
2651                 return declaringTypeName == null
2652                         ? TypeDescription.UNDEFINED
2653                         : typePool.describe(declaringTypeName).resolve();
2654             }
2655
2656             /**
2657              * {@inheritDoc}
2658              */

2659             public int getModifiers() {
2660                 return modifiers;
2661             }
2662
2663             /**
2664              * {@inheritDoc}
2665              */

2666             public int getActualModifiers(boolean superFlag) {
2667                 return superFlag ? (actualModifiers | Opcodes.ACC_SUPER) : actualModifiers;
2668             }
2669
2670             /**
2671              * {@inheritDoc}
2672              */

2673             public TypeDescription getNestHost() {
2674                 return nestHost == null
2675                         ? this
2676                         : typePool.describe(nestHost).resolve();
2677             }
2678
2679             /**
2680              * {@inheritDoc}
2681              */

2682             public TypeList getNestMembers() {
2683                 return nestHost == null
2684                         ? new LazyNestMemberList(this, typePool, nestMembers)
2685                         : typePool.describe(nestHost).resolve().getNestMembers();
2686             }
2687
2688             /**
2689              * {@inheritDoc}
2690              */

2691             public AnnotationList getDeclaredAnnotations() {
2692                 return LazyAnnotationDescription.asList(typePool, annotationTokens);
2693             }
2694
2695             /**
2696              * {@inheritDoc}
2697              */

2698             public TypeList.Generic getTypeVariables() {
2699                 return signatureResolution.resolveTypeVariables(typePool, this, typeVariableAnnotationTokens, typeVariableBoundsAnnotationTokens);
2700             }
2701
2702             @Override
2703             public String getGenericSignature() {
2704                 return genericSignature;
2705             }
2706
2707             /**
2708              * {@inheritDoc}
2709              */

2710             public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
2711                 return new RecordComponentTokenList();
2712             }
2713
2714             /**
2715              * {@inheritDoc}
2716              */

2717             public boolean isRecord() {
2718                 return (actualModifiers & Opcodes.ACC_RECORD) != 0 && JavaType.RECORD.getTypeStub().getDescriptor().equals(superClassDescriptor);
2719             }
2720
2721             /**
2722              * {@inheritDoc}
2723              */

2724             public TypeList getPermittedSubclasses() {
2725                 return new LazyTypeList(typePool, permittedSubclasses);
2726             }
2727
2728             /**
2729              * A list of field tokens representing each entry as a field description.
2730              */

2731             protected class FieldTokenList extends FieldList.AbstractBase<FieldDescription.InDefinedShape> {
2732
2733                 /**
2734                  * {@inheritDoc}
2735                  */

2736                 public FieldDescription.InDefinedShape get(int index) {
2737                     return fieldTokens.get(index).toFieldDescription(LazyTypeDescription.this);
2738                 }
2739
2740                 /**
2741                  * {@inheritDoc}
2742                  */

2743                 public int size() {
2744                     return fieldTokens.size();
2745                 }
2746             }
2747
2748             /**
2749              * A list of method tokens representing each entry as a method description.
2750              */

2751             protected class MethodTokenList extends MethodList.AbstractBase<MethodDescription.InDefinedShape> {
2752
2753                 /**
2754                  * {@inheritDoc}
2755                  */

2756                 public MethodDescription.InDefinedShape get(int index) {
2757                     return methodTokens.get(index).toMethodDescription(LazyTypeDescription.this);
2758                 }
2759
2760                 /**
2761                  * {@inheritDoc}
2762                  */

2763                 public int size() {
2764                     return methodTokens.size();
2765                 }
2766             }
2767
2768             /**
2769              * A list of record component tokens representing each record component as a description.
2770              */

2771             protected class RecordComponentTokenList extends RecordComponentList.AbstractBase<RecordComponentDescription.InDefinedShape> {
2772
2773                 /**
2774                  * {@inheritDoc}
2775                  */

2776                 public RecordComponentDescription.InDefinedShape get(int index) {
2777                     return recordComponentTokens.get(index).toRecordComponentDescription(LazyTypeDescription.this);
2778                 }
2779
2780                 /**
2781                  * {@inheritDoc}
2782                  */

2783                 public int size() {
2784                     return recordComponentTokens.size();
2785                 }
2786             }
2787
2788             /**
2789              * A declaration context encapsulates information about whether a type was declared within another type
2790              * or within a method of another type.
2791              */

2792             protected interface TypeContainment {
2793
2794                 /**
2795                  * Returns the enclosing method or {@code nullif no such method exists.
2796                  *
2797                  * @param typePool The type pool to be used for looking up linked types.
2798                  * @return A method description describing the linked type or {@code null}.
2799                  */

2800                 MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool);
2801
2802                 /**
2803                  * Returns the enclosing type or {@code nullif no such type exists.
2804                  *
2805                  * @param typePool The type pool to be used for looking up linked types.
2806                  * @return A type description describing the linked type or {@code null}.
2807                  */

2808                 TypeDescription getEnclosingType(TypePool typePool);
2809
2810                 /**
2811                  * Returns {@code trueif the type is self-contained.
2812                  *
2813                  * @return {@code trueif the type is self-contained.
2814                  */

2815                 boolean isSelfContained();
2816
2817                 /**
2818                  * Returns {@code trueif the type is a local type unless it is an anonymous type.
2819                  *
2820                  * @return {@code trueif the type is a local type unless it is an anonymous type
2821                  */

2822                 boolean isLocalType();
2823
2824                 /**
2825                  * Describes a type that is not contained within another type, a method or a constructor.
2826                  */

2827                 enum SelfContained implements TypeContainment {
2828
2829                     /**
2830                      * The singleton instance.
2831                      */

2832                     INSTANCE;
2833
2834                     /**
2835                      * {@inheritDoc}
2836                      */

2837                     public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
2838                         return MethodDescription.UNDEFINED;
2839                     }
2840
2841                     /**
2842                      * {@inheritDoc}
2843                      */

2844                     public TypeDescription getEnclosingType(TypePool typePool) {
2845                         return TypeDescription.UNDEFINED;
2846                     }
2847
2848                     /**
2849                      * {@inheritDoc}
2850                      */

2851                     public boolean isSelfContained() {
2852                         return true;
2853                     }
2854
2855                     /**
2856                      * {@inheritDoc}
2857                      */

2858                     public boolean isLocalType() {
2859                         return false;
2860                     }
2861                 }
2862
2863                 /**
2864                  * Describes a type that is contained within another type.
2865                  */

2866                 @HashCodeAndEqualsPlugin.Enhance
2867                 class WithinType implements TypeContainment {
2868
2869                     /**
2870                      * The type's binary name.
2871                      */

2872                     private final String name;
2873
2874                     /**
2875                      * {@code trueif the type is a local type unless it is an anonymous type.
2876                      */

2877                     private final boolean localType;
2878
2879                     /**
2880                      * Creates a new type containment for a type that is declared within another type.
2881                      *
2882                      * @param internalName The type's internal name.
2883                      * @param localType    {@code trueif the type is a local type unless it is an anonymous type.
2884                      */

2885                     protected WithinType(String internalName, boolean localType) {
2886                         name = internalName.replace('/', '.');
2887                         this.localType = localType;
2888                     }
2889
2890                     /**
2891                      * {@inheritDoc}
2892                      */

2893                     public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
2894                         return MethodDescription.UNDEFINED;
2895                     }
2896
2897                     /**
2898                      * {@inheritDoc}
2899                      */

2900                     public TypeDescription getEnclosingType(TypePool typePool) {
2901                         return typePool.describe(name).resolve();
2902                     }
2903
2904                     /**
2905                      * {@inheritDoc}
2906                      */

2907                     public boolean isSelfContained() {
2908                         return false;
2909                     }
2910
2911                     /**
2912                      * {@inheritDoc}
2913                      */

2914                     public boolean isLocalType() {
2915                         return localType;
2916                     }
2917                 }
2918
2919                 /**
2920                  * Describes a type that is contained within a method or constructor.
2921                  */

2922                 @HashCodeAndEqualsPlugin.Enhance
2923                 class WithinMethod implements TypeContainment {
2924
2925                     /**
2926                      * The method's declaring type's internal name.
2927                      */

2928                     private final String name;
2929
2930                     /**
2931                      * The method's internal name.
2932                      */

2933                     private final String methodName;
2934
2935                     /**
2936                      * The method's descriptor.
2937                      */

2938                     private final String methodDescriptor;
2939
2940                     /**
2941                      * Creates a new type containment for a type that is declared within a method.
2942                      *
2943                      * @param internalName     The method's declaring type's internal name.
2944                      * @param methodName       The method's internal name.
2945                      * @param methodDescriptor The method's descriptor.
2946                      */

2947                     protected WithinMethod(String internalName, String methodName, String methodDescriptor) {
2948                         name = internalName.replace('/', '.');
2949                         this.methodName = methodName;
2950                         this.methodDescriptor = methodDescriptor;
2951                     }
2952
2953                     /**
2954                      * {@inheritDoc}
2955                      */

2956                     public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
2957                         TypeDescription enclosingType = getEnclosingType(typePool);
2958                         MethodList<MethodDescription.InDefinedShape> enclosingMethod = enclosingType.getDeclaredMethods()
2959                                 .filter(hasMethodName(methodName).and(hasDescriptor(methodDescriptor)));
2960                         if (enclosingMethod.isEmpty()) {
2961                             throw new IllegalStateException(methodName + methodDescriptor + " not declared by " + enclosingType);
2962                         }
2963                         return enclosingMethod.getOnly();
2964                     }
2965
2966                     /**
2967                      * {@inheritDoc}
2968                      */

2969                     public TypeDescription getEnclosingType(TypePool typePool) {
2970                         return typePool.describe(name).resolve();
2971                     }
2972
2973                     /**
2974                      * {@inheritDoc}
2975                      */

2976                     public boolean isSelfContained() {
2977                         return false;
2978                     }
2979
2980                     /**
2981                      * {@inheritDoc}
2982                      */

2983                     public boolean isLocalType() {
2984                         return true;
2985                     }
2986                 }
2987             }
2988
2989             /**
2990              * A token that represents a generic Java type.
2991              */

2992             protected interface GenericTypeToken {
2993
2994                 /**
2995                  * Represents an empty type path.
2996                  */

2997                 String EMPTY_TYPE_PATH = "";
2998
2999                 /**
3000                  * Represents a step to a component type within a type path.
3001                  */

3002                 char COMPONENT_TYPE_PATH = '[';
3003
3004                 /**
3005                  * Represents a wildcard type step within a type path.
3006                  */

3007                 char WILDCARD_TYPE_PATH = '*';
3008
3009                 /**
3010                  * Represents a (reversed) step to an inner class within a type path.
3011                  */

3012                 char INNER_CLASS_PATH = '.';
3013
3014                 /**
3015                  * Represents an index type delimiter within a type path.
3016                  */

3017                 char INDEXED_TYPE_DELIMITER = ';';
3018
3019                 /**
3020                  * Transforms this token into a generic type representation.
3021                  *
3022                  * @param typePool           The type pool to be used for locating non-generic type descriptions.
3023                  * @param typeVariableSource The type variable source.
3024                  * @param typePath           The type path of the resolved generic type.
3025                  * @param annotationTokens   A mapping of the type's annotation tokens by their type path.
3026                  * @return A description of the represented generic type.
3027                  */

3028                 Generic toGenericType(TypePool typePool, TypeVariableSource typeVariableSource, String typePath, Map<String, List<AnnotationToken>> annotationTokens);
3029
3030                 /**
3031                  * Determines if a generic type tokens represents a primary bound of a type variable. This method must only be invoked on types
3032                  * that represent a {@link Sort#NON_GENERIC},
3033                  * {@link Sort#PARAMETERIZED} or {@link Sort#VARIABLE}.
3034                  *
3035                  * @param typePool The type pool to use.
3036                  * @return {@code trueif this token represents a primary bound.
3037                  */

3038                 boolean isPrimaryBound(TypePool typePool);
3039
3040                 /**
3041                  * Returns the type path prefix that needs to be appended to the existing type path before any further navigation on the parameterized
3042                  * type. This method must only be called on type tokens that represent parameterized type
3043                  *
3044                  * @return A type path segment that needs to be appended to the base type path before any further navigation on the parameterized type.
3045                  */

3046                 String getTypePathPrefix();
3047
3048                 /**
3049                  * Represents a generic type token for a formal type variable.
3050                  */

3051                 interface OfFormalTypeVariable {
3052
3053                     /**
3054                      * Transforms this token into a generic type representation.
3055                      *
3056                      * @param typePool                 The type pool to be used for locating non-generic type descriptions.
3057                      * @param typeVariableSource       The type variable source.
3058                      * @param annotationTokens         A mapping of the type variables' type annotations.
3059                      * @param boundaryAnnotationTokens A mapping of the type variables' bounds' type annotation by their bound index.
3060                      * @return A generic type representation of this formal type variable.
3061                      */

3062                     Generic toGenericType(TypePool typePool,
3063                                           TypeVariableSource typeVariableSource,
3064                                           Map<String, List<AnnotationToken>> annotationTokens,
3065                                           Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens);
3066                 }
3067
3068                 /**
3069                  * A generic type token that represents a primitive type.
3070                  */

3071                 enum ForPrimitiveType implements GenericTypeToken {
3072
3073                     /**
3074                      * The generic type token describing the {@code boolean} type.
3075                      */

3076                     BOOLEAN(boolean.class),
3077
3078                     /**
3079                      * The generic type token describing the {@code byte} type.
3080                      */

3081                     BYTE(byte.class),
3082
3083                     /**
3084                      * The generic type token describing the {@code short} type.
3085                      */

3086                     SHORT(short.class),
3087
3088                     /**
3089                      * The generic type token describing the {@code char} type.
3090                      */

3091                     CHAR(char.class),
3092
3093                     /**
3094                      * The generic type token describing the {@code int} type.
3095                      */

3096                     INTEGER(int.class),
3097
3098                     /**
3099                      * The generic type token describing the {@code long} type.
3100                      */

3101                     LONG(long.class),
3102
3103                     /**
3104                      * The generic type token describing the {@code float} type.
3105                      */

3106                     FLOAT(float.class),
3107
3108                     /**
3109                      * The generic type token describing the {@code double} type.
3110                      */

3111                     DOUBLE(double.class),
3112
3113                     /**
3114                      * The generic type token describing the {@code void} type.
3115                      */

3116                     VOID(void.class);
3117
3118                     /**
3119                      * A description of this primitive type token.
3120                      */

3121                     private final TypeDescription typeDescription;
3122
3123                     /**
3124                      * Creates a new primitive type token.
3125                      *
3126                      * @param type The loaded type representing this primitive.
3127                      */

3128                     ForPrimitiveType(Class<?> type) {
3129                         typeDescription = ForLoadedType.of(type);
3130                     }
3131
3132                     /**
3133                      * Resolves a generic type token of a primitive type.
3134                      *
3135                      * @param descriptor The descriptor of the primitive type.
3136                      * @return The corresponding generic type token.
3137                      */

3138                     public static GenericTypeToken of(char descriptor) {
3139                         switch (descriptor) {
3140                             case 'V':
3141                                 return VOID;
3142                             case 'Z':
3143                                 return BOOLEAN;
3144                             case 'B':
3145                                 return BYTE;
3146                             case 'S':
3147                                 return SHORT;
3148                             case 'C':
3149                                 return CHAR;
3150                             case 'I':
3151                                 return INTEGER;
3152                             case 'J':
3153                                 return LONG;
3154                             case 'F':
3155                                 return FLOAT;
3156                             case 'D':
3157                                 return DOUBLE;
3158                             default:
3159                                 throw new IllegalArgumentException("Not a valid primitive type descriptor: " + descriptor);
3160                         }
3161                     }
3162
3163                     /**
3164                      * {@inheritDoc}
3165                      */

3166                     public Generic toGenericType(TypePool typePool,
3167                                                  TypeVariableSource typeVariableSource,
3168                                                  String typePath,
3169                                                  Map<String, List<AnnotationToken>> annotationTokens) {
3170                         return new LazyPrimitiveType(typePool,
3171                                 typePath,
3172                                 annotationTokens == null
3173                                         ? Collections.<String, List<AnnotationToken>>emptyMap()
3174                                         : annotationTokens,
3175                                 typeDescription);
3176                     }
3177
3178                     /**
3179                      * {@inheritDoc}
3180                      */

3181                     public boolean isPrimaryBound(TypePool typePool) {
3182                         throw new IllegalStateException("A primitive type cannot be a type variable bound: " + this);
3183                     }
3184
3185                     /**
3186                      * {@inheritDoc}
3187                      */

3188                     public String getTypePathPrefix() {
3189                         throw new IllegalStateException("A primitive type cannot be the owner of a nested type: " + this);
3190                     }
3191
3192                     /**
3193                      * A representation of a lazy primitive type.
3194                      */

3195                     protected static class LazyPrimitiveType extends Generic.OfNonGenericType {
3196
3197                         /**
3198                          * The type pool to use.
3199                          */

3200                         private final TypePool typePool;
3201
3202                         /**
3203                          * This type's type path.
3204                          */

3205                         private final String typePath;
3206
3207                         /**
3208                          * This type's type annotation tokens.
3209                          */

3210                         private final Map<String, List<AnnotationToken>> annotationTokens;
3211
3212                         /**
3213                          * The represented type's description.
3214                          */

3215                         private final TypeDescription typeDescription;
3216
3217                         /**
3218                          * Creates a new lazy primitive type.
3219                          *
3220                          * @param typePool         The type pool to use.
3221                          * @param typePath         This type's type path.
3222                          * @param annotationTokens This type's type annotation tokens.
3223                          * @param typeDescription  The represented type's description.
3224                          */

3225                         protected LazyPrimitiveType(TypePool typePool,
3226                                                     String typePath,
3227                                                     Map<String, List<AnnotationToken>> annotationTokens,
3228                                                     TypeDescription typeDescription) {
3229                             this.typePool = typePool;
3230                             this.typePath = typePath;
3231                             this.annotationTokens = annotationTokens;
3232                             this.typeDescription = typeDescription;
3233                         }
3234
3235                         /**
3236                          * {@inheritDoc}
3237                          */

3238                         public TypeDescription asErasure() {
3239                             return typeDescription;
3240                         }
3241
3242                         /**
3243                          * {@inheritDoc}
3244                          */

3245                         public Generic getOwnerType() {
3246                             return Generic.UNDEFINED;
3247                         }
3248
3249                         /**
3250                          * {@inheritDoc}
3251                          */

3252                         public Generic getComponentType() {
3253                             return Generic.UNDEFINED;
3254                         }
3255
3256                         /**
3257                          * {@inheritDoc}
3258                          */

3259                         public AnnotationList getDeclaredAnnotations() {
3260                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
3261                         }
3262                     }
3263                 }
3264
3265                 /**
3266                  * A generic type token that represents an unbound wildcard.
3267                  */

3268                 enum ForUnboundWildcard implements GenericTypeToken {
3269
3270                     /**
3271                      * The singleton instance.
3272                      */

3273                     INSTANCE;
3274
3275                     /**
3276                      * {@inheritDoc}
3277                      */

3278                     public Generic toGenericType(TypePool typePool,
3279                                                  TypeVariableSource typeVariableSource,
3280                                                  String typePath,
3281                                                  Map<String, List<AnnotationToken>> annotationTokens) {
3282                         return new LazyUnboundWildcard(typePool,
3283                                 typePath,
3284                                 annotationTokens == null
3285                                         ? Collections.<String, List<AnnotationToken>>emptyMap()
3286                                         : annotationTokens);
3287                     }
3288
3289                     /**
3290                      * {@inheritDoc}
3291                      */

3292                     public boolean isPrimaryBound(TypePool typePool) {
3293                         throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
3294                     }
3295
3296                     /**
3297                      * {@inheritDoc}
3298                      */

3299                     public String getTypePathPrefix() {
3300                         throw new IllegalStateException("An unbound wildcard cannot be the owner of a nested type: " + this);
3301                     }
3302
3303                     /**
3304                      * A generic type representation of a generic unbound wildcard.
3305                      */

3306                     protected static class LazyUnboundWildcard extends Generic.OfWildcardType {
3307
3308                         /**
3309                          * The type pool to use.
3310                          */

3311                         private final TypePool typePool;
3312
3313                         /**
3314                          * This type's type path.
3315                          */

3316                         private final String typePath;
3317
3318                         /**
3319                          * The type's type annotations.
3320                          */

3321                         private final Map<String, List<AnnotationToken>> annotationTokens;
3322
3323                         /**
3324                          * Creates a new lazy unbound wildcard.
3325                          *
3326                          * @param typePool         The type pool to use.
3327                          * @param typePath         This type's type path.
3328                          * @param annotationTokens The type's type annotations.
3329                          */

3330                         protected LazyUnboundWildcard(TypePool typePool, String typePath, Map<String, List<AnnotationToken>> annotationTokens) {
3331                             this.typePool = typePool;
3332                             this.typePath = typePath;
3333                             this.annotationTokens = annotationTokens;
3334                         }
3335
3336                         /**
3337                          * {@inheritDoc}
3338                          */

3339                         public TypeList.Generic getUpperBounds() {
3340                             return new TypeList.Generic.Explicit(Generic.OBJECT);
3341                         }
3342
3343                         /**
3344                          * {@inheritDoc}
3345                          */

3346                         public TypeList.Generic getLowerBounds() {
3347                             return new TypeList.Generic.Empty();
3348                         }
3349
3350                         /**
3351                          * {@inheritDoc}
3352                          */

3353                         public AnnotationList getDeclaredAnnotations() {
3354                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
3355                         }
3356                     }
3357                 }
3358
3359                 /**
3360                  * A resolution of a type's, method's or field's generic types.
3361                  */

3362                 interface Resolution {
3363
3364                     /**
3365                      * Resolves the type variables of the represented element.
3366                      *
3367                      * @param typePool              The type pool to be used for locating non-generic type descriptions.
3368                      * @param typeVariableSource    The type variable source to use for resolving type variables.
3369                      * @param annotationTokens      A mapping of the type variables' type annotation tokens by their indices.
3370                      * @param boundAnnotationTokens A mapping of the type variables' bounds' type annotation tokens by their indices
3371                      *                              and each type variable's index.
3372                      * @return A list describing the resolved generic types.
3373                      */

3374                     TypeList.Generic resolveTypeVariables(TypePool typePool,
3375                                                           TypeVariableSource typeVariableSource,
3376                                                           Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3377                                                           Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens);
3378
3379                     /**
3380                      * A resolution of a type's, method's or field's generic types if all of the represented element's are raw.
3381                      */

3382                     enum Raw implements ForType, ForField, ForMethod, ForRecordComponent {
3383
3384                         /**
3385                          * The singleton instance.
3386                          */

3387                         INSTANCE;
3388
3389                         /**
3390                          * {@inheritDoc}
3391                          */

3392                         public Generic resolveSuperClass(String superClassDescriptor,
3393                                                          TypePool typePool,
3394                                                          Map<String, List<AnnotationToken>> annotationTokens,
3395                                                          TypeDescription definingType) {
3396                             return RawAnnotatedType.of(typePool, annotationTokens, superClassDescriptor);
3397                         }
3398
3399                         /**
3400                          * {@inheritDoc}
3401                          */

3402                         public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
3403                                                                       TypePool typePool,
3404                                                                       Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3405                                                                       TypeDescription definingType) {
3406                             return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, interfaceTypeDescriptors);
3407                         }
3408
3409                         /**
3410                          * {@inheritDoc}
3411                          */

3412                         public TypeList.Generic resolveTypeVariables(TypePool typePool,
3413                                                                      TypeVariableSource typeVariableSource,
3414                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3415                                                                      Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
3416                             return new TypeList.Generic.Empty();
3417                         }
3418
3419                         /**
3420                          * {@inheritDoc}
3421                          */

3422                         public Generic resolveFieldType(String fieldTypeDescriptor,
3423                                                         TypePool typePool,
3424                                                         Map<String, List<AnnotationToken>> annotationTokens,
3425                                                         FieldDescription.InDefinedShape definingField) {
3426                             return RawAnnotatedType.of(typePool, annotationTokens, fieldTypeDescriptor);
3427                         }
3428
3429                         /**
3430                          * {@inheritDoc}
3431                          */

3432                         public Generic resolveReturnType(String returnTypeDescriptor,
3433                                                          TypePool typePool,
3434                                                          Map<String, List<AnnotationToken>> annotationTokens,
3435                                                          MethodDescription.InDefinedShape definingMethod) {
3436                             return RawAnnotatedType.of(typePool, annotationTokens, returnTypeDescriptor);
3437                         }
3438
3439                         /**
3440                          * {@inheritDoc}
3441                          */

3442                         public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
3443                                                                       TypePool typePool,
3444                                                                       Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3445                                                                       MethodDescription.InDefinedShape definingMethod) {
3446                             return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, parameterTypeDescriptors);
3447                         }
3448
3449                         /**
3450                          * {@inheritDoc}
3451                          */

3452                         public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
3453                                                                       TypePool typePool,
3454                                                                       Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3455                                                                       MethodDescription.InDefinedShape definingMethod) {
3456                             return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, exceptionTypeDescriptors);
3457                         }
3458
3459                         /**
3460                          * {@inheritDoc}
3461                          */

3462                         public Generic resolveRecordType(String recordTypeDescriptor,
3463                                                          TypePool typePool,
3464                                                          Map<String, List<AnnotationToken>> annotationTokens,
3465                                                          RecordComponentDescription definingRecordComponent) {
3466                             return RawAnnotatedType.of(typePool, annotationTokens, recordTypeDescriptor);
3467                         }
3468
3469                         /**
3470                          * Represents a non-generic type that defines type annotations.
3471                          */

3472                         protected static class RawAnnotatedType extends Generic.OfNonGenericType {
3473
3474                             /**
3475                              * The type pool to use.
3476                              */

3477                             private final TypePool typePool;
3478
3479                             /**
3480                              * The type's type path.
3481                              */

3482                             private final String typePath;
3483
3484                             /**
3485                              * A mapping of this type's type annotations.
3486                              */

3487                             private final Map<String, List<AnnotationToken>> annotationTokens;
3488
3489                             /**
3490                              * The represented non-generic type.
3491                              */

3492                             private final TypeDescription typeDescription;
3493
3494                             /**
3495                              * Creates a new raw annotated type.
3496                              *
3497                              * @param typePool         The type pool to use.
3498                              * @param typePath         The type's type path.
3499                              * @param annotationTokens A mapping of this type's type annotations.
3500                              * @param typeDescription  The represented non-generic type.
3501                              */

3502                             protected RawAnnotatedType(TypePool typePool,
3503                                                        String typePath,
3504                                                        Map<String, List<AnnotationToken>> annotationTokens,
3505                                                        TypeDescription typeDescription) {
3506                                 this.typePool = typePool;
3507                                 this.typePath = typePath;
3508                                 this.annotationTokens = annotationTokens;
3509                                 this.typeDescription = typeDescription;
3510                             }
3511
3512                             /**
3513                              * Creates a new raw annotated type.
3514                              *
3515                              * @param typePool         The type pool to use.
3516                              * @param annotationTokens A mapping of this type's type annotations.
3517                              * @param descriptor       The descriptor of the represented non-generic type.
3518                              * @return An annotated non-generic type.
3519                              */

3520                             protected static Generic of(TypePool typePool, Map<String, List<AnnotationToken>> annotationTokens, String descriptor) {
3521                                 return new RawAnnotatedType(typePool,
3522                                         EMPTY_TYPE_PATH,
3523                                         annotationTokens == null
3524                                                 ? Collections.<String, List<AnnotationToken>>emptyMap()
3525                                                 : annotationTokens,
3526                                         TokenizedGenericType.toErasure(typePool, descriptor));
3527                             }
3528
3529                             /**
3530                              * {@inheritDoc}
3531                              */

3532                             public TypeDescription asErasure() {
3533                                 return typeDescription;
3534                             }
3535
3536                             /**
3537                              * {@inheritDoc}
3538                              */

3539                             public Generic getOwnerType() {
3540                                 TypeDescription declaringType = typeDescription.getDeclaringType();
3541                                 return declaringType == null
3542                                         ? Generic.UNDEFINED
3543                                         : new RawAnnotatedType(typePool, typePath, annotationTokens, declaringType);
3544                             }
3545
3546                             /**
3547                              * {@inheritDoc}
3548                              */

3549                             public Generic getComponentType() {
3550                                 TypeDescription componentType = typeDescription.getComponentType();
3551                                 return componentType == null
3552                                         ? Generic.UNDEFINED
3553                                         : new RawAnnotatedType(typePool, typePath + COMPONENT_TYPE_PATH, annotationTokens, componentType);
3554                             }
3555
3556                             /**
3557                              * {@inheritDoc}
3558                              */

3559                             public AnnotationList getDeclaredAnnotations() {
3560                                 StringBuilder typePath = new StringBuilder(this.typePath);
3561                                 for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
3562                                     typePath = typePath.append(INNER_CLASS_PATH);
3563                                 }
3564                                 return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath.toString()));
3565                             }
3566
3567                             /**
3568                              * A generic type list representing raw types.
3569                              */

3570                             protected static class LazyRawAnnotatedTypeList extends TypeList.Generic.AbstractBase {
3571
3572                                 /**
3573                                  * The type pool to use for locating types.
3574                                  */

3575                                 private final TypePool typePool;
3576
3577                                 /**
3578                                  * A mapping of the represented types' type annotation tokens by their indices.
3579                                  */

3580                                 private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
3581
3582                                 /**
3583                                  * A list of type descriptors that this list represents.
3584                                  */

3585                                 private final List<String> descriptors;
3586
3587                                 /**
3588                                  * Creates a generic type list only representing raw types.
3589                                  *
3590                                  * @param typePool         The type pool to use for locating types.
3591                                  * @param annotationTokens A mapping of the represented types' type annotation tokens by their indices.
3592                                  * @param descriptors      A list of type descriptors that this list represents.
3593                                  */

3594                                 protected LazyRawAnnotatedTypeList(TypePool typePool,
3595                                                                    Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3596                                                                    List<String> descriptors) {
3597                                     this.typePool = typePool;
3598                                     this.annotationTokens = annotationTokens;
3599                                     this.descriptors = descriptors;
3600                                 }
3601
3602                                 /**
3603                                  * Creates generic type list only representing raw types.
3604                                  *
3605                                  * @param typePool         The type pool to use for locating types.
3606                                  * @param annotationTokens A mapping of the represented types' type annotation tokens by their indices or
3607                                  *                         {@code nullif no type annotations are defined for any type.
3608                                  * @param descriptors      A list of type descriptors that this list represents.
3609                                  * @return A generic type list representing the raw types this list represents.
3610                                  */

3611                                 protected static TypeList.Generic of(TypePool typePool,
3612                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3613                                                                      List<String> descriptors) {
3614                                     return new LazyRawAnnotatedTypeList(typePool,
3615                                             annotationTokens == null
3616                                                     ? Collections.<Integer, Map<String, List<AnnotationToken>>>emptyMap()
3617                                                     : annotationTokens,
3618                                             descriptors);
3619                                 }
3620
3621                                 /**
3622                                  * {@inheritDoc}
3623                                  */

3624                                 public Generic get(int index) {
3625                                     return RawAnnotatedType.of(typePool, annotationTokens.get(index), descriptors.get(index));
3626                                 }
3627
3628                                 /**
3629                                  * {@inheritDoc}
3630                                  */

3631                                 public int size() {
3632                                     return descriptors.size();
3633                                 }
3634
3635                                 /**
3636                                  * {@inheritDoc}
3637                                  */

3638                                 public TypeList asErasures() {
3639                                     return new LazyTypeList(typePool, descriptors);
3640                                 }
3641
3642                                 /**
3643                                  * {@inheritDoc}
3644                                  */

3645                                 public TypeList.Generic asRawTypes() {
3646                                     return this;
3647                                 }
3648
3649                                 /**
3650                                  * {@inheritDoc}
3651                                  */

3652                                 public int getStackSize() {
3653                                     int stackSize = 0;
3654                                     for (String descriptor : descriptors) {
3655                                         stackSize += Type.getType(descriptor).getSize();
3656                                     }
3657                                     return stackSize;
3658                                 }
3659                             }
3660                         }
3661                     }
3662
3663                     /**
3664                      * A resolution of a type's, method's or field's generic types if its generic signature is malformed.
3665                      */

3666                     enum Malformed implements ForType, ForField, ForMethod, ForRecordComponent {
3667
3668                         /**
3669                          * The singleton instance.
3670                          */

3671                         INSTANCE;
3672
3673                         /**
3674                          * {@inheritDoc}
3675                          */

3676                         public Generic resolveSuperClass(String superClassDescriptor,
3677                                                          TypePool typePool,
3678                                                          Map<String, List<AnnotationToken>> annotationTokens,
3679                                                          TypeDescription definingType) {
3680                             return new TokenizedGenericType.Malformed(typePool, superClassDescriptor);
3681                         }
3682
3683                         /**
3684                          * {@inheritDoc}
3685                          */

3686                         public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
3687                                                                       TypePool typePool,
3688                                                                       Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3689                                                                       TypeDescription definingType) {
3690                             return new TokenizedGenericType.Malformed.TokenList(typePool, interfaceTypeDescriptors);
3691                         }
3692
3693                         /**
3694                          * {@inheritDoc}
3695                          */

3696                         public TypeList.Generic resolveTypeVariables(TypePool typePool,
3697                                                                      TypeVariableSource typeVariableSource,
3698                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3699                                                                      Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
3700                             throw new GenericSignatureFormatError();
3701                         }
3702
3703                         /**
3704                          * {@inheritDoc}
3705                          */

3706                         public Generic resolveFieldType(String fieldTypeDescriptor,
3707                                                         TypePool typePool,
3708                                                         Map<String, List<AnnotationToken>> annotationTokens,
3709                                                         FieldDescription.InDefinedShape definingField) {
3710                             return new TokenizedGenericType.Malformed(typePool, fieldTypeDescriptor);
3711                         }
3712
3713                         /**
3714                          * {@inheritDoc}
3715                          */

3716                         public Generic resolveReturnType(String returnTypeDescriptor,
3717                                                          TypePool typePool,
3718                                                          Map<String, List<AnnotationToken>> annotationTokens,
3719                                                          MethodDescription.InDefinedShape definingMethod) {
3720                             return new TokenizedGenericType.Malformed(typePool, returnTypeDescriptor);
3721                         }
3722
3723                         /**
3724                          * {@inheritDoc}
3725                          */

3726                         public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
3727                                                                       TypePool typePool,
3728                                                                       Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3729                                                                       MethodDescription.InDefinedShape definingMethod) {
3730                             return new TokenizedGenericType.Malformed.TokenList(typePool, parameterTypeDescriptors);
3731                         }
3732
3733                         /**
3734                          * {@inheritDoc}
3735                          */

3736                         public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
3737                                                                       TypePool typePool,
3738                                                                       Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3739                                                                       MethodDescription.InDefinedShape definingMethod) {
3740                             return new TokenizedGenericType.Malformed.TokenList(typePool, exceptionTypeDescriptors);
3741                         }
3742
3743
3744                         /**
3745                          * {@inheritDoc}
3746                          */

3747                         public Generic resolveRecordType(String recordTypeDescriptor,
3748                                                          TypePool typePool,
3749                                                          Map<String, List<AnnotationToken>> annotationTokens,
3750                                                          RecordComponentDescription definingRecordComponent) {
3751                             return new TokenizedGenericType.Malformed(typePool, recordTypeDescriptor);
3752                         }
3753                     }
3754
3755                     /**
3756                      * A resolution of the generic types of a {@link TypeDescription}.
3757                      */

3758                     interface ForType extends Resolution {
3759
3760                         /**
3761                          * Resolves the generic super type of the represented type.
3762                          *
3763                          * @param superClassDescriptor The descriptor of the raw super type.
3764                          * @param typePool             The type pool to be used for locating non-generic type descriptions.
3765                          * @param annotationTokens     A mapping of the super type's type annotation tokens.
3766                          * @param definingType         The type that defines this super type.
3767                          * @return A description of this type's generic super type.
3768                          */

3769                         Generic resolveSuperClass(String superClassDescriptor,
3770                                                   TypePool typePool,
3771                                                   Map<String, List<AnnotationToken>> annotationTokens,
3772                                                   TypeDescription definingType);
3773
3774                         /**
3775                          * Resolves the generic interface types of the represented type.
3776                          *
3777                          * @param interfaceTypeDescriptors The descriptor of the raw interface types.
3778                          * @param typePool                 The type pool to be used for locating non-generic type descriptions.
3779                          * @param annotationTokens         A mapping of the interface types' type annotation tokens by their indices.
3780                          * @param definingType             The type that defines these interface type.
3781                          * @return A description of this type's generic interface types.
3782                          */

3783                         TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
3784                                                                TypePool typePool,
3785                                                                Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3786                                                                TypeDescription definingType);
3787
3788                         /**
3789                          * An implementation of a tokenized resolution of generic types of a {@link TypeDescription}.
3790                          */

3791                         @HashCodeAndEqualsPlugin.Enhance
3792                         class Tokenized implements ForType {
3793
3794                             /**
3795                              * The super type's generic type token.
3796                              */

3797                             private final GenericTypeToken superClassToken;
3798
3799                             /**
3800                              * The interface type's generic type tokens.
3801                              */

3802                             private final List<GenericTypeToken> interfaceTypeTokens;
3803
3804                             /**
3805                              * The type variables generic type tokens.
3806                              */

3807                             private final List<OfFormalTypeVariable> typeVariableTokens;
3808
3809                             /**
3810                              * Creates a new tokenized resolution of a {@link TypeDescription}'s generic signatures.
3811                              *
3812                              * @param superClassToken     The super class's generic type token.
3813                              * @param interfaceTypeTokens The interface type's generic type tokens.
3814                              * @param typeVariableTokens  The type variables generic type tokens.
3815                              */

3816                             protected Tokenized(GenericTypeToken superClassToken,
3817                                                 List<GenericTypeToken> interfaceTypeTokens,
3818                                                 List<OfFormalTypeVariable> typeVariableTokens) {
3819                                 this.superClassToken = superClassToken;
3820                                 this.interfaceTypeTokens = interfaceTypeTokens;
3821                                 this.typeVariableTokens = typeVariableTokens;
3822                             }
3823
3824                             /**
3825                              * {@inheritDoc}
3826                              */

3827                             public Generic resolveSuperClass(String superClassDescriptor,
3828                                                              TypePool typePool,
3829                                                              Map<String, List<AnnotationToken>> annotationTokens,
3830                                                              TypeDescription definingType) {
3831                                 return TokenizedGenericType.of(typePool, superClassToken, superClassDescriptor, annotationTokens, definingType);
3832                             }
3833
3834                             /**
3835                              * {@inheritDoc}
3836                              */

3837                             public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
3838                                                                           TypePool typePool,
3839                                                                           Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3840                                                                           TypeDescription definingType) {
3841                                 return new TokenizedGenericType.TokenList(typePool, interfaceTypeTokens, annotationTokens, interfaceTypeDescriptors, definingType);
3842                             }
3843
3844                             /**
3845                              * {@inheritDoc}
3846                              */

3847                             public TypeList.Generic resolveTypeVariables(TypePool typePool,
3848                                                                          TypeVariableSource typeVariableSource,
3849                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3850                                                                          Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
3851                                 return new TokenizedGenericType.TypeVariableList(typePool, typeVariableTokens, typeVariableSource, annotationTokens, boundAnnotationTokens);
3852                             }
3853                         }
3854                     }
3855
3856                     /**
3857                      * A resolution of the generic type of a {@link FieldDescription}.
3858                      */

3859                     interface ForField {
3860
3861                         /**
3862                          * Resolves the field type of the represented field.
3863                          *
3864                          * @param fieldTypeDescriptor The descriptor of the raw field type.
3865                          * @param typePool            The type pool to be used for locating non-generic type descriptions.
3866                          * @param annotationTokens    A mapping of the represented types' type annotation tokens.
3867                          * @param definingField       The field that defines this type.
3868                          * @return A generic type representation of the field's type.
3869                          */

3870                         Generic resolveFieldType(String fieldTypeDescriptor,
3871                                                  TypePool typePool,
3872                                                  Map<String, List<AnnotationToken>> annotationTokens,
3873                                                  FieldDescription.InDefinedShape definingField);
3874
3875                         /**
3876                          * An implementation of a tokenized resolution of the generic type of a {@link FieldDescription}.
3877                          */

3878                         @HashCodeAndEqualsPlugin.Enhance
3879                         class Tokenized implements ForField {
3880
3881                             /**
3882                              * The token of the represented field's type.
3883                              */

3884                             private final GenericTypeToken fieldTypeToken;
3885
3886                             /**
3887                              * Creates a new tokenized resolution of a {@link FieldDescription}'s type.
3888                              *
3889                              * @param fieldTypeToken The token of the represented field's type.
3890                              */

3891                             protected Tokenized(GenericTypeToken fieldTypeToken) {
3892                                 this.fieldTypeToken = fieldTypeToken;
3893                             }
3894
3895                             /**
3896                              * {@inheritDoc}
3897                              */

3898                             public Generic resolveFieldType(String fieldTypeDescriptor,
3899                                                             TypePool typePool,
3900                                                             Map<String, List<AnnotationToken>> annotationTokens,
3901                                                             FieldDescription.InDefinedShape definingField) {
3902                                 return TokenizedGenericType.of(typePool, fieldTypeToken, fieldTypeDescriptor, annotationTokens, definingField.getDeclaringType());
3903                             }
3904                         }
3905                     }
3906
3907                     /**
3908                      * A resolution of the generic types of a {@link MethodDescription}.
3909                      */

3910                     interface ForMethod extends Resolution {
3911
3912                         /**
3913                          * Resolves the return type of the represented method.
3914                          *
3915                          * @param returnTypeDescriptor The descriptor of the raw return type.
3916                          * @param typePool             The type pool to be used for locating non-generic type descriptions.
3917                          * @param annotationTokens     A mapping of the return type's type annotation tokens.
3918                          * @param definingMethod       The method that defines this return type.
3919                          * @return A description of this type's generic return type.
3920                          */

3921                         Generic resolveReturnType(String returnTypeDescriptor,
3922                                                   TypePool typePool,
3923                                                   Map<String, List<AnnotationToken>> annotationTokens,
3924                                                   MethodDescription.InDefinedShape definingMethod);
3925
3926                         /**
3927                          * Resolves the generic parameter types of the represented method.
3928                          *
3929                          * @param parameterTypeDescriptors The descriptor of the raw parameter types.
3930                          * @param typePool                 The type pool to be used for locating non-generic type descriptions.
3931                          * @param annotationTokens         A mapping of the parameter types' type annotation tokens by their indices.
3932                          * @param definingMethod           The method that defines these parameter types.
3933                          * @return A description of this type's generic interface types.
3934                          */

3935                         TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
3936                                                                TypePool typePool,
3937                                                                Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3938                                                                MethodDescription.InDefinedShape definingMethod);
3939
3940                         /**
3941                          * Resolves the generic parameter types of the represented method.
3942                          *
3943                          * @param exceptionTypeDescriptors The descriptor of the raw exception types.
3944                          * @param typePool                 The type pool to be used for locating non-generic type descriptions.
3945                          * @param annotationTokens         A mapping of the exception types' type annotation tokens by their indices.
3946                          * @param definingMethod           The method that defines these exception types.
3947                          * @return A description of this type's generic interface types.
3948                          */

3949                         TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
3950                                                                TypePool typePool,
3951                                                                Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3952                                                                MethodDescription.InDefinedShape definingMethod);
3953
3954                         /**
3955                          * An implementation of a tokenized resolution of generic types of a {@link MethodDescription}.
3956                          */

3957                         @HashCodeAndEqualsPlugin.Enhance
3958                         class Tokenized implements ForMethod {
3959
3960                             /**
3961                              * A token describing the represented method's return type.
3962                              */

3963                             private final GenericTypeToken returnTypeToken;
3964
3965                             /**
3966                              * A token describing the represented method's parameter types.
3967                              */

3968                             private final List<GenericTypeToken> parameterTypeTokens;
3969
3970                             /**
3971                              * A token describing the represented method's exception types.
3972                              */

3973                             private final List<GenericTypeToken> exceptionTypeTokens;
3974
3975                             /**
3976                              * A token describing the represented method's type variables.
3977                              */

3978                             private final List<OfFormalTypeVariable> typeVariableTokens;
3979
3980                             /**
3981                              * Creates a new tokenized resolution of a {@link MethodDescription}'s generic signatures.
3982                              *
3983                              * @param returnTypeToken     A token describing the represented method's return type.
3984                              * @param parameterTypeTokens A token describing the represented method's parameter types.
3985                              * @param exceptionTypeTokens A token describing the represented method's exception types.
3986                              * @param typeVariableTokens  A token describing the represented method's type variables.
3987                              */

3988                             protected Tokenized(GenericTypeToken returnTypeToken,
3989                                                 List<GenericTypeToken> parameterTypeTokens,
3990                                                 List<GenericTypeToken> exceptionTypeTokens,
3991                                                 List<OfFormalTypeVariable> typeVariableTokens) {
3992                                 this.returnTypeToken = returnTypeToken;
3993                                 this.parameterTypeTokens = parameterTypeTokens;
3994                                 this.exceptionTypeTokens = exceptionTypeTokens;
3995                                 this.typeVariableTokens = typeVariableTokens;
3996                             }
3997
3998                             /**
3999                              * {@inheritDoc}
4000                              */

4001                             public Generic resolveReturnType(String returnTypeDescriptor,
4002                                                              TypePool typePool,
4003                                                              Map<String, List<AnnotationToken>> annotationTokens,
4004                                                              MethodDescription.InDefinedShape definingMethod) {
4005                                 return TokenizedGenericType.of(typePool, returnTypeToken, returnTypeDescriptor, annotationTokens, definingMethod);
4006                             }
4007
4008                             /**
4009                              * {@inheritDoc}
4010                              */

4011                             public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
4012                                                                           TypePool typePool,
4013                                                                           Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4014                                                                           MethodDescription.InDefinedShape definingMethod) {
4015                                 return new TokenizedGenericType.TokenList(typePool, parameterTypeTokens, annotationTokens, parameterTypeDescriptors, definingMethod);
4016                             }
4017
4018                             /**
4019                              * {@inheritDoc}
4020                              */

4021                             public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
4022                                                                           TypePool typePool,
4023                                                                           Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4024                                                                           MethodDescription.InDefinedShape definingMethod) {
4025                                 // Generic signatures of methods are optional.
4026                                 return exceptionTypeTokens.isEmpty()
4027                                         ? Raw.INSTANCE.resolveExceptionTypes(exceptionTypeDescriptors, typePool, annotationTokens, definingMethod)
4028                                         : new TokenizedGenericType.TokenList(typePool, exceptionTypeTokens, annotationTokens, exceptionTypeDescriptors, definingMethod);
4029                             }
4030
4031                             /**
4032                              * {@inheritDoc}
4033                              */

4034                             public TypeList.Generic resolveTypeVariables(TypePool typePool,
4035                                                                          TypeVariableSource typeVariableSource,
4036                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4037                                                                          Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
4038                                 return new TokenizedGenericType.TypeVariableList(typePool, typeVariableTokens, typeVariableSource, annotationTokens, boundAnnotationTokens);
4039                             }
4040                         }
4041                     }
4042
4043                     /**
4044                      * A resolution of the generic type of a {@link RecordComponentDescription}.
4045                      */

4046                     interface ForRecordComponent {
4047
4048                         /**
4049                          * Resolves a record component's type.
4050                          *
4051                          * @param recordTypeDescriptor    The record component's descriptor.
4052                          * @param typePool                The type pool to be used for locating non-generic type descriptions.
4053                          * @param annotationTokens        A mapping of the represented types' type annotation tokens.
4054                          * @param definingRecordComponent The defining record component.
4055                          * @return A generic type representation of the record component's type.
4056                          */

4057                         Generic resolveRecordType(String recordTypeDescriptor,
4058                                                   TypePool typePool,
4059                                                   Map<String, List<AnnotationToken>> annotationTokens,
4060                                                   RecordComponentDescription definingRecordComponent);
4061
4062                         /**
4063                          * An implementation of a tokenized resolution of the generic type of a {@link RecordComponentDescription}.
4064                          */

4065                         @HashCodeAndEqualsPlugin.Enhance
4066                         class Tokenized implements ForRecordComponent {
4067
4068                             /**
4069                              * The token of the represented record component's type.
4070                              */

4071                             private final GenericTypeToken recordComponentTypeToken;
4072
4073                             /**
4074                              * Creates a new tokenized resolution of a {@link RecordComponentDescription}'s type.
4075                              *
4076                              * @param recordComponentTypeToken The token of the represented record component's type.
4077                              */

4078                             protected Tokenized(GenericTypeToken recordComponentTypeToken) {
4079                                 this.recordComponentTypeToken = recordComponentTypeToken;
4080                             }
4081
4082                             /**
4083                              * {@inheritDoc}
4084                              */

4085                             public Generic resolveRecordType(String recordTypeDescriptor,
4086                                                              TypePool typePool,
4087                                                              Map<String, List<AnnotationToken>> annotationTokens,
4088                                                              RecordComponentDescription definingRecordComponent) {
4089                                 return TokenizedGenericType.of(typePool, recordComponentTypeToken, recordTypeDescriptor, annotationTokens, null); // TODO
4090                             }
4091                         }
4092                     }
4093                 }
4094
4095                 /**
4096                  * A generic type token that represents a non-generic type.
4097                  */

4098                 @HashCodeAndEqualsPlugin.Enhance
4099                 class ForRawType implements GenericTypeToken {
4100
4101                     /**
4102                      * The name of the represented type.
4103                      */

4104                     private final String name;
4105
4106                     /**
4107                      * Creates a new type token that represents a non-generic type.
4108                      *
4109                      * @param name The name of the represented type.
4110                      */

4111                     protected ForRawType(String name) {
4112                         this.name = name;
4113                     }
4114
4115                     /**
4116                      * {@inheritDoc}
4117                      */

4118                     public Generic toGenericType(TypePool typePool,
4119                                                  TypeVariableSource typeVariableSource,
4120                                                  String typePath,
4121                                                  Map<String, List<AnnotationToken>> annotationTokens) {
4122                         return new Resolution.Raw.RawAnnotatedType(typePool,
4123                                 typePath,
4124                                 annotationTokens == null
4125                                         ? Collections.<String, List<AnnotationToken>>emptyMap()
4126                                         : annotationTokens,
4127                                 typePool.describe(name).resolve());
4128                     }
4129
4130                     /**
4131                      * {@inheritDoc}
4132                      */

4133                     public boolean isPrimaryBound(TypePool typePool) {
4134                         return !typePool.describe(name).resolve().isInterface();
4135                     }
4136
4137                     /**
4138                      * {@inheritDoc}
4139                      */

4140                     public String getTypePathPrefix() {
4141                         throw new IllegalStateException("A non-generic type cannot be the owner of a nested type: " + this);
4142                     }
4143                 }
4144
4145                 /**
4146                  * A generic type token that represents a type variable.
4147                  */

4148                 @HashCodeAndEqualsPlugin.Enhance
4149                 class ForTypeVariable implements GenericTypeToken {
4150
4151                     /**
4152                      * This type variable's nominal symbol.
4153                      */

4154                     private final String symbol;
4155
4156                     /**
4157                      * Creates a generic type token that represents a type variable.
4158                      *
4159                      * @param symbol This type variable's nominal symbol.
4160                      */

4161                     protected ForTypeVariable(String symbol) {
4162                         this.symbol = symbol;
4163                     }
4164
4165                     /**
4166                      * {@inheritDoc}
4167                      */

4168                     public Generic toGenericType(TypePool typePool, TypeVariableSource typeVariableSource, String typePath, Map<String, List<AnnotationToken>> annotationTokens) {
4169                         Generic typeVariable = typeVariableSource.findVariable(symbol);
4170                         return typeVariable == null
4171                                 ? new UnresolvedTypeVariable(typeVariableSource, typePool, symbol, annotationTokens.get(typePath))
4172                                 : new AnnotatedTypeVariable(typePool, annotationTokens.get(typePath), typeVariable);
4173                     }
4174
4175                     /**
4176                      * {@inheritDoc}
4177                      */

4178                     public boolean isPrimaryBound(TypePool typePool) {
4179                         return true;
4180                     }
4181
4182                     /**
4183                      * {@inheritDoc}
4184                      */

4185                     public String getTypePathPrefix() {
4186                         throw new IllegalStateException("A type variable cannot be the owner of a nested type: " + this);
4187                     }
4188
4189                     /**
4190                      * An annotated representation of a formal type variable.
4191                      */

4192                     protected static class AnnotatedTypeVariable extends Generic.OfTypeVariable {
4193
4194                         /**
4195                          * The type pool to use.
4196                          */

4197                         private final TypePool typePool;
4198
4199                         /**
4200                          * The represented annotation tokens.
4201                          */

4202                         private final List<AnnotationToken> annotationTokens;
4203
4204                         /**
4205                          * The represented type variable.
4206                          */

4207                         private final Generic typeVariable;
4208
4209                         /**
4210                          * Creates a new annotated type variable.
4211                          *
4212                          * @param typePool         The type pool to use.
4213                          * @param annotationTokens The represented annotation tokens.
4214                          * @param typeVariable     The represented type variable.
4215                          */

4216                         protected AnnotatedTypeVariable(TypePool typePool, List<AnnotationToken> annotationTokens, Generic typeVariable) {
4217                             this.typePool = typePool;
4218                             this.annotationTokens = annotationTokens;
4219                             this.typeVariable = typeVariable;
4220                         }
4221
4222                         /**
4223                          * {@inheritDoc}
4224                          */

4225                         public TypeList.Generic getUpperBounds() {
4226                             return typeVariable.getUpperBounds();
4227                         }
4228
4229                         /**
4230                          * {@inheritDoc}
4231                          */

4232                         public TypeVariableSource getTypeVariableSource() {
4233                             return typeVariable.getTypeVariableSource();
4234                         }
4235
4236                         /**
4237                          * {@inheritDoc}
4238                          */

4239                         public String getSymbol() {
4240                             return typeVariable.getSymbol();
4241                         }
4242
4243                         /**
4244                          * {@inheritDoc}
4245                          */

4246                         public AnnotationList getDeclaredAnnotations() {
4247                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
4248                         }
4249                     }
4250
4251                     /**
4252                      * Represents a type variable that a type references but that does not exist. Such type variables are only emitted by wrongful
4253                      * compilation either due to the isolated recompilation of outer classes or due to bugs in compilers.
4254                      */

4255                     protected static class UnresolvedTypeVariable extends Generic.OfTypeVariable {
4256
4257                         /**
4258                          * The undeclared type variable's source.
4259                          */

4260                         private final TypeVariableSource typeVariableSource;
4261
4262                         /**
4263                          * The type pool to use.
4264                          */

4265                         private final TypePool typePool;
4266
4267                         /**
4268                          * The type variable's symbol.
4269                          */

4270                         private final String symbol;
4271
4272                         /**
4273                          * The type variable's annotation tokens.
4274                          */

4275                         private final List<AnnotationToken> annotationTokens;
4276
4277                         /**
4278                          * Creates an unresolved type variable.
4279                          *
4280                          * @param typeVariableSource The undeclared type variable's source.
4281                          * @param typePool           The type pool to use.
4282                          * @param symbol             The type variable's symbol.
4283                          * @param annotationTokens   The type variable's annotation tokens.
4284                          */

4285                         protected UnresolvedTypeVariable(TypeVariableSource typeVariableSource,
4286                                                          TypePool typePool,
4287                                                          String symbol,
4288                                                          List<AnnotationToken> annotationTokens) {
4289                             this.typeVariableSource = typeVariableSource;
4290                             this.typePool = typePool;
4291                             this.symbol = symbol;
4292                             this.annotationTokens = annotationTokens;
4293                         }
4294
4295                         /**
4296                          * {@inheritDoc}
4297                          */

4298                         public TypeList.Generic getUpperBounds() {
4299                             throw new IllegalStateException("Cannot resolve bounds of unresolved type variable " + this + " by " + typeVariableSource);
4300                         }
4301
4302                         /**
4303                          * {@inheritDoc}
4304                          */

4305                         public TypeVariableSource getTypeVariableSource() {
4306                             return typeVariableSource;
4307                         }
4308
4309                         /**
4310                          * {@inheritDoc}
4311                          */

4312                         public String getSymbol() {
4313                             return symbol;
4314                         }
4315
4316                         /**
4317                          * {@inheritDoc}
4318                          */

4319                         public AnnotationList getDeclaredAnnotations() {
4320                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
4321                         }
4322                     }
4323
4324                     /**
4325                      * A generic type token that represent a formal type variable, i.e. a type variable including its upper bounds.
4326                      */

4327                     @HashCodeAndEqualsPlugin.Enhance
4328                     protected static class Formal implements GenericTypeToken.OfFormalTypeVariable {
4329
4330                         /**
4331                          * This type variable's nominal symbol.
4332                          */

4333                         private final String symbol;
4334
4335                         /**
4336                          * A list of tokens that represent this type variable's upper bounds.
4337                          */

4338                         private final List<GenericTypeToken> boundTypeTokens;
4339
4340                         /**
4341                          * Creates generic type token that represent a formal type variable.
4342                          *
4343                          * @param symbol          This type variable's nominal symbol.
4344                          * @param boundTypeTokens A list of tokens that represent this type variable's upper bounds.
4345                          */

4346                         protected Formal(String symbol, List<GenericTypeToken> boundTypeTokens) {
4347                             this.symbol = symbol;
4348                             this.boundTypeTokens = boundTypeTokens;
4349                         }
4350
4351                         /**
4352                          * {@inheritDoc}
4353                          */

4354                         public Generic toGenericType(TypePool typePool,
4355                                                      TypeVariableSource typeVariableSource,
4356                                                      Map<String, List<AnnotationToken>> annotationTokens,
4357                                                      Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens) {
4358                             return new LazyTypeVariable(typePool,
4359                                     typeVariableSource,
4360                                     annotationTokens == null
4361                                             ? Collections.<String, List<AnnotationToken>>emptyMap()
4362                                             : annotationTokens,
4363                                     boundaryAnnotationTokens == null
4364                                             ? Collections.<Integer, Map<String, List<AnnotationToken>>>emptyMap()
4365                                             : boundaryAnnotationTokens,
4366                                     symbol,
4367                                     boundTypeTokens);
4368                         }
4369
4370                         /**
4371                          * A type description that represents a type variable with bounds that are resolved lazily.
4372                          */

4373                         protected static class LazyTypeVariable extends Generic.OfTypeVariable {
4374
4375                             /**
4376                              * The type pool to use for locating type descriptions.
4377                              */

4378                             private final TypePool typePool;
4379
4380                             /**
4381                              * The type variable source to use for locating type variables.
4382                              */

4383                             private final TypeVariableSource typeVariableSource;
4384
4385                             /**
4386                              * The type variable's type annotation tokens.
4387                              */

4388                             private final Map<String, List<AnnotationToken>> annotationTokens;
4389
4390                             /**
4391                              * A mapping of the type variable bounds' type annotation tokens by their indices.
4392                              */

4393                             private final Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens;
4394
4395                             /**
4396                              * The type variable's symbol.
4397                              */

4398                             private final String symbol;
4399
4400                             /**
4401                              * Tokenized representations of the type variables bound types.
4402                              */

4403                             private final List<GenericTypeToken> boundTypeTokens;
4404
4405                             /**
4406                              * Creates a lazy type description of a type variables.
4407                              *
4408                              * @param typePool                 The type pool to use for locating type descriptions.
4409                              * @param typeVariableSource       The type variable source to use for locating type variables.
4410                              * @param annotationTokens         The type variable's type annotation tokens.
4411                              * @param boundaryAnnotationTokens A mapping of the type variable bounds' type annotation tokens by their indices.
4412                              * @param symbol                   The type variable's symbol.
4413                              * @param boundTypeTokens          Tokenized representations of the type variables bound types.
4414                              */

4415                             protected LazyTypeVariable(TypePool typePool,
4416                                                        TypeVariableSource typeVariableSource,
4417                                                        Map<String, List<AnnotationToken>> annotationTokens,
4418                                                        Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens,
4419                                                        String symbol,
4420                                                        List<GenericTypeToken> boundTypeTokens) {
4421                                 this.typePool = typePool;
4422                                 this.typeVariableSource = typeVariableSource;
4423                                 this.annotationTokens = annotationTokens;
4424                                 this.boundaryAnnotationTokens = boundaryAnnotationTokens;
4425                                 this.symbol = symbol;
4426                                 this.boundTypeTokens = boundTypeTokens;
4427                             }
4428
4429                             /**
4430                              * {@inheritDoc}
4431                              */

4432                             public TypeList.Generic getUpperBounds() {
4433                                 return new LazyBoundTokenList(typePool, typeVariableSource, boundaryAnnotationTokens, boundTypeTokens);
4434                             }
4435
4436                             /**
4437                              * {@inheritDoc}
4438                              */

4439                             public TypeVariableSource getTypeVariableSource() {
4440                                 return typeVariableSource;
4441                             }
4442
4443                             /**
4444                              * {@inheritDoc}
4445                              */

4446                             public String getSymbol() {
4447                                 return symbol;
4448                             }
4449
4450                             /**
4451                              * {@inheritDoc}
4452                              */

4453                             public AnnotationList getDeclaredAnnotations() {
4454                                 return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(EMPTY_TYPE_PATH));
4455                             }
4456
4457                             /**
4458                              * A list representing a formal type variable's bounds.
4459                              */

4460                             protected static class LazyBoundTokenList extends TypeList.Generic.AbstractBase {
4461
4462                                 /**
4463                                  * The type pool to use.
4464                                  */

4465                                 private final TypePool typePool;
4466
4467                                 /**
4468                                  * The type variable source for locating type variables.
4469                                  */

4470                                 private final TypeVariableSource typeVariableSource;
4471
4472                                 /**
4473                                  * A mapping of the bound type's type annotations by their bound index.
4474                                  */

4475                                 private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
4476
4477                                 /**
4478                                  * The bound types in their tokenized form.
4479                                  */

4480                                 private final List<GenericTypeToken> boundTypeTokens;
4481
4482                                 /**
4483                                  * Creates a new lazy bound token list for a type variable.
4484                                  *
4485                                  * @param typePool           The type pool to use.
4486                                  * @param typeVariableSource The type variable source for locating type variables.
4487                                  * @param annotationTokens   A mapping of the bound type's type annotations by their bound index.
4488                                  * @param boundTypeTokens    The bound types in their tokenized form.
4489                                  */

4490                                 protected LazyBoundTokenList(TypePool typePool,
4491                                                              TypeVariableSource typeVariableSource,
4492                                                              Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4493                                                              List<GenericTypeToken> boundTypeTokens) {
4494                                     this.typePool = typePool;
4495                                     this.typeVariableSource = typeVariableSource;
4496                                     this.annotationTokens = annotationTokens;
4497                                     this.boundTypeTokens = boundTypeTokens;
4498                                 }
4499
4500                                 /**
4501                                  * {@inheritDoc}
4502                                  */

4503                                 public Generic get(int index) {
4504                                     // Avoid resolution of interface bound type unless a type annotation can be possibly resolved.
4505                                     Map<String, List<AnnotationToken>> annotationTokens = !this.annotationTokens.containsKey(index) && !this.annotationTokens.containsKey(index + 1)
4506                                             ? Collections.<String, List<AnnotationToken>>emptyMap()
4507                                             : this.annotationTokens.get(index + (boundTypeTokens.get(0).isPrimaryBound(typePool) ? 0 : 1));
4508                                     return boundTypeTokens.get(index).toGenericType(typePool,
4509                                             typeVariableSource,
4510                                             EMPTY_TYPE_PATH,
4511                                             annotationTokens == null
4512                                                     ? Collections.<String, List<AnnotationToken>>emptyMap()
4513                                                     : annotationTokens);
4514                                 }
4515
4516                                 /**
4517                                  * {@inheritDoc}
4518                                  */

4519                                 public int size() {
4520                                     return boundTypeTokens.size();
4521                                 }
4522                             }
4523                         }
4524                     }
4525                 }
4526
4527                 /**
4528                  * A generic type token that represents a generic array.
4529                  */

4530                 @HashCodeAndEqualsPlugin.Enhance
4531                 class ForGenericArray implements GenericTypeToken {
4532
4533                     /**
4534                      * The array's component type.
4535                      */

4536                     private final GenericTypeToken componentTypeToken;
4537
4538                     /**
4539                      * Creates a generic type token that represents a generic array.
4540                      *
4541                      * @param componentTypeToken The array's component type.
4542                      */

4543                     protected ForGenericArray(GenericTypeToken componentTypeToken) {
4544                         this.componentTypeToken = componentTypeToken;
4545                     }
4546
4547                     /**
4548                      * {@inheritDoc}
4549                      */

4550                     public Generic toGenericType(TypePool typePool, TypeVariableSource typeVariableSource, String typePath, Map<String, List<AnnotationToken>> annotationTokens) {
4551                         return new LazyGenericArray(typePool, typeVariableSource, typePath, annotationTokens, componentTypeToken);
4552                     }
4553
4554                     /**
4555                      * {@inheritDoc}
4556                      */

4557                     public boolean isPrimaryBound(TypePool typePool) {
4558                         throw new IllegalStateException("A generic array type cannot be a type variable bound: " + this);
4559                     }
4560
4561                     /**
4562                      * {@inheritDoc}
4563                      */

4564                     public String getTypePathPrefix() {
4565                         throw new IllegalStateException("A generic array type cannot be the owner of a nested type: " + this);
4566                     }
4567
4568                     /**
4569                      * A generic type representation of a generic array.
4570                      */

4571                     protected static class LazyGenericArray extends Generic.OfGenericArray {
4572
4573                         /**
4574                          * The type pool to use.
4575                          */

4576                         private final TypePool typePool;
4577
4578                         /**
4579                          * The type variable source for locating type variables.
4580                          */

4581                         private final TypeVariableSource typeVariableSource;
4582
4583                         /**
4584                          * This type's type path.
4585                          */

4586                         private final String typePath;
4587
4588                         /**
4589                          * This type's type annotations.
4590                          */

4591                         private final Map<String, List<AnnotationToken>> annotationTokens;
4592
4593                         /**
4594                          * A tokenized representation of this generic arrays's component type.
4595                          */

4596                         private final GenericTypeToken componentTypeToken;
4597
4598                         /**
4599                          * Creates a new lazy generic array.
4600                          *
4601                          * @param typePool           The type pool to use.
4602                          * @param typeVariableSource The type variable source for locating type variables.
4603                          * @param typePath           This type's type path.
4604                          * @param annotationTokens   This type's type annotations.
4605                          * @param componentTypeToken A tokenized representation of this generic arrays's component type.
4606                          */

4607                         protected LazyGenericArray(TypePool typePool,
4608                                                    TypeVariableSource typeVariableSource,
4609                                                    String typePath,
4610                                                    Map<String, List<AnnotationToken>> annotationTokens,
4611                                                    GenericTypeToken componentTypeToken) {
4612                             this.typePool = typePool;
4613                             this.typeVariableSource = typeVariableSource;
4614                             this.typePath = typePath;
4615                             this.annotationTokens = annotationTokens;
4616                             this.componentTypeToken = componentTypeToken;
4617                         }
4618
4619                         /**
4620                          * {@inheritDoc}
4621                          */

4622                         public Generic getComponentType() {
4623                             return componentTypeToken.toGenericType(typePool, typeVariableSource, typePath + COMPONENT_TYPE_PATH, annotationTokens);
4624                         }
4625
4626                         /**
4627                          * {@inheritDoc}
4628                          */

4629                         public AnnotationList getDeclaredAnnotations() {
4630                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
4631                         }
4632                     }
4633                 }
4634
4635                 /**
4636                  * A generic type token for a wildcard that is bound below.
4637                  */

4638                 @HashCodeAndEqualsPlugin.Enhance
4639                 class ForLowerBoundWildcard implements GenericTypeToken {
4640
4641                     /**
4642                      * A token that represents the wildcard's lower bound.
4643                      */

4644                     private final GenericTypeToken boundTypeToken;
4645
4646                     /**
4647                      * Creates a generic type token for a wildcard that is bound below.
4648                      *
4649                      * @param boundTypeToken A token that represents the wildcard's lower bound.
4650                      */

4651                     protected ForLowerBoundWildcard(GenericTypeToken boundTypeToken) {
4652                         this.boundTypeToken = boundTypeToken;
4653                     }
4654
4655                     /**
4656                      * {@inheritDoc}
4657                      */

4658                     public Generic toGenericType(TypePool typePool, TypeVariableSource typeVariableSource, String typePath, Map<String, List<AnnotationToken>> annotationTokens) {
4659                         return new LazyLowerBoundWildcard(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
4660                     }
4661
4662                     /**
4663                      * {@inheritDoc}
4664                      */

4665                     public boolean isPrimaryBound(TypePool typePool) {
4666                         throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
4667                     }
4668
4669                     /**
4670                      * {@inheritDoc}
4671                      */

4672                     public String getTypePathPrefix() {
4673                         throw new IllegalStateException("A lower bound wildcard cannot be the owner of a nested type: " + this);
4674                     }
4675
4676                     /**
4677                      * A generic type representation of a lower bound wildcard.
4678                      */

4679                     protected static class LazyLowerBoundWildcard extends Generic.OfWildcardType {
4680
4681                         /**
4682                          * The type pool to use.
4683                          */

4684                         private final TypePool typePool;
4685
4686                         /**
4687                          * The type variable source for locating type variables.
4688                          */

4689                         private final TypeVariableSource typeVariableSource;
4690
4691                         /**
4692                          * This type's type path.
4693                          */

4694                         private final String typePath;
4695
4696                         /**
4697                          * This type's type annotations.
4698                          */

4699                         private final Map<String, List<AnnotationToken>> annotationTokens;
4700
4701                         /**
4702                          * A tokenized representation of this wildcard's bound.
4703                          */

4704                         private final GenericTypeToken boundTypeToken;
4705
4706                         /**
4707                          * Creates a new lazy lower bound wildcard.
4708                          *
4709                          * @param typePool           The type pool to use.
4710                          * @param typeVariableSource The type variable source for locating type variables.
4711                          * @param typePath           This type's type path.
4712                          * @param annotationTokens   This type's type annotations.
4713                          * @param boundTypeToken     A tokenized representation of this wildcard's bound.
4714                          */

4715                         protected LazyLowerBoundWildcard(TypePool typePool,
4716                                                          TypeVariableSource typeVariableSource,
4717                                                          String typePath,
4718                                                          Map<String, List<AnnotationToken>> annotationTokens,
4719                                                          GenericTypeToken boundTypeToken) {
4720                             this.typePool = typePool;
4721                             this.typeVariableSource = typeVariableSource;
4722                             this.typePath = typePath;
4723                             this.annotationTokens = annotationTokens;
4724                             this.boundTypeToken = boundTypeToken;
4725                         }
4726
4727                         /**
4728                          * {@inheritDoc}
4729                          */

4730                         public TypeList.Generic getUpperBounds() {
4731                             return new TypeList.Generic.Explicit(Generic.OBJECT);
4732                         }
4733
4734                         /**
4735                          * {@inheritDoc}
4736                          */

4737                         public TypeList.Generic getLowerBounds() {
4738                             return new LazyTokenList.ForWildcardBound(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
4739                         }
4740
4741                         /**
4742                          * {@inheritDoc}
4743                          */

4744                         public AnnotationList getDeclaredAnnotations() {
4745                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
4746                         }
4747                     }
4748                 }
4749
4750                 /**
4751                  * A generic type token for a wildcard that is bound above.
4752                  */

4753                 @HashCodeAndEqualsPlugin.Enhance
4754                 class ForUpperBoundWildcard implements GenericTypeToken {
4755
4756                     /**
4757                      * A token that represents the wildcard's upper bound.
4758                      */

4759                     private final GenericTypeToken boundTypeToken;
4760
4761                     /**
4762                      * Creates a generic type token for a wildcard that is bound above.
4763                      *
4764                      * @param boundTypeToken A token that represents the wildcard's upper bound.
4765                      */

4766                     protected ForUpperBoundWildcard(GenericTypeToken boundTypeToken) {
4767                         this.boundTypeToken = boundTypeToken;
4768                     }
4769
4770                     /**
4771                      * {@inheritDoc}
4772                      */

4773                     public Generic toGenericType(TypePool typePool,
4774                                                  TypeVariableSource typeVariableSource,
4775                                                  String typePath,
4776                                                  Map<String, List<AnnotationToken>> annotationTokens) {
4777                         return new LazyUpperBoundWildcard(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
4778                     }
4779
4780                     /**
4781                      * {@inheritDoc}
4782                      */

4783                     public boolean isPrimaryBound(TypePool typePool) {
4784                         throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
4785                     }
4786
4787                     /**
4788                      * {@inheritDoc}
4789                      */

4790                     public String getTypePathPrefix() {
4791                         throw new IllegalStateException("An upper bound wildcard cannot be the owner of a nested type: " + this);
4792                     }
4793
4794                     /**
4795                      * A generic type representation of a tokenized wildcard with an upper bound.
4796                      */

4797                     protected static class LazyUpperBoundWildcard extends Generic.OfWildcardType {
4798
4799                         /**
4800                          * The type pool to use.
4801                          */

4802                         private final TypePool typePool;
4803
4804                         /**
4805                          * The type variable source for locating type variables.
4806                          */

4807                         private final TypeVariableSource typeVariableSource;
4808
4809                         /**
4810                          * This type's type path.
4811                          */

4812                         private final String typePath;
4813
4814                         /**
4815                          * This type's type annotations.
4816                          */

4817                         private final Map<String, List<AnnotationToken>> annotationTokens;
4818
4819                         /**
4820                          * A tokenized representation of this wildcard's bound.
4821                          */

4822                         private final GenericTypeToken boundTypeToken;
4823
4824                         /**
4825                          * Creates a new lazy upper bound wildcard.
4826                          *
4827                          * @param typePool           The type pool to use.
4828                          * @param typeVariableSource The type variable source for locating type variables.
4829                          * @param typePath           This type's type path.
4830                          * @param annotationTokens   This type's type annotations.
4831                          * @param boundTypeToken     A tokenized representation of this wildcard's bound.
4832                          */

4833                         protected LazyUpperBoundWildcard(TypePool typePool,
4834                                                          TypeVariableSource typeVariableSource,
4835                                                          String typePath,
4836                                                          Map<String, List<AnnotationToken>> annotationTokens,
4837                                                          GenericTypeToken boundTypeToken) {
4838                             this.typePool = typePool;
4839                             this.typeVariableSource = typeVariableSource;
4840                             this.typePath = typePath;
4841                             this.annotationTokens = annotationTokens;
4842                             this.boundTypeToken = boundTypeToken;
4843                         }
4844
4845                         /**
4846                          * {@inheritDoc}
4847                          */

4848                         public TypeList.Generic getUpperBounds() {
4849                             return new LazyTokenList.ForWildcardBound(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
4850                         }
4851
4852                         /**
4853                          * {@inheritDoc}
4854                          */

4855                         public TypeList.Generic getLowerBounds() {
4856                             return new TypeList.Generic.Empty();
4857                         }
4858
4859                         /**
4860                          * {@inheritDoc}
4861                          */

4862                         public AnnotationList getDeclaredAnnotations() {
4863                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
4864                         }
4865                     }
4866                 }
4867
4868                 /**
4869                  * A generic type token that represents a parameterized type.
4870                  */

4871                 @HashCodeAndEqualsPlugin.Enhance
4872                 class ForParameterizedType implements GenericTypeToken {
4873
4874                     /**
4875                      * The name of the parameterized type's erasure.
4876                      */

4877                     private final String name;
4878
4879                     /**
4880                      * A list of tokens that represent the parameters of the represented type.
4881                      */

4882                     private final List<GenericTypeToken> parameterTypeTokens;
4883
4884                     /**
4885                      * Creates a type token that represents a parameterized type.
4886                      *
4887                      * @param name                The name of the parameterized type's erasure.
4888                      * @param parameterTypeTokens A list of tokens that represent the parameters of the represented type.
4889                      */

4890                     protected ForParameterizedType(String name, List<GenericTypeToken> parameterTypeTokens) {
4891                         this.name = name;
4892                         this.parameterTypeTokens = parameterTypeTokens;
4893                     }
4894
4895                     /**
4896                      * {@inheritDoc}
4897                      */

4898                     public Generic toGenericType(TypePool typePool, TypeVariableSource typeVariableSource, String typePath, Map<String, List<AnnotationToken>> annotationTokens) {
4899                         return new LazyParameterizedType(typePool, typeVariableSource, typePath, annotationTokens, name, parameterTypeTokens);
4900                     }
4901
4902                     /**
4903                      * {@inheritDoc}
4904                      */

4905                     public boolean isPrimaryBound(TypePool typePool) {
4906                         return !typePool.describe(name).resolve().isInterface();
4907                     }
4908
4909                     /**
4910                      * {@inheritDoc}
4911                      */

4912                     public String getTypePathPrefix() {
4913                         return String.valueOf(INNER_CLASS_PATH);
4914                     }
4915
4916                     /**
4917                      * A generic type token to describe a parameterized type description with a generic owner type.
4918                      */

4919                     @HashCodeAndEqualsPlugin.Enhance
4920                     public static class Nested implements GenericTypeToken {
4921
4922                         /**
4923                          * The name of the parameterized type's erasure.
4924                          */

4925                         private final String name;
4926
4927                         /**
4928                          * A list of tokens that represent the parameters of the represented type.
4929                          */

4930                         private final List<GenericTypeToken> parameterTypeTokens;
4931
4932                         /**
4933                          * A token that describes the described parameterized type's owner type.
4934                          */

4935                         private final GenericTypeToken ownerTypeToken;
4936
4937                         /**
4938                          * Creates a type token that represents a parameterized type.
4939                          *
4940                          * @param name                The name of the parameterized type's erasure.
4941                          * @param parameterTypeTokens A list of tokens that represent the parameters of the represented type.
4942                          * @param ownerTypeToken      A token that describes the described parameterized type's owner type.
4943                          */

4944                         protected Nested(String name, List<GenericTypeToken> parameterTypeTokens, GenericTypeToken ownerTypeToken) {
4945                             this.name = name;
4946                             this.parameterTypeTokens = parameterTypeTokens;
4947                             this.ownerTypeToken = ownerTypeToken;
4948                         }
4949
4950                         /**
4951                          * {@inheritDoc}
4952                          */

4953                         public Generic toGenericType(TypePool typePool,
4954                                                      TypeVariableSource typeVariableSource,
4955                                                      String typePath,
4956                                                      Map<String, List<AnnotationToken>> annotationTokens) {
4957                             return new LazyParameterizedType(typePool, typeVariableSource, typePath, annotationTokens, name, parameterTypeTokens, ownerTypeToken);
4958                         }
4959
4960                         /**
4961                          * {@inheritDoc}
4962                          */

4963                         public String getTypePathPrefix() {
4964                             return ownerTypeToken.getTypePathPrefix() + INNER_CLASS_PATH;
4965                         }
4966
4967                         /**
4968                          * {@inheritDoc}
4969                          */

4970                         public boolean isPrimaryBound(TypePool typePool) {
4971                             return !typePool.describe(name).resolve().isInterface();
4972                         }
4973
4974                         /**
4975                          * A lazy description of a parameterized type with an owner type.
4976                          */

4977                         protected static class LazyParameterizedType extends Generic.OfParameterizedType {
4978
4979                             /**
4980                              * The type pool that is used for locating a generic type.
4981                              */

4982                             private final TypePool typePool;
4983
4984                             /**
4985                              * The type variable source to use for resolving type variables.
4986                              */

4987                             private final TypeVariableSource typeVariableSource;
4988
4989                             /**
4990                              * This type's type path.
4991                              */

4992                             private final String typePath;
4993
4994                             /**
4995                              * A mapping of type annotations for this type.
4996                              */

4997                             private final Map<String, List<AnnotationToken>> annotationTokens;
4998
4999                             /**
5000                              * The binary name of this parameterized type's raw type.
5001                              */

5002                             private final String name;
5003
5004                             /**
5005                              * Tokens that represent this parameterized type's parameters.
5006                              */

5007                             private final List<GenericTypeToken> parameterTypeTokens;
5008
5009                             /**
5010                              * A token that represents this type's owner type.
5011                              */

5012                             private final GenericTypeToken ownerTypeToken;
5013
5014                             /**
5015                              * Creates a new lazy parameterized type.
5016                              *
5017                              * @param typePool            The type pool that is used for locating a generic type.
5018                              * @param typeVariableSource  The type variable source to use for resolving type variables.
5019                              * @param typePath            This type's type path.
5020                              * @param annotationTokens    A mapping of type annotations for this type.
5021                              * @param name                The binary name of this parameterized type's raw type.
5022                              * @param parameterTypeTokens Tokens that represent this parameterized type's parameters.
5023                              * @param ownerTypeToken      A token that represents this type's owner type.
5024                              */

5025                             protected LazyParameterizedType(TypePool typePool,
5026                                                             TypeVariableSource typeVariableSource,
5027                                                             String typePath,
5028                                                             Map<String, List<AnnotationToken>> annotationTokens,
5029                                                             String name,
5030                                                             List<GenericTypeToken> parameterTypeTokens,
5031                                                             GenericTypeToken ownerTypeToken) {
5032                                 this.typePool = typePool;
5033                                 this.typeVariableSource = typeVariableSource;
5034                                 this.typePath = typePath;
5035                                 this.annotationTokens = annotationTokens;
5036                                 this.name = name;
5037                                 this.parameterTypeTokens = parameterTypeTokens;
5038                                 this.ownerTypeToken = ownerTypeToken;
5039                             }
5040
5041                             /**
5042                              * {@inheritDoc}
5043                              */

5044                             public TypeDescription asErasure() {
5045                                 return typePool.describe(name).resolve();
5046                             }
5047
5048                             /**
5049                              * {@inheritDoc}
5050                              */

5051                             public TypeList.Generic getTypeArguments() {
5052                                 return new LazyTokenList(typePool, typeVariableSource, typePath + ownerTypeToken.getTypePathPrefix(), annotationTokens, parameterTypeTokens);
5053                             }
5054
5055                             /**
5056                              * {@inheritDoc}
5057                              */

5058                             public Generic getOwnerType() {
5059                                 return ownerTypeToken.toGenericType(typePool, typeVariableSource, typePath, annotationTokens);
5060                             }
5061
5062                             /**
5063                              * {@inheritDoc}
5064                              */

5065                             public AnnotationList getDeclaredAnnotations() {
5066                                 return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath + ownerTypeToken.getTypePathPrefix()));
5067                             }
5068                         }
5069                     }
5070
5071                     /**
5072                      * A generic type description that represents a parameterized type <b>without</b> an enclosing generic owner type.
5073                      */

5074                     protected static class LazyParameterizedType extends Generic.OfParameterizedType {
5075
5076                         /**
5077                          * The type pool that is used for locating a generic type.
5078                          */

5079                         private final TypePool typePool;
5080
5081                         /**
5082                          * The type variable source to use for resolving type variables.
5083                          */

5084                         private final TypeVariableSource typeVariableSource;
5085
5086                         /**
5087                          * This type's type path.
5088                          */

5089                         private final String typePath;
5090
5091                         /**
5092                          * A mapping of the represent type's annotation tokens.
5093                          */

5094                         private final Map<String, List<AnnotationToken>> annotationTokens;
5095
5096                         /**
5097                          * The binary name of the raw type.
5098                          */

5099                         private final String name;
5100
5101                         /**
5102                          * A list of type tokens representing this type's bounds.
5103                          */

5104                         private final List<GenericTypeToken> parameterTypeTokens;
5105
5106                         /**
5107                          * Creates a new description of a parameterized type.
5108                          *
5109                          * @param typePool            The type pool that is used for locating a generic type.
5110                          * @param typeVariableSource  The type variable source to use for resolving type variables.
5111                          * @param typePath            This type's type path.
5112                          * @param annotationTokens    A mapping of the represent type's annotation tokens,
5113                          * @param name                The binary name of the raw type.
5114                          * @param parameterTypeTokens A list of type tokens representing this type's bounds.
5115                          */

5116                         protected LazyParameterizedType(TypePool typePool,
5117                                                         TypeVariableSource typeVariableSource,
5118                                                         String typePath,
5119                                                         Map<String, List<AnnotationToken>> annotationTokens,
5120                                                         String name,
5121                                                         List<GenericTypeToken> parameterTypeTokens) {
5122                             this.typePool = typePool;
5123                             this.typeVariableSource = typeVariableSource;
5124                             this.typePath = typePath;
5125                             this.annotationTokens = annotationTokens;
5126                             this.name = name;
5127                             this.parameterTypeTokens = parameterTypeTokens;
5128                         }
5129
5130                         /**
5131                          * {@inheritDoc}
5132                          */

5133                         public TypeDescription asErasure() {
5134                             return typePool.describe(name).resolve();
5135                         }
5136
5137                         /**
5138                          * {@inheritDoc}
5139                          */

5140                         public TypeList.Generic getTypeArguments() {
5141                             return new LazyTokenList(typePool, typeVariableSource, typePath, annotationTokens, parameterTypeTokens);
5142                         }
5143
5144                         /**
5145                          * {@inheritDoc}
5146                          */

5147                         public Generic getOwnerType() {
5148                             TypeDescription ownerType = typePool.describe(name).resolve().getEnclosingType();
5149                             return ownerType == null
5150                                     ? Generic.UNDEFINED
5151                                     : ownerType.asGenericType();
5152                         }
5153
5154                         /**
5155                          * {@inheritDoc}
5156                          */

5157                         public AnnotationList getDeclaredAnnotations() {
5158                             return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
5159                         }
5160                     }
5161                 }
5162
5163                 /**
5164                  * A lazy list of type tokens.
5165                  */

5166                 class LazyTokenList extends TypeList.Generic.AbstractBase {
5167
5168                     /**
5169                      * The type pool that is used for locating a generic type.
5170                      */

5171                     private final TypePool typePool;
5172
5173                     /**
5174                      * The type variable source to use for resolving type variables.
5175                      */

5176                     private final TypeVariableSource typeVariableSource;
5177
5178                     /**
5179                      * The represented types' type path to which an index step is added upon resolution.
5180                      */

5181                     private final String typePath;
5182
5183                     /**
5184                      * A mapping of the represent types' annotation tokens.
5185                      */

5186                     private final Map<String, List<AnnotationToken>> annotationTokens;
5187
5188                     /**
5189                      * A list of type tokens this list represents.
5190                      */

5191                     private final List<GenericTypeToken> genericTypeTokens;
5192
5193                     /**
5194                      * Creates a new type list that represents a list of tokenized types.
5195                      *
5196                      * @param typePool           The type pool that is used for locating a generic type.
5197                      * @param typeVariableSource The type variable source to use for resolving type variables.
5198                      * @param typePath           The represented types' type path to which an index step is added upon resolution.
5199                      * @param annotationTokens   A mapping of the represent types' annotation tokens,
5200                      * @param genericTypeTokens  A list of type tokens this list represents.
5201                      */

5202                     protected LazyTokenList(TypePool typePool,
5203                                             TypeVariableSource typeVariableSource,
5204                                             String typePath,
5205                                             Map<String, List<AnnotationToken>> annotationTokens,
5206                                             List<GenericTypeToken> genericTypeTokens) {
5207                         this.typePool = typePool;
5208                         this.typeVariableSource = typeVariableSource;
5209                         this.typePath = typePath;
5210                         this.annotationTokens = annotationTokens;
5211                         this.genericTypeTokens = genericTypeTokens;
5212                     }
5213
5214                     /**
5215                      * {@inheritDoc}
5216                      */

5217                     public Generic get(int index) {
5218                         return genericTypeTokens.get(index).toGenericType(typePool, typeVariableSource, typePath + index + INDEXED_TYPE_DELIMITER, annotationTokens);
5219                     }
5220
5221                     /**
5222                      * {@inheritDoc}
5223                      */

5224                     public int size() {
5225                         return genericTypeTokens.size();
5226                     }
5227
5228                     /**
5229                      * A generic type description representing a tokenized wildcard bound.
5230                      */

5231                     protected static class ForWildcardBound extends TypeList.Generic.AbstractBase {
5232
5233                         /**
5234                          * The type pool that is used for locating a generic type.
5235                          */

5236                         private final TypePool typePool;
5237
5238                         /**
5239                          * The type variable source to use for resolving type variables.
5240                          */

5241                         private final TypeVariableSource typeVariableSource;
5242
5243                         /**
5244                          * The represented types' type path to which a wildcard step is added upon resolution.
5245                          */

5246                         private final String typePath;
5247
5248                         /**
5249                          * A mapping of the represent types' annotation tokens.
5250                          */

5251                         private final Map<String, List<AnnotationToken>> annotationTokens;
5252
5253                         /**
5254                          * A token representing the wildcard's bound.
5255                          */

5256                         private final GenericTypeToken genericTypeToken;
5257
5258                         /**
5259                          * @param typePool           The type pool that is used for locating a generic type.
5260                          * @param typeVariableSource The type variable source to use for resolving type variables.
5261                          * @param typePath           The represented types' type path to which a wildcard step is added upon resolution.
5262                          * @param annotationTokens   A mapping of the represent types' annotation tokens,
5263                          * @param genericTypeToken   A token representing the wildcard's bound.
5264                          */

5265                         protected ForWildcardBound(TypePool typePool,
5266                                                    TypeVariableSource typeVariableSource,
5267                                                    String typePath,
5268                                                    Map<String, List<AnnotationToken>> annotationTokens,
5269                                                    GenericTypeToken genericTypeToken) {
5270                             this.typePool = typePool;
5271                             this.typeVariableSource = typeVariableSource;
5272                             this.typePath = typePath;
5273                             this.annotationTokens = annotationTokens;
5274                             this.genericTypeToken = genericTypeToken;
5275                         }
5276
5277                         /**
5278                          * {@inheritDoc}
5279                          */

5280                         public Generic get(int index) {
5281                             if (index == 0) {
5282                                 return genericTypeToken.toGenericType(typePool, typeVariableSource, typePath + WILDCARD_TYPE_PATH, annotationTokens);
5283                             } else {
5284                                 throw new IndexOutOfBoundsException("index = " + index);
5285                             }
5286                         }
5287
5288                         /**
5289                          * {@inheritDoc}
5290                          */

5291                         public int size() {
5292                             return 1;
5293                         }
5294                     }
5295                 }
5296             }
5297
5298             /**
5299              * A token for representing collected data on an annotation.
5300              */

5301             @HashCodeAndEqualsPlugin.Enhance
5302             protected static class AnnotationToken {
5303
5304                 /**
5305                  * The descriptor of the represented annotation.
5306                  */

5307                 private final String descriptor;
5308
5309                 /**
5310                  * A map of annotation value names to their value representations.
5311                  */

5312                 private final Map<String, AnnotationValue<?, ?>> values;
5313
5314                 /**
5315                  * Creates a new annotation token.
5316                  *
5317                  * @param descriptor The descriptor of the represented annotation.
5318                  * @param values     A map of annotation value names to their value representations.
5319                  */

5320                 protected AnnotationToken(String descriptor, Map<String, AnnotationValue<?, ?>> values) {
5321                     this.descriptor = descriptor;
5322                     this.values = values;
5323                 }
5324
5325                 /**
5326                  * Returns a map of annotation value names to their value representations.
5327                  *
5328                  * @return A map of annotation value names to their value representations.
5329                  */

5330                 protected Map<String, AnnotationValue<?, ?>> getValues() {
5331                     return values;
5332                 }
5333
5334                 /**
5335                  * Returns the annotation type's binary name.
5336                  *
5337                  * @return The annotation type's binary name.
5338                  */

5339                 protected String getBinaryName() {
5340                     return descriptor.substring(1, descriptor.length() - 1).replace('/', '.');
5341                 }
5342
5343                 /**
5344                  * Transforms this token into an annotation description.
5345                  *
5346                  * @param typePool The type pool to be used for looking up linked types.
5347                  * @return An optional description of this annotation's token.
5348                  */

5349                 private Resolution toAnnotationDescription(TypePool typePool) {
5350                     TypePool.Resolution resolution = typePool.describe(getBinaryName());
5351                     return resolution.isResolved()
5352                             ? new Resolution.Simple(new LazyAnnotationDescription(typePool, resolution.resolve(), values))
5353                             : new Resolution.Illegal(getBinaryName());
5354                 }
5355
5356                 /**
5357                  * A resolution for an annotation tokens. Any annotation is suppressed if its type is not available.
5358                  * This conforms to the handling of the Java reflection API.
5359                  */

5360                 protected interface Resolution {
5361
5362                     /**
5363                      * Returns {@code trueif the represented annotation could be resolved.
5364                      *
5365                      * @return {@code trueif the represented annotation could be resolved.
5366                      */

5367                     boolean isResolved();
5368
5369                     /**
5370                      * Returns the resolved annotation. This method throws an exception if this instance is not resolved.
5371                      *
5372                      * @return The resolved annotation. This method throws an exception if this instance is not resolved.
5373                      */

5374                     AnnotationDescription resolve();
5375
5376                     /**
5377                      * A simple resolved annotation.
5378                      */

5379                     @HashCodeAndEqualsPlugin.Enhance
5380                     class Simple implements Resolution {
5381
5382                         /**
5383                          * The represented annotation description.
5384                          */

5385                         private final AnnotationDescription annotationDescription;
5386
5387                         /**
5388                          * Creates a new simple resolution.
5389                          *
5390                          * @param annotationDescription The represented annotation description.
5391                          */

5392                         protected Simple(AnnotationDescription annotationDescription) {
5393                             this.annotationDescription = annotationDescription;
5394                         }
5395
5396                         /**
5397                          * {@inheritDoc}
5398                          */

5399                         public boolean isResolved() {
5400                             return true;
5401                         }
5402
5403                         /**
5404                          * {@inheritDoc}
5405                          */

5406                         public AnnotationDescription resolve() {
5407                             return annotationDescription;
5408                         }
5409                     }
5410
5411                     /**
5412                      * An illegal resolution.
5413                      */

5414                     @HashCodeAndEqualsPlugin.Enhance
5415                     class Illegal implements Resolution {
5416
5417                         /**
5418                          * The annotation's binary type name.
5419                          */

5420                         private final String annotationType;
5421
5422                         /**
5423                          * Creates a new illegal resolution.
5424                          *
5425                          * @param annotationType The annotation's binary type name.
5426                          */

5427                         public Illegal(String annotationType) {
5428                             this.annotationType = annotationType;
5429                         }
5430
5431                         /**
5432                          * {@inheritDoc}
5433                          */

5434                         public boolean isResolved() {
5435                             return false;
5436                         }
5437
5438                         /**
5439                          * {@inheritDoc}
5440                          */

5441                         public AnnotationDescription resolve() {
5442                             throw new IllegalStateException("Annotation type is not available: " + annotationType);
5443                         }
5444                     }
5445                 }
5446             }
5447
5448             /**
5449              * A token for representing collected data on a field.
5450              */

5451             @HashCodeAndEqualsPlugin.Enhance
5452             protected static class FieldToken {
5453
5454                 /**
5455                  * The name of the field.
5456                  */

5457                 private final String name;
5458
5459                 /**
5460                  * The modifiers of the represented field.
5461                  */

5462                 private final int modifiers;
5463
5464                 /**
5465                  * The descriptor of the field.
5466                  */

5467                 private final String descriptor;
5468
5469                 /**
5470                  * The field's generic signature as found in the class file or {@code nullif the field is not generic.
5471                  */

5472                 private final String genericSignature;
5473
5474                 /**
5475                  * The resolution of this field's generic type.
5476                  */

5477                 private final GenericTypeToken.Resolution.ForField signatureResolution;
5478
5479                 /**
5480                  * A mapping of the field type's type annotation tokens.
5481                  */

5482                 private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
5483
5484                 /**
5485                  * A list of annotation tokens representing the annotations of the represented field.
5486                  */

5487                 private final List<AnnotationToken> annotationTokens;
5488
5489                 /**
5490                  * Creates a new field token.
5491                  *
5492                  * @param name                 The name of the field.
5493                  * @param modifiers            The modifiers of the represented field.
5494                  * @param descriptor           The descriptor of the field.
5495                  * @param genericSignature     The field's generic signature as found in the class file or {@code nullif the field is not generic.
5496                  * @param typeAnnotationTokens A mapping of the field type's type annotation tokens.
5497                  * @param annotationTokens     A list of annotation tokens representing the annotations of the represented field.
5498                  */

5499                 protected FieldToken(String name,
5500                                      int modifiers,
5501                                      String descriptor,
5502                                      String genericSignature,
5503                                      Map<String, List<AnnotationToken>> typeAnnotationTokens,
5504                                      List<AnnotationToken> annotationTokens) {
5505                     this.modifiers = modifiers & ~Opcodes.ACC_DEPRECATED;
5506                     this.name = name;
5507                     this.descriptor = descriptor;
5508                     this.genericSignature = genericSignature;
5509                     signatureResolution = RAW_TYPES
5510                             ? GenericTypeToken.Resolution.Raw.INSTANCE
5511                             : GenericTypeExtractor.ForSignature.OfField.extract(genericSignature);
5512                     this.typeAnnotationTokens = typeAnnotationTokens;
5513                     this.annotationTokens = annotationTokens;
5514                 }
5515
5516                 /**
5517                  * Transforms this token into a lazy field description.
5518                  *
5519                  * @param lazyTypeDescription The lazy type description to attach this field description to.
5520                  * @return A field description resembling this field token.
5521                  */

5522                 private LazyFieldDescription toFieldDescription(LazyTypeDescription lazyTypeDescription) {
5523                     return lazyTypeDescription.new LazyFieldDescription(name,
5524                             modifiers,
5525                             descriptor,
5526                             genericSignature,
5527                             signatureResolution,
5528                             typeAnnotationTokens,
5529                             annotationTokens);
5530                 }
5531             }
5532
5533             /**
5534              * A token for representing collected data on a method.
5535              */

5536             @HashCodeAndEqualsPlugin.Enhance
5537             protected static class MethodToken {
5538
5539                 /**
5540                  * The internal name of the represented method.
5541                  */

5542                 private final String name;
5543
5544                 /**
5545                  * The modifiers of the represented method.
5546                  */

5547                 private final int modifiers;
5548
5549                 /**
5550                  * The descriptor of the represented method.
5551                  */

5552                 private final String descriptor;
5553
5554                 /**
5555                  * The methods's generic signature as found in the class file or {@code nullif the method is not generic.
5556                  */

5557                 private final String genericSignature;
5558
5559                 /**
5560                  * The generic type resolution of this method.
5561                  */

5562                 private final GenericTypeToken.Resolution.ForMethod signatureResolution;
5563
5564                 /**
5565                  * An array of internal names of the exceptions of the represented method or {@code nullif there
5566                  * are no such exceptions.
5567                  */

5568                 private final String[] exceptionName;
5569
5570                 /**
5571                  * A mapping of the type variables' type annotation tokens by their indices.
5572                  */

5573                 private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
5574
5575                 /**
5576                  * A mapping of the type variables' type bounds' type annotation tokens by their indices and each variable's index.
5577                  */

5578                 private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens;
5579
5580                 /**
5581                  * A mapping of the return type's type variable tokens.
5582                  */

5583                 private final Map<String, List<AnnotationToken>> returnTypeAnnotationTokens;
5584
5585                 /**
5586                  * A mapping of the parameter types' type annotation tokens by their indices.
5587                  */

5588                 private final Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens;
5589
5590                 /**
5591                  * A mapping of the exception types' type annotation tokens by their indices.
5592                  */

5593                 private final Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens;
5594
5595                 /**
5596                  * A mapping of the receiver type's annotation tokens.
5597                  */

5598                 private final Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens;
5599
5600                 /**
5601                  * A list of annotation tokens that are present on the represented method.
5602                  */

5603                 private final List<AnnotationToken> annotationTokens;
5604
5605                 /**
5606                  * A map of parameter indices to tokens that represent their annotations.
5607                  */

5608                 private final Map<Integer, List<AnnotationToken>> parameterAnnotationTokens;
5609
5610                 /**
5611                  * A list of tokens describing meta data of the method's parameters.
5612                  */

5613                 private final List<ParameterToken> parameterTokens;
5614
5615                 /**
5616                  * The default value of this method or {@code nullif there is no such value.
5617                  */

5618                 private final AnnotationValue<?, ?> defaultValue;
5619
5620                 /**
5621                  * Creates a new method token.
5622                  *
5623                  * @param name                              The name of the method.
5624                  * @param modifiers                         The modifiers of the represented method.
5625                  * @param descriptor                        The descriptor of the represented method.
5626                  * @param genericSignature                  The methods's generic signature as found in the class file or {@code nullif the method is not generic.
5627                  * @param exceptionName                     An array of internal names of the exceptions of the represented method or {@code nullif
5628                  *                                          there are no such exceptions.
5629                  * @param typeVariableAnnotationTokens      A mapping of the type variables' type annotation tokens by their indices.
5630                  * @param typeVariableBoundAnnotationTokens A mapping of the type variables' type bounds' type annotation tokens by their
5631                  *                                          index and each variable's index.
5632                  * @param returnTypeAnnotationTokens        A mapping of the return type's type variable tokens.
5633                  * @param parameterTypeAnnotationTokens     A mapping of the parameter types' type annotation tokens by their indices.
5634                  * @param exceptionTypeAnnotationTokens     A mapping of the exception types' type annotation tokens by their indices.
5635                  * @param receiverTypeAnnotationTokens      A mapping of the receiver type's annotation tokens.
5636                  * @param annotationTokens                  A list of annotation tokens that are present on the represented method.
5637                  * @param parameterAnnotationTokens         A map of parameter indices to tokens that represent their annotations.
5638                  * @param parameterTokens                   A list of tokens describing meta data of the method's parameters.
5639                  * @param defaultValue                      The default value of this method or {@code nullif there is no such value.
5640                  */

5641                 protected MethodToken(String name,
5642                                       int modifiers,
5643                                       String descriptor,
5644                                       String genericSignature,
5645                                       String[] exceptionName,
5646                                       Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
5647                                       Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens,
5648                                       Map<String, List<AnnotationToken>> returnTypeAnnotationTokens,
5649                                       Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens,
5650                                       Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens,
5651                                       Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens,
5652                                       List<AnnotationToken> annotationTokens,
5653                                       Map<Integer, List<AnnotationToken>> parameterAnnotationTokens,
5654                                       List<ParameterToken> parameterTokens,
5655                                       AnnotationValue<?, ?> defaultValue) {
5656                     this.modifiers = modifiers & ~Opcodes.ACC_DEPRECATED;
5657                     this.name = name;
5658                     this.descriptor = descriptor;
5659                     this.genericSignature = genericSignature;
5660                     signatureResolution = RAW_TYPES
5661                             ? GenericTypeToken.Resolution.Raw.INSTANCE
5662                             : GenericTypeExtractor.ForSignature.OfMethod.extract(genericSignature);
5663                     this.exceptionName = exceptionName;
5664                     this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
5665                     this.typeVariableBoundAnnotationTokens = typeVariableBoundAnnotationTokens;
5666                     this.returnTypeAnnotationTokens = returnTypeAnnotationTokens;
5667                     this.parameterTypeAnnotationTokens = parameterTypeAnnotationTokens;
5668                     this.exceptionTypeAnnotationTokens = exceptionTypeAnnotationTokens;
5669                     this.receiverTypeAnnotationTokens = receiverTypeAnnotationTokens;
5670                     this.annotationTokens = annotationTokens;
5671                     this.parameterAnnotationTokens = parameterAnnotationTokens;
5672                     this.parameterTokens = parameterTokens;
5673                     this.defaultValue = defaultValue;
5674                 }
5675
5676                 /**
5677                  * Transforms this method token to a method description that is attached to a lazy type description.
5678                  *
5679                  * @param lazyTypeDescription The lazy type description to attach this method description to.
5680                  * @return A method description representing this method token.
5681                  */

5682                 private MethodDescription.InDefinedShape toMethodDescription(LazyTypeDescription lazyTypeDescription) {
5683                     return lazyTypeDescription.new LazyMethodDescription(name,
5684                             modifiers,
5685                             descriptor,
5686                             genericSignature,
5687                             signatureResolution,
5688                             exceptionName,
5689                             typeVariableAnnotationTokens,
5690                             typeVariableBoundAnnotationTokens,
5691                             returnTypeAnnotationTokens,
5692                             parameterTypeAnnotationTokens,
5693                             exceptionTypeAnnotationTokens,
5694                             receiverTypeAnnotationTokens,
5695                             annotationTokens,
5696                             parameterAnnotationTokens,
5697                             parameterTokens,
5698                             defaultValue);
5699                 }
5700
5701                 /**
5702                  * A token representing a method's parameter.
5703                  */

5704                 @HashCodeAndEqualsPlugin.Enhance
5705                 protected static class ParameterToken {
5706
5707                     /**
5708                      * Donates an unknown name of a parameter.
5709                      */

5710                     protected static final String NO_NAME = null;
5711
5712                     /**
5713                      * Donates an unknown modifier of a parameter.
5714                      */

5715                     protected static final Integer NO_MODIFIERS = null;
5716
5717                     /**
5718                      * The name of the parameter or {@code nullif no explicit name for this parameter is known.
5719                      */

5720                     @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
5721                     private final String name;
5722
5723                     /**
5724                      * The modifiers of the parameter or {@code nullif no modifiers are known for this parameter.
5725                      */

5726                     @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
5727                     private final Integer modifiers;
5728
5729                     /**
5730                      * Creates a parameter token for a parameter without an explicit name and without specific modifiers.
5731                      */

5732                     protected ParameterToken() {
5733                         this(NO_NAME);
5734                     }
5735
5736                     /**
5737                      * Creates a parameter token for a parameter with an explicit name and without specific modifiers.
5738                      *
5739                      * @param name The name of the parameter.
5740                      */

5741                     protected ParameterToken(String name) {
5742                         this(name, NO_MODIFIERS);
5743                     }
5744
5745                     /**
5746                      * Creates a parameter token for a parameter with an explicit name and with specific modifiers.
5747                      *
5748                      * @param name      The name of the parameter.
5749                      * @param modifiers The modifiers of the parameter.
5750                      */

5751                     protected ParameterToken(String name, Integer modifiers) {
5752                         this.name = name;
5753                         this.modifiers = modifiers;
5754                     }
5755
5756                     /**
5757                      * Returns the name of the parameter or {@code nullif there is no such name.
5758                      *
5759                      * @return The name of the parameter or {@code nullif there is no such name.
5760                      */

5761                     protected String getName() {
5762                         return name;
5763                     }
5764
5765                     /**
5766                      * Returns the modifiers of the parameter or {@code nullif no modifiers are known.
5767                      *
5768                      * @return The modifiers of the parameter or {@code nullif no modifiers are known.
5769                      */

5770                     protected Integer getModifiers() {
5771                         return modifiers;
5772                     }
5773                 }
5774             }
5775
5776             /**
5777              * A token representing a record component.
5778              */

5779             @HashCodeAndEqualsPlugin.Enhance
5780             protected static class RecordComponentToken {
5781
5782                 /**
5783                  * The record component's name.
5784                  */

5785                 private final String name;
5786
5787                 /**
5788                  * The record component's descriptor.
5789                  */

5790                 private final String descriptor;
5791
5792                 /**
5793                  * The record component's generic signature or {@code nullif it is non-generic.
5794                  */

5795                 private final String genericSignature;
5796
5797                 /**
5798                  * The record component's signature resolution.
5799                  */

5800                 private final GenericTypeToken.Resolution.ForRecordComponent signatureResolution;
5801
5802                 /**
5803                  * A mapping of the record component's type annotations.
5804                  */

5805                 private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
5806
5807                 /**
5808                  * A list of the record component's annotations.
5809                  */

5810                 private final List<AnnotationToken> annotationTokens;
5811
5812                 /**
5813                  * Creates a new record component token.
5814                  *
5815                  * @param name                 The record component's name.
5816                  * @param descriptor           The record component's descriptor.
5817                  * @param genericSignature     The record component's generic signature or {@code nullif it is non-generic.
5818                  * @param typeAnnotationTokens A mapping of the record component's type annotations.
5819                  * @param annotationTokens     A list of the record component's annotations.
5820                  */

5821                 protected RecordComponentToken(String name,
5822                                                String descriptor,
5823                                                String genericSignature,
5824                                                Map<String, List<AnnotationToken>> typeAnnotationTokens,
5825                                                List<AnnotationToken> annotationTokens) {
5826                     this.name = name;
5827                     this.descriptor = descriptor;
5828                     this.genericSignature = genericSignature;
5829                     signatureResolution = RAW_TYPES
5830                             ? GenericTypeToken.Resolution.Raw.INSTANCE
5831                             : GenericTypeExtractor.ForSignature.OfRecordComponent.extract(genericSignature);
5832                     this.typeAnnotationTokens = typeAnnotationTokens;
5833                     this.annotationTokens = annotationTokens;
5834                 }
5835
5836                 /**
5837                  * Transforms this record component token to a record component description that is attached to a lazy type description.
5838                  *
5839                  * @param lazyTypeDescription The lazy type description to attach this record component description to.
5840                  * @return A record component description representing this record component token.
5841                  */

5842                 private RecordComponentDescription.InDefinedShape toRecordComponentDescription(LazyTypeDescription lazyTypeDescription) {
5843                     return lazyTypeDescription.new LazyRecordComponentDescription(name,
5844                             descriptor,
5845                             genericSignature,
5846                             signatureResolution,
5847                             typeAnnotationTokens,
5848                             annotationTokens);
5849                 }
5850             }
5851
5852             /**
5853              * A lazy description of an annotation that looks up types from a type pool when required.
5854              */

5855             private static class LazyAnnotationDescription extends AnnotationDescription.AbstractBase {
5856
5857                 /**
5858                  * The type pool for looking up type references.
5859                  */

5860                 protected final TypePool typePool;
5861
5862                 /**
5863                  * The type of this annotation.
5864                  */

5865                 private final TypeDescription annotationType;
5866
5867                 /**
5868                  * A map of annotation values by their property name.
5869                  */

5870                 protected final Map<String, AnnotationValue<?, ?>> values;
5871
5872                 /**
5873                  * Creates a new lazy annotation description.
5874                  *
5875                  * @param typePool       The type pool to be used for looking up linked types.
5876                  * @param annotationType The annotation's type.
5877                  * @param values         A map of annotation value names to their value representations.
5878                  */

5879                 private LazyAnnotationDescription(TypePool typePool, TypeDescription annotationType, Map<String, AnnotationValue<?, ?>> values) {
5880                     this.typePool = typePool;
5881                     this.annotationType = annotationType;
5882                     this.values = values;
5883                 }
5884
5885                 /**
5886                  * Represents a list of annotation tokens in form of a list of lazy type annotations. Any annotation with
5887                  * a type that cannot be loaded from the type pool is ignored and not included in the list. If the provided
5888                  * {@code tokens} are {@code null}, an empty list is returned.
5889                  *
5890                  * @param typePool The type pool to be used for looking up linked types.
5891                  * @param tokens   The tokens to represent in the list.
5892                  * @return A list of the loadable annotations.
5893                  */

5894                 protected static AnnotationList asListOfNullable(TypePool typePool, List<? extends AnnotationToken> tokens) {
5895                     return tokens == null
5896                             ? new AnnotationList.Empty()
5897                             : asList(typePool, tokens);
5898                 }
5899
5900                 /**
5901                  * Represents a list of annotation tokens in form of a list of lazy type annotations. Any annotation with
5902                  * a type that cannot be loaded from the type pool is ignored and not included in the list.
5903                  *
5904                  * @param typePool The type pool to be used for looking up linked types.
5905                  * @param tokens   The tokens to represent in the list.
5906                  * @return A list of the loadable annotations.
5907                  */

5908                 protected static AnnotationList asList(TypePool typePool, List<? extends AnnotationToken> tokens) {
5909                     List<AnnotationDescription> annotationDescriptions = new ArrayList<AnnotationDescription>(tokens.size());
5910                     for (AnnotationToken token : tokens) {
5911                         AnnotationToken.Resolution resolution = token.toAnnotationDescription(typePool);
5912                         if (resolution.isResolved()) {
5913                             annotationDescriptions.add(resolution.resolve());
5914                         }
5915                     }
5916                     return new AnnotationList.Explicit(annotationDescriptions);
5917                 }
5918
5919                 /**
5920                  * {@inheritDoc}
5921                  */

5922                 public AnnotationValue<?, ?> getValue(MethodDescription.InDefinedShape property) {
5923                     if (!property.getDeclaringType().asErasure().equals(annotationType)) {
5924                         throw new IllegalArgumentException(property + " is not declared by " + getAnnotationType());
5925                     }
5926                     AnnotationValue<?, ?> annotationValue = values.get(property.getName());
5927                     if (annotationValue != null) {
5928                         return annotationValue.filter(property);
5929                     } else {
5930                         annotationValue = getAnnotationType().getDeclaredMethods().filter(is(property)).getOnly().getDefaultValue();
5931                     }
5932                     return annotationValue == null
5933                             ? new AnnotationValue.ForMissingValue<Void, Void>(annotationType, property.getName())
5934                             : annotationValue;
5935                 }
5936
5937                 /**
5938                  * {@inheritDoc}
5939                  */

5940                 public TypeDescription getAnnotationType() {
5941                     return annotationType;
5942                 }
5943
5944                 /**
5945                  * {@inheritDoc}
5946                  */

5947                 public <T extends Annotation> Loadable<T> prepare(Class<T> annotationType) {
5948                     if (!this.annotationType.represents(annotationType)) {
5949                         throw new IllegalArgumentException(annotationType + " does not represent " + this.annotationType);
5950                     }
5951                     return new Loadable<T>(typePool, annotationType, values);
5952                 }
5953
5954                 /**
5955                  * A loadable version of a lazy annotation description.
5956                  *
5957                  * @param <S> The annotation type.
5958                  */

5959                 private static class Loadable<S extends Annotation> extends LazyAnnotationDescription implements AnnotationDescription.Loadable<S> {
5960
5961                     /**
5962                      * The loaded annotation type.
5963                      */

5964                     private final Class<S> annotationType;
5965
5966                     /**
5967                      * Creates a new loadable version of a lazy annotation.
5968                      *
5969                      * @param typePool       The type pool to be used for looking up linked types.
5970                      * @param annotationType The annotation's loaded type.
5971                      * @param values         A map of annotation value names to their value representations.
5972                      */

5973                     private Loadable(TypePool typePool, Class<S> annotationType, Map<String, AnnotationValue<?, ?>> values) {
5974                         super(typePool, ForLoadedType.of(annotationType), values);
5975                         this.annotationType = annotationType;
5976                     }
5977
5978                     /**
5979                      * {@inheritDoc}
5980                      */

5981                     public S load() {
5982                         return AnnotationInvocationHandler.of(annotationType.getClassLoader(), annotationType, values);
5983                     }
5984                 }
5985             }
5986
5987             /**
5988              * A proxy for a lazy annotation value.
5989              *
5990              * @param <U> The represented unloaded type.
5991              * @param <V> The represented loaded type.
5992              */

5993             private abstract static class LazyAnnotationValue<U, V> extends AnnotationValue.AbstractBase<U, V> {
5994
5995                 /**
5996                  * Resolves the actual annotation value.
5997                  *
5998                  * @return The actual annotation value.
5999                  */

6000                 protected abstract AnnotationValue<U, V> doResolve();
6001
6002                 /**
6003                  * {@inheritDoc}
6004                  */

6005                 public State getState() {
6006                     return doResolve().getState();
6007                 }
6008
6009                 /**
6010                  * {@inheritDoc}
6011                  */

6012                 public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
6013                     return doResolve().filter(property, typeDefinition);
6014                 }
6015
6016                 /**
6017                  * {@inheritDoc}
6018                  */

6019                 public U resolve() {
6020                     return doResolve().resolve();
6021                 }
6022
6023                 /**
6024                  * {@inheritDoc}
6025                  */

6026                 public Loaded<V> load(ClassLoader classLoader) {
6027                     return doResolve().load(classLoader);
6028                 }
6029
6030                 @Override
6031                 @CachedReturnPlugin.Enhance
6032                 public int hashCode() {
6033                     return doResolve().hashCode();
6034                 }
6035
6036                 @Override
6037                 public boolean equals(Object other) {
6038                     return doResolve().equals(other);
6039                 }
6040
6041                 @Override
6042                 public String toString() {
6043                     return doResolve().toString();
6044                 }
6045
6046                 /**
6047                  * A lazy annotation value description for a type value.
6048                  */

6049                 private static class ForTypeValue extends LazyAnnotationValue<TypeDescription, Class<?>> {
6050
6051                     /**
6052                      * The type pool to query for the type.
6053                      */

6054                     private final TypePool typePool;
6055
6056                     /**
6057                      * The type's binary name.
6058                      */

6059                     private final String typeName;
6060
6061                     /**
6062                      * Creates a new lazy description of an annotation type constant.
6063                      *
6064                      * @param typePool The type pool to query for the type.
6065                      * @param typeName The type's binary name.
6066                      */

6067                     private ForTypeValue(TypePool typePool, String typeName) {
6068                         this.typePool = typePool;
6069                         this.typeName = typeName;
6070                     }
6071
6072                     @Override
6073                     @CachedReturnPlugin.Enhance
6074                     @SuppressWarnings("unchecked")
6075                     protected AnnotationValue<TypeDescription, Class<?>> doResolve() {
6076                         Resolution resolution = typePool.describe(typeName);
6077                         return resolution.isResolved()
6078                                 ? new AnnotationValue.ForTypeDescription(resolution.resolve())
6079                                 : new AnnotationValue.ForMissingType<TypeDescription, Class<?>>(typeName);
6080                     }
6081                 }
6082
6083                 /**
6084                  * A lazy annotation value description for an annotation value.
6085                  */

6086                 private static class ForAnnotationValue extends LazyAnnotationValue<AnnotationDescription, Annotation> {
6087
6088                     /**
6089                      * The type pool to use for resolving the annotation type.
6090                      */

6091                     private final TypePool typePool;
6092
6093                     /**
6094                      * The annotation token.
6095                      */

6096                     private final AnnotationToken annotationToken;
6097
6098                     /**
6099                      * Creates a new lazy annotation value.
6100                      *
6101                      * @param typePool        The type pool to use for resolving the annotation type.
6102                      * @param annotationToken The annotation token.
6103                      */

6104                     private ForAnnotationValue(TypePool typePool, AnnotationToken annotationToken) {
6105                         this.typePool = typePool;
6106                         this.annotationToken = annotationToken;
6107                     }
6108
6109                     @Override
6110                     @CachedReturnPlugin.Enhance
6111                     protected AnnotationValue<AnnotationDescription, Annotation> doResolve() {
6112                         AnnotationToken.Resolution resolution = annotationToken.toAnnotationDescription(typePool);
6113                         if (!resolution.isResolved()) {
6114                             return new AnnotationValue.ForMissingType<AnnotationDescription, Annotation>(annotationToken.getBinaryName());
6115                         } else if (!resolution.resolve().getAnnotationType().isAnnotation()) {
6116                             return new ForIncompatibleType<AnnotationDescription, Annotation>(resolution.resolve().getAnnotationType());
6117                         } else {
6118                             return new AnnotationValue.ForAnnotationDescription<Annotation>(resolution.resolve());
6119                         }
6120                     }
6121                 }
6122
6123                 /**
6124                  * A lazy annotation value description for an enumeration value.
6125                  */

6126                 private static class ForEnumerationValue extends LazyAnnotationValue<EnumerationDescription, Enum<?>> {
6127
6128                     /**
6129                      * The type pool to use for looking up types.
6130                      */

6131                     private final TypePool typePool;
6132
6133                     /**
6134                      * The binary name of the enumeration type.
6135                      */

6136                     private final String typeName;
6137
6138                     /**
6139                      * The name of the enumeration.
6140                      */

6141                     private final String value;
6142
6143                     /**
6144                      * Creates a lazy annotation value description for an enumeration.
6145                      *
6146                      * @param typePool The type pool to use for looking up types.
6147                      * @param typeName The binary name of the enumeration type.
6148                      * @param value    The name of the enumeration.
6149                      */

6150                     private ForEnumerationValue(TypePool typePool, String typeName, String value) {
6151                         this.typePool = typePool;
6152                         this.typeName = typeName;
6153                         this.value = value;
6154                     }
6155
6156                     @Override
6157                     @CachedReturnPlugin.Enhance
6158                     @SuppressWarnings("unchecked")
6159                     protected AnnotationValue<EnumerationDescription, Enum<?>> doResolve() {
6160                         Resolution resolution = typePool.describe(typeName);
6161                         if (!resolution.isResolved()) {
6162                             return new AnnotationValue.ForMissingType<EnumerationDescription, Enum<?>>(typeName);
6163                         } else if (!resolution.resolve().isEnum()) {
6164                             return new ForIncompatibleType<EnumerationDescription, Enum<?>>(resolution.resolve());
6165                         } else if (resolution.resolve().getDeclaredFields().filter(named(value)).isEmpty()) {
6166                             return new AnnotationValue.ForEnumerationDescription.WithUnknownConstant(resolution.resolve(), value);
6167                         } else {
6168                             return new AnnotationValue.ForEnumerationDescription(new EnumerationDescription.Latent(resolution.resolve(), value));
6169                         }
6170                     }
6171                 }
6172
6173                 /**
6174                  * A lazy projection of an annotation value that is an array of non-primitive values.
6175                  */

6176                 private static class ForNonPrimitiveArray extends LazyAnnotationValue<Object[], Object[]> {
6177
6178                     /**
6179                      * The type pool to use for looking up types.
6180                      */

6181                     private final TypePool typePool;
6182
6183                     /**
6184                      * A reference to the component type.
6185                      */

6186                     private final ComponentTypeReference componentTypeReference;
6187
6188                     /**
6189                      * A list of all values of this array value in their order.
6190                      */

6191                     private final List<AnnotationValue<?, ?>> values;
6192
6193                     /**
6194                      * Creates a lazy projection for a non-primitive array.
6195                      *
6196                      * @param typePool               The type pool to use for looking up types.
6197                      * @param componentTypeReference A reference to the component type.
6198                      * @param values                 A list of all values of this array value in their order.
6199                      */

6200                     private ForNonPrimitiveArray(TypePool typePool, ComponentTypeReference componentTypeReference, List<AnnotationValue<?, ?>> values) {
6201                         this.typePool = typePool;
6202                         this.componentTypeReference = componentTypeReference;
6203                         this.values = values;
6204                     }
6205
6206                     @Override
6207                     protected AnnotationValue<Object[], Object[]> doResolve() {
6208                         String typeName = componentTypeReference.lookup();
6209                         Resolution resolution = typePool.describe(typeName);
6210                         if (!resolution.isResolved()) {
6211                             return new ForMissingType<Object[], Object[]>(typeName);
6212                         } else if (resolution.resolve().isEnum()) {
6213                             return new AnnotationValue.ForDescriptionArray<Object, Object>(EnumerationDescription.class, resolution.resolve(), values);
6214                         } else if (resolution.resolve().isAnnotation()) {
6215                             return new AnnotationValue.ForDescriptionArray<Object, Object>(AnnotationDescription.class, resolution.resolve(), values);
6216                         } else if (resolution.resolve().represents(Class.class)) {
6217                             return new AnnotationValue.ForDescriptionArray<Object, Object>(TypeDescription.class, resolution.resolve(), values);
6218                         } else if (resolution.resolve().represents(String.class)) {
6219                             return new AnnotationValue.ForDescriptionArray<Object, Object>(String.class, resolution.resolve(), values);
6220                         } else {
6221                             return new ForIncompatibleType<Object[], Object[]>(resolution.resolve());
6222                         }
6223                     }
6224                 }
6225             }
6226
6227             /**
6228              * An implementation of a {@link PackageDescription} that only
6229              * loads its annotations on requirement.
6230              */

6231             private static class LazyPackageDescription extends PackageDescription.AbstractBase {
6232
6233                 /**
6234                  * The type pool to use for look-ups.
6235                  */

6236                 private final TypePool typePool;
6237
6238                 /**
6239                  * The name of the package.
6240                  */

6241                 private final String name;
6242
6243                 /**
6244                  * Creates a new lazy package description.
6245                  *
6246                  * @param typePool The type pool to use for look-ups.
6247                  * @param name     The name of the package.
6248                  */

6249                 private LazyPackageDescription(TypePool typePool, String name) {
6250                     this.typePool = typePool;
6251                     this.name = name;
6252                 }
6253
6254                 /**
6255                  * {@inheritDoc}
6256                  */

6257                 public AnnotationList getDeclaredAnnotations() {
6258                     Resolution resolution = typePool.describe(name + "." + PackageDescription.PACKAGE_CLASS_NAME);
6259                     return resolution.isResolved()
6260                             ? resolution.resolve().getDeclaredAnnotations()
6261                             : new AnnotationList.Empty();
6262                 }
6263
6264                 /**
6265                  * {@inheritDoc}
6266                  */

6267                 public String getName() {
6268                     return name;
6269                 }
6270             }
6271
6272             /**
6273              * A list that is constructing {@link LazyTypeDescription}s.
6274              */

6275             protected static class LazyTypeList extends TypeList.AbstractBase {
6276
6277                 /**
6278                  * The type pool to use for locating types.
6279                  */

6280                 private final TypePool typePool;
6281
6282                 /**
6283                  * A list of type descriptors that this list represents.
6284                  */

6285                 private final List<String> descriptors;
6286
6287                 /**
6288                  * Creates a list of lazy type descriptions.
6289                  *
6290                  * @param typePool    The type pool to use for locating types.
6291                  * @param descriptors A list of type descriptors that this list represents.
6292                  */

6293                 protected LazyTypeList(TypePool typePool, List<String> descriptors) {
6294                     this.typePool = typePool;
6295                     this.descriptors = descriptors;
6296                 }
6297
6298                 /**
6299                  * {@inheritDoc}
6300                  */

6301                 public TypeDescription get(int index) {
6302                     return TokenizedGenericType.toErasure(typePool, descriptors.get(index));
6303                 }
6304
6305                 /**
6306                  * {@inheritDoc}
6307                  */

6308                 public int size() {
6309                     return descriptors.size();
6310                 }
6311
6312                 /**
6313                  * {@inheritDoc}
6314                  */

6315                 public String[] toInternalNames() {
6316                     String[] internalName = new String[descriptors.size()];
6317                     int index = 0;
6318                     for (String descriptor : descriptors) {
6319                         internalName[index++] = Type.getType(descriptor).getInternalName();
6320                     }
6321                     return internalName.length == 0
6322                             ? NO_INTERFACES
6323                             : internalName;
6324                 }
6325
6326                 /**
6327                  * {@inheritDoc}
6328                  */

6329                 public int getStackSize() {
6330                     int stackSize = 0;
6331                     for (String descriptor : descriptors) {
6332                         stackSize += Type.getType(descriptor).getSize();
6333                     }
6334                     return stackSize;
6335                 }
6336             }
6337
6338             /**
6339              * A lazy list that represents all nest members of the represented type.
6340              */

6341             protected static class LazyNestMemberList extends TypeList.AbstractBase {
6342
6343                 /**
6344                  * The type for which the nest members are represented.
6345                  */

6346                 private final TypeDescription typeDescription;
6347
6348                 /**
6349                  * The type pool to use for looking up types.
6350                  */

6351                 private final TypePool typePool;
6352
6353                 /**
6354                  * The binary names of all nest members of this nest mate group excluding the represented type.
6355                  */

6356                 private final List<String> nestMembers;
6357
6358                 /**
6359                  * Creates a new lazy type list of all nest members of this group.
6360                  *
6361                  * @param typeDescription The type for which the nest members are represented.
6362                  * @param typePool        The type pool to use for looking up types.
6363                  * @param nestMembers     The binary names of all nest members of this nest mate group excluding the represented type.
6364                  */

6365                 protected LazyNestMemberList(TypeDescription typeDescription, TypePool typePool, List<String> nestMembers) {
6366                     this.typeDescription = typeDescription;
6367                     this.typePool = typePool;
6368                     this.nestMembers = nestMembers;
6369                 }
6370
6371                 /**
6372                  * {@inheritDoc}
6373                  */

6374                 public TypeDescription get(int index) {
6375                     return index == 0
6376                             ? typeDescription
6377                             : typePool.describe(nestMembers.get(index - 1)).resolve();
6378                 }
6379
6380                 /**
6381                  * {@inheritDoc}
6382                  */

6383                 public int size() {
6384                     return nestMembers.size() + 1;
6385                 }
6386
6387                 /**
6388                  * {@inheritDoc}
6389                  */

6390                 public String[] toInternalNames() {
6391                     String[] internalName = new String[nestMembers.size() + 1];
6392                     internalName[0] = typeDescription.getInternalName();
6393                     int index = 1;
6394                     for (String name : nestMembers) {
6395                         internalName[index++] = name.replace('.', '/');
6396                     }
6397                     return internalName;
6398                 }
6399
6400                 /**
6401                  * {@inheritDoc}
6402                  */

6403                 public int getStackSize() {
6404                     return nestMembers.size() + 1;
6405                 }
6406             }
6407
6408             /**
6409              * A representation of a generic type that is described by a {@link GenericTypeToken}.
6410              */

6411             protected static class TokenizedGenericType extends Generic.LazyProjection.WithEagerNavigation {
6412
6413                 /**
6414                  * The type pool to use for locating referenced types.
6415                  */

6416                 private final TypePool typePool;
6417
6418                 /**
6419                  * The token that describes the represented generic type.
6420                  */

6421                 private final GenericTypeToken genericTypeToken;
6422
6423                 /**
6424                  * A descriptor of the generic type's raw type.
6425                  */

6426                 private final String rawTypeDescriptor;
6427
6428                 /**
6429                  * The tokenized type's type annotation tokens.
6430                  */

6431                 private final Map<String, List<AnnotationToken>> annotationTokens;
6432
6433                 /**
6434                  * The closest type variable source of this generic type's declaration context.
6435                  */

6436                 private final TypeVariableSource typeVariableSource;
6437
6438                 /**
6439                  * Creates a new tokenized generic type.
6440                  *
6441                  * @param typePool           The type pool to use for locating referenced types.
6442                  * @param genericTypeToken   The token that describes the represented generic type.
6443                  * @param rawTypeDescriptor  A descriptor of the generic type's erasure.
6444                  * @param annotationTokens   The tokenized type's type annotation tokens.
6445                  * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6446                  */

6447                 protected TokenizedGenericType(TypePool typePool,
6448                                                GenericTypeToken genericTypeToken,
6449                                                String rawTypeDescriptor,
6450                                                Map<String, List<AnnotationToken>> annotationTokens,
6451                                                TypeVariableSource typeVariableSource) {
6452                     this.typePool = typePool;
6453                     this.genericTypeToken = genericTypeToken;
6454                     this.rawTypeDescriptor = rawTypeDescriptor;
6455                     this.annotationTokens = annotationTokens;
6456                     this.typeVariableSource = typeVariableSource;
6457                 }
6458
6459                 /**
6460                  * Creates a new generic type description for a tokenized generic type.
6461                  *
6462                  * @param typePool           The type pool to use for locating referenced types.
6463                  * @param genericTypeToken   The token that describes the represented generic type.
6464                  * @param rawTypeDescriptor  A descriptor of the generic type's erasure.
6465                  * @param annotationTokens   The tokenized type's type annotation tokens or {@code nullif no such annotations are defined.
6466                  * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6467                  * @return A suitable generic type.
6468                  */

6469                 protected static Generic of(TypePool typePool,
6470                                             GenericTypeToken genericTypeToken,
6471                                             String rawTypeDescriptor,
6472                                             Map<String, List<AnnotationToken>> annotationTokens,
6473                                             TypeVariableSource typeVariableSource) {
6474                     return new TokenizedGenericType(typePool,
6475                             genericTypeToken,
6476                             rawTypeDescriptor,
6477                             annotationTokens == null
6478                                     ? Collections.<String, List<AnnotationToken>>emptyMap()
6479                                     : annotationTokens,
6480                             typeVariableSource);
6481                 }
6482
6483                 /**
6484                  * Creates a type description from a descriptor by looking up the corresponding type.
6485                  *
6486                  * @param typePool   The type pool to use for locating a type.
6487                  * @param descriptor The descriptor to interpret.
6488                  * @return A description of the type represented by the descriptor.
6489                  */

6490                 protected static TypeDescription toErasure(TypePool typePool, String descriptor) {
6491                     Type type = Type.getType(descriptor);
6492                     return typePool.describe(type.getSort() == Type.ARRAY
6493                             ? type.getInternalName().replace('/', '.')
6494                             : type.getClassName()).resolve();
6495                 }
6496
6497                 @Override
6498                 @CachedReturnPlugin.Enhance("resolved")
6499                 protected Generic resolve() {
6500                     return genericTypeToken.toGenericType(typePool, typeVariableSource, GenericTypeToken.EMPTY_TYPE_PATH, annotationTokens);
6501                 }
6502
6503                 /**
6504                  * {@inheritDoc}
6505                  */

6506                 @CachedReturnPlugin.Enhance("erasure")
6507                 public TypeDescription asErasure() {
6508                     return toErasure(typePool, rawTypeDescriptor);
6509                 }
6510
6511                 /**
6512                  * {@inheritDoc}
6513                  */

6514                 public AnnotationList getDeclaredAnnotations() {
6515                     return resolve().getDeclaredAnnotations();
6516                 }
6517
6518                 /**
6519                  * A tokenized list of generic types.
6520                  */

6521                 protected static class TokenList extends TypeList.Generic.AbstractBase {
6522
6523                     /**
6524                      * The type pool to use for locating types.
6525                      */

6526                     private final TypePool typePool;
6527
6528                     /**
6529                      * Type tokens that describe the represented generic types.
6530                      */

6531                     private final List<GenericTypeToken> genericTypeTokens;
6532
6533                     /**
6534                      * A list of the generic types' erasures.
6535                      */

6536                     private final List<String> rawTypeDescriptors;
6537
6538                     /**
6539                      * The closest type variable source of this generic type's declaration context.
6540                      */

6541                     private final TypeVariableSource typeVariableSource;
6542
6543                     /**
6544                      * A mapping of each type's type annotation tokens by its index.
6545                      */

6546                     private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
6547
6548                     /**
6549                      * Creates a list of tokenized generic types.
6550                      *
6551                      * @param typePool           The type pool to use for locating type descriptions.
6552                      * @param genericTypeTokens  A list of tokens describing the represented generic types.
6553                      * @param annotationTokens   A mapping of each type's type annotation tokens by its index.
6554                      * @param rawTypeDescriptors A list of the generic types' erasures.
6555                      * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6556                      */

6557                     private TokenList(TypePool typePool,
6558                                       List<GenericTypeToken> genericTypeTokens,
6559                                       Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
6560                                       List<String> rawTypeDescriptors,
6561                                       TypeVariableSource typeVariableSource) {
6562                         this.typePool = typePool;
6563                         this.genericTypeTokens = genericTypeTokens;
6564                         this.annotationTokens = annotationTokens;
6565                         this.rawTypeDescriptors = rawTypeDescriptors;
6566                         this.typeVariableSource = typeVariableSource;
6567                     }
6568
6569                     /**
6570                      * {@inheritDoc}
6571                      */

6572                     public Generic get(int index) {
6573                         return rawTypeDescriptors.size() == genericTypeTokens.size()
6574                                 ? TokenizedGenericType.of(typePool, genericTypeTokens.get(index), rawTypeDescriptors.get(index), annotationTokens.get(index), typeVariableSource)
6575                                 : TokenizedGenericType.toErasure(typePool, rawTypeDescriptors.get(index)).asGenericType();
6576                     }
6577
6578                     /**
6579                      * {@inheritDoc}
6580                      */

6581                     public int size() {
6582                         return rawTypeDescriptors.size();
6583                     }
6584
6585                     /**
6586                      * {@inheritDoc}
6587                      */

6588                     public TypeList asErasures() {
6589                         return new LazyTypeList(typePool, rawTypeDescriptors);
6590                     }
6591                 }
6592
6593                 /**
6594                  * A list of tokenized type variables.
6595                  */

6596                 protected static class TypeVariableList extends TypeList.Generic.AbstractBase {
6597
6598                     /**
6599                      * The type pool to use for locating types.
6600                      */

6601                     private final TypePool typePool;
6602
6603                     /**
6604                      * Type tokens that describe the represented type variables.
6605                      */

6606                     private final List<GenericTypeToken.OfFormalTypeVariable> typeVariables;
6607
6608                     /**
6609                      * The type variable source of the represented type variables.
6610                      */

6611                     private final TypeVariableSource typeVariableSource;
6612
6613                     /**
6614                      * A mapping of the type variables' type annotation tokens by their indices.
6615                      */

6616                     private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
6617
6618                     /**
6619                      * A mapping of the type variables' bound types' annotation tokens by their indices and each type variable's index..
6620                      */

6621                     private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens;
6622
6623                     /**
6624                      * Creates a list of type variables.
6625                      *
6626                      * @param typePool              The type pool to use for locating types.
6627                      * @param typeVariables         Type tokens that describe the represented generic types.
6628                      * @param typeVariableSource    The type variable source of the represented type variables.
6629                      * @param annotationTokens      A mapping of the type variables' type annotation tokens by their indices.
6630                      * @param boundAnnotationTokens A mapping of the type variables' bound types' annotation tokens by their indices
6631                      *                              and each type variable's index.
6632                      */

6633                     protected TypeVariableList(TypePool typePool,
6634                                                List<GenericTypeToken.OfFormalTypeVariable> typeVariables,
6635                                                TypeVariableSource typeVariableSource,
6636                                                Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
6637                                                Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
6638                         this.typePool = typePool;
6639                         this.typeVariables = typeVariables;
6640                         this.typeVariableSource = typeVariableSource;
6641                         this.annotationTokens = annotationTokens;
6642                         this.boundAnnotationTokens = boundAnnotationTokens;
6643                     }
6644
6645                     /**
6646                      * {@inheritDoc}
6647                      */

6648                     public Generic get(int index) {
6649                         return typeVariables.get(index).toGenericType(typePool, typeVariableSource, annotationTokens.get(index), boundAnnotationTokens.get(index));
6650                     }
6651
6652                     /**
6653                      * {@inheritDoc}
6654                      */

6655                     public int size() {
6656                         return typeVariables.size();
6657                     }
6658                 }
6659
6660                 /**
6661                  * A lazy description of a non-well-defined described generic type.
6662                  */

6663                 protected static class Malformed extends LazyProjection.WithEagerNavigation {
6664
6665                     /**
6666                      * The type pool to use for locating types.
6667                      */

6668                     private final TypePool typePool;
6669
6670                     /**
6671                      * The descriptor of the type erasure.
6672                      */

6673                     private final String rawTypeDescriptor;
6674
6675                     /**
6676                      * Creates a lazy description of a non-well-defined described generic type.
6677                      *
6678                      * @param typePool          The type pool to use for locating types.
6679                      * @param rawTypeDescriptor The descriptor of the type erasure.
6680                      */

6681                     protected Malformed(TypePool typePool, String rawTypeDescriptor) {
6682                         this.typePool = typePool;
6683                         this.rawTypeDescriptor = rawTypeDescriptor;
6684                     }
6685
6686                     @Override
6687                     protected Generic resolve() {
6688                         throw new GenericSignatureFormatError();
6689                     }
6690
6691                     /**
6692                      * {@inheritDoc}
6693                      */

6694                     public TypeDescription asErasure() {
6695                         return toErasure(typePool, rawTypeDescriptor);
6696                     }
6697
6698                     /**
6699                      * {@inheritDoc}
6700                      */

6701                     public AnnotationList getDeclaredAnnotations() {
6702                         throw new GenericSignatureFormatError();
6703                     }
6704
6705                     /**
6706                      * A tokenized list of non-well-defined generic types.
6707                      */

6708                     protected static class TokenList extends TypeList.Generic.AbstractBase {
6709
6710                         /**
6711                          * The type pool to use for locating types.
6712                          */

6713                         private final TypePool typePool;
6714
6715                         /**
6716                          * A list of descriptors of the list's types' erasures.
6717                          */

6718                         private final List<String> rawTypeDescriptors;
6719
6720                         /**
6721                          * Creates a new tokenized list of generic types.
6722                          *
6723                          * @param typePool           The type pool to use for locating types.
6724                          * @param rawTypeDescriptors A list of descriptors of the list's types' erasures.
6725                          */

6726                         protected TokenList(TypePool typePool, List<String> rawTypeDescriptors) {
6727                             this.typePool = typePool;
6728                             this.rawTypeDescriptors = rawTypeDescriptors;
6729                         }
6730
6731                         /**
6732                          * {@inheritDoc}
6733                          */

6734                         public Generic get(int index) {
6735                             return new Malformed(typePool, rawTypeDescriptors.get(index));
6736                         }
6737
6738                         /**
6739                          * {@inheritDoc}
6740                          */

6741                         public int size() {
6742                             return rawTypeDescriptors.size();
6743                         }
6744
6745                         /**
6746                          * {@inheritDoc}
6747                          */

6748                         public TypeList asErasures() {
6749                             return new LazyTypeList(typePool, rawTypeDescriptors);
6750                         }
6751                     }
6752
6753                 }
6754             }
6755
6756             /**
6757              * A lazy field description that only resolved type references when required.
6758              */

6759             private class LazyFieldDescription extends FieldDescription.InDefinedShape.AbstractBase {
6760
6761                 /**
6762                  * The name of the field.
6763                  */

6764                 private final String name;
6765
6766                 /**
6767                  * The modifiers of the field.
6768                  */

6769                 private final int modifiers;
6770
6771                 /**
6772                  * The descriptor of this field's type.
6773                  */

6774                 private final String descriptor;
6775
6776                 /**
6777                  * The field's generic signature as found in the class file or {@code nullif the field is not generic.
6778                  */

6779                 private final String genericSignature;
6780
6781                 /**
6782                  * A resolution of this field's generic type.
6783                  */

6784                 private final GenericTypeToken.Resolution.ForField signatureResolution;
6785
6786                 /**
6787                  * A mapping of the field type's type annotation tokens.
6788                  */

6789                 private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
6790
6791                 /**
6792                  * A list of annotation descriptions of this field.
6793                  */

6794                 private final List<AnnotationToken> annotationTokens;
6795
6796                 /**
6797                  * Creates a new lazy field description.
6798                  *
6799                  * @param name                 The name of the field.
6800                  * @param modifiers            The modifiers of the field.
6801                  * @param descriptor           The descriptor of this field's type.
6802                  * @param genericSignature     The field's generic signature as found in the class file or {@code nullif the field is not generic.
6803                  * @param signatureResolution  A resolution of this field's generic type.
6804                  * @param typeAnnotationTokens A mapping of the field type's type annotation tokens.
6805                  * @param annotationTokens     A list of annotation descriptions of this field.
6806                  */

6807                 private LazyFieldDescription(String name,
6808                                              int modifiers,
6809                                              String descriptor,
6810                                              String genericSignature,
6811                                              GenericTypeToken.Resolution.ForField signatureResolution,
6812                                              Map<String, List<AnnotationToken>> typeAnnotationTokens,
6813                                              List<AnnotationToken> annotationTokens) {
6814                     this.modifiers = modifiers;
6815                     this.name = name;
6816                     this.descriptor = descriptor;
6817                     this.genericSignature = genericSignature;
6818                     this.signatureResolution = signatureResolution;
6819                     this.typeAnnotationTokens = typeAnnotationTokens;
6820                     this.annotationTokens = annotationTokens;
6821                 }
6822
6823                 /**
6824                  * {@inheritDoc}
6825                  */

6826                 public Generic getType() {
6827                     return signatureResolution.resolveFieldType(descriptor, typePool, typeAnnotationTokens, this);
6828                 }
6829
6830                 /**
6831                  * {@inheritDoc}
6832                  */

6833                 public AnnotationList getDeclaredAnnotations() {
6834                     return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
6835                 }
6836
6837                 /**
6838                  * {@inheritDoc}
6839                  */

6840                 public String getName() {
6841                     return name;
6842                 }
6843
6844                 /**
6845                  * {@inheritDoc}
6846                  */

6847                 public TypeDescription getDeclaringType() {
6848                     return LazyTypeDescription.this;
6849                 }
6850
6851                 /**
6852                  * {@inheritDoc}
6853                  */

6854                 public int getModifiers() {
6855                     return modifiers;
6856                 }
6857
6858                 /**
6859                  * {@inheritDoc}
6860                  */

6861                 public String getGenericSignature() {
6862                     return genericSignature;
6863                 }
6864             }
6865
6866             /**
6867              * A lazy representation of a method that resolves references to types only on demand.
6868              */

6869             private class LazyMethodDescription extends MethodDescription.InDefinedShape.AbstractBase {
6870
6871                 /**
6872                  * The internal name of this method.
6873                  */

6874                 private final String internalName;
6875
6876                 /**
6877                  * The modifiers of this method.
6878                  */

6879                 private final int modifiers;
6880
6881                 /**
6882                  * The descriptor of the return type.
6883                  */

6884                 private final String returnTypeDescriptor;
6885
6886                 /**
6887                  * The method's generic signature as found in the class file or {@code nullif the method is not generic.
6888                  */

6889                 private final String genericSignature;
6890
6891                 /**
6892                  * The generic type token of this method.
6893                  */

6894                 private final GenericTypeToken.Resolution.ForMethod signatureResolution;
6895
6896                 /**
6897                  * A list of type descriptions of this method's parameters.
6898                  */

6899                 private final List<String> parameterTypeDescriptors;
6900
6901                 /**
6902                  * A list of type descriptions of this method's exception types.
6903                  */

6904                 private final List<String> exceptionTypeDescriptors;
6905
6906                 /**
6907                  * A mapping of the type variables' type annotation tokens by their indices.
6908                  */

6909                 private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
6910
6911                 /**
6912                  * A mapping of the type variables' type bounds' type annotation tokens by their indices and each variable's index.
6913                  */

6914                 private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens;
6915
6916                 /**
6917                  * A mapping of the return type's type variable tokens.
6918                  */

6919                 private final Map<String, List<AnnotationToken>> returnTypeAnnotationTokens;
6920
6921                 /**
6922                  * A mapping of the parameter types' type annotation tokens by their indices.
6923                  */

6924                 private final Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens;
6925
6926                 /**
6927                  * A mapping of the exception types' type annotation tokens by their indices.
6928                  */

6929                 private final Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens;
6930
6931                 /**
6932                  * A mapping of the receiver type's type annotation tokens.
6933                  */

6934                 private final Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens;
6935
6936                 /**
6937                  * The annotation tokens representing the method's annotations.
6938                  */

6939                 private final List<AnnotationToken> annotationTokens;
6940
6941                 /**
6942                  * The annotation tokens representing the parameter's annotation. Every index can
6943                  * contain {@code nullif a parameter does not define any annotations.
6944                  */

6945                 private final Map<Integer, List<AnnotationToken>> parameterAnnotationTokens;
6946
6947                 /**
6948                  * An array of parameter names which may be {@code nullif no explicit name is known for a parameter.
6949                  */

6950                 private final String[] parameterNames;
6951
6952                 /**
6953                  * An array of parameter modifiers which may be {@code nullif no modifiers is known.
6954                  */

6955                 private final Integer[] parameterModifiers;
6956
6957                 /**
6958                  * The default value of this method or {@code nullif no such value exists.
6959                  */

6960                 private final AnnotationValue<?, ?> defaultValue;
6961
6962                 /**
6963                  * Creates a new lazy method description.
6964                  *
6965                  * @param internalName                      The internal name of this method.
6966                  * @param modifiers                         The modifiers of the represented method.
6967                  * @param descriptor                        The method descriptor of this method.
6968                  * @param genericSignature                  The method's generic signature as found in the class file or {@code nullif the method is not generic.
6969                  * @param signatureResolution               The generic type token of this method.
6970                  * @param exceptionTypeInternalName         The internal names of the exceptions that are declared by this
6971                  *                                          method or {@code nullif no exceptions are declared by this
6972                  *                                          method.
6973                  * @param typeVariableAnnotationTokens      A mapping of the type variables' type annotation tokens by their indices.
6974                  * @param typeVariableBoundAnnotationTokens A mapping of the type variables' type bounds' type annotation tokens by their
6975                  *                                          index and each variable's index.
6976                  * @param returnTypeAnnotationTokens        A mapping of the return type's type variable tokens.
6977                  * @param parameterTypeAnnotationTokens     A mapping of the parameter types' type annotation tokens by their indices.
6978                  * @param exceptionTypeAnnotationTokens     A mapping of the exception types' type annotation tokens by their indices.
6979                  * @param receiverTypeAnnotationTokens      A mapping of the receiver type's type annotation tokens.
6980                  * @param annotationTokens                  The annotation tokens representing the method's annotations.
6981                  * @param parameterAnnotationTokens         The annotation tokens representing the parameter's annotation. Every
6982                  *                                          index can contain {@code nullif a parameter does not define any annotations.
6983                  * @param parameterTokens                   A list of parameter tokens which might be empty or even out of sync
6984                  *                                          with the actual parameters if the debugging information found in a
6985                  *                                          class was corrupt.
6986                  * @param defaultValue                      The default value of this method or {@code nullif there is no
6987                  */

6988                 private LazyMethodDescription(String internalName,
6989                                               int modifiers,
6990                                               String descriptor,
6991                                               String genericSignature,
6992                                               GenericTypeToken.Resolution.ForMethod signatureResolution,
6993                                               String[] exceptionTypeInternalName,
6994                                               Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
6995                                               Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens,
6996                                               Map<String, List<AnnotationToken>> returnTypeAnnotationTokens,
6997                                               Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens,
6998                                               Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens,
6999                                               Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens,
7000                                               List<AnnotationToken> annotationTokens,
7001                                               Map<Integer, List<AnnotationToken>> parameterAnnotationTokens,
7002                                               List<MethodToken.ParameterToken> parameterTokens,
7003                                               AnnotationValue<?, ?> defaultValue) {
7004                     this.modifiers = modifiers;
7005                     this.internalName = internalName;
7006                     Type methodType = Type.getMethodType(descriptor);
7007                     Type returnType = methodType.getReturnType();
7008                     Type[] parameterType = methodType.getArgumentTypes();
7009                     returnTypeDescriptor = returnType.getDescriptor();
7010                     parameterTypeDescriptors = new ArrayList<String>(parameterType.length);
7011                     for (Type type : parameterType) {
7012                         parameterTypeDescriptors.add(type.getDescriptor());
7013                     }
7014                     this.genericSignature = genericSignature;
7015                     this.signatureResolution = signatureResolution;
7016                     if (exceptionTypeInternalName == null) {
7017                         exceptionTypeDescriptors = Collections.emptyList();
7018                     } else {
7019                         exceptionTypeDescriptors = new ArrayList<String>(exceptionTypeInternalName.length);
7020                         for (String anExceptionTypeInternalName : exceptionTypeInternalName) {
7021                             exceptionTypeDescriptors.add(Type.getObjectType(anExceptionTypeInternalName).getDescriptor());
7022                         }
7023                     }
7024                     this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
7025                     this.typeVariableBoundAnnotationTokens = typeVariableBoundAnnotationTokens;
7026                     this.returnTypeAnnotationTokens = returnTypeAnnotationTokens;
7027                     this.parameterTypeAnnotationTokens = parameterTypeAnnotationTokens;
7028                     this.exceptionTypeAnnotationTokens = exceptionTypeAnnotationTokens;
7029                     this.receiverTypeAnnotationTokens = receiverTypeAnnotationTokens;
7030                     this.annotationTokens = annotationTokens;
7031                     this.parameterAnnotationTokens = parameterAnnotationTokens;
7032                     parameterNames = new String[parameterType.length];
7033                     parameterModifiers = new Integer[parameterType.length];
7034                     if (parameterTokens.size() == parameterType.length) {
7035                         int index = 0;
7036                         for (MethodToken.ParameterToken parameterToken : parameterTokens) {
7037                             parameterNames[index] = parameterToken.getName();
7038                             parameterModifiers[index] = parameterToken.getModifiers();
7039                             index++;
7040                         }
7041                     }
7042                     this.defaultValue = defaultValue;
7043                 }
7044
7045                 /**
7046                  * {@inheritDoc}
7047                  */

7048                 public Generic getReturnType() {
7049                     return signatureResolution.resolveReturnType(returnTypeDescriptor, typePool, returnTypeAnnotationTokens, this);
7050                 }
7051
7052                 /**
7053                  * {@inheritDoc}
7054                  */

7055                 public TypeList.Generic getExceptionTypes() {
7056                     return signatureResolution.resolveExceptionTypes(exceptionTypeDescriptors, typePool, exceptionTypeAnnotationTokens, this);
7057                 }
7058
7059                 /**
7060                  * {@inheritDoc}
7061                  */

7062                 public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
7063                     return new LazyParameterList();
7064                 }
7065
7066                 /**
7067                  * {@inheritDoc}
7068                  */

7069                 public AnnotationList getDeclaredAnnotations() {
7070                     return LazyAnnotationDescription.asList(typePool, annotationTokens);
7071                 }
7072
7073                 /**
7074                  * {@inheritDoc}
7075                  */

7076                 public String getInternalName() {
7077                     return internalName;
7078                 }
7079
7080                 /**
7081                  * {@inheritDoc}
7082                  */

7083                 public TypeDescription getDeclaringType() {
7084                     return LazyTypeDescription.this;
7085                 }
7086
7087                 /**
7088                  * {@inheritDoc}
7089                  */

7090                 public int getModifiers() {
7091                     return modifiers;
7092                 }
7093
7094                 /**
7095                  * {@inheritDoc}
7096                  */

7097                 public TypeList.Generic getTypeVariables() {
7098                     return signatureResolution.resolveTypeVariables(typePool, this, typeVariableAnnotationTokens, typeVariableBoundAnnotationTokens);
7099                 }
7100
7101                 /**
7102                  * {@inheritDoc}
7103                  */

7104                 public AnnotationValue<?, ?> getDefaultValue() {
7105                     return defaultValue;
7106                 }
7107
7108                 /**
7109                  * {@inheritDoc}
7110                  */

7111                 public Generic getReceiverType() {
7112                     if (isStatic()) {
7113                         return Generic.UNDEFINED;
7114                     } else if (isConstructor()) {
7115                         TypeDescription declaringType = getDeclaringType(), enclosingDeclaringType = declaringType.getEnclosingType();
7116                         if (enclosingDeclaringType == null) {
7117                             return declaringType.isGenerified()
7118                                     ? new LazyParameterizedReceiverType(declaringType)
7119                                     : new LazyNonGenericReceiverType(declaringType);
7120                         } else {
7121                             return !declaringType.isStatic() && declaringType.isGenerified()
7122                                     ? new LazyParameterizedReceiverType(enclosingDeclaringType)
7123                                     : new LazyNonGenericReceiverType(enclosingDeclaringType);
7124                         }
7125                     } else {
7126                         return LazyTypeDescription.this.isGenerified()
7127                                 ? new LazyParameterizedReceiverType()
7128                                 : new LazyNonGenericReceiverType();
7129                     }
7130                 }
7131
7132                 /**
7133                  * {@inheritDoc}
7134                  */

7135                 public String getGenericSignature() {
7136                     return genericSignature;
7137                 }
7138
7139                 /**
7140                  * A lazy list of parameter descriptions for the enclosing method description.
7141                  */

7142                 private class LazyParameterList extends ParameterList.AbstractBase<ParameterDescription.InDefinedShape> {
7143
7144                     /**
7145                      * {@inheritDoc}
7146                      */

7147                     public ParameterDescription.InDefinedShape get(int index) {
7148                         return new LazyParameterDescription(index);
7149                     }
7150
7151                     /**
7152                      * {@inheritDoc}
7153                      */

7154                     public boolean hasExplicitMetaData() {
7155                         for (int i = 0; i < size(); i++) {
7156                             if (parameterNames[i] == null || parameterModifiers[i] == null) {
7157                                 return false;
7158                             }
7159                         }
7160                         return true;
7161                     }
7162
7163                     /**
7164                      * {@inheritDoc}
7165                      */

7166                     public int size() {
7167                         return parameterTypeDescriptors.size();
7168                     }
7169
7170                     /**
7171                      * {@inheritDoc}
7172                      */

7173                     public TypeList.Generic asTypeList() {
7174                         return signatureResolution.resolveParameterTypes(parameterTypeDescriptors, typePool, parameterTypeAnnotationTokens, LazyMethodDescription.this);
7175                     }
7176                 }
7177
7178                 /**
7179                  * A lazy description of a parameters of the enclosing method.
7180                  */

7181                 private class LazyParameterDescription extends ParameterDescription.InDefinedShape.AbstractBase {
7182
7183                     /**
7184                      * The index of the described parameter.
7185                      */

7186                     private final int index;
7187
7188                     /**
7189                      * Creates a new description for a given parameter of the enclosing method.
7190                      *
7191                      * @param index The index of the described parameter.
7192                      */

7193                     protected LazyParameterDescription(int index) {
7194                         this.index = index;
7195                     }
7196
7197                     /**
7198                      * {@inheritDoc}
7199                      */

7200                     public MethodDescription.InDefinedShape getDeclaringMethod() {
7201                         return LazyMethodDescription.this;
7202                     }
7203
7204                     /**
7205                      * {@inheritDoc}
7206                      */

7207                     public int getIndex() {
7208                         return index;
7209                     }
7210
7211                     /**
7212                      * {@inheritDoc}
7213                      */

7214                     public boolean isNamed() {
7215                         return parameterNames[index] != null;
7216                     }
7217
7218                     /**
7219                      * {@inheritDoc}
7220                      */

7221                     public boolean hasModifiers() {
7222                         return parameterModifiers[index] != null;
7223                     }
7224
7225                     /**
7226                      * {@inheritDoc}
7227                      */

7228                     public String getName() {
7229                         return isNamed()
7230                                 ? parameterNames[index]
7231                                 : super.getName();
7232                     }
7233
7234                     /**
7235                      * {@inheritDoc}
7236                      */

7237                     public int getModifiers() {
7238                         return hasModifiers()
7239                                 ? parameterModifiers[index]
7240                                 : super.getModifiers();
7241                     }
7242
7243                     /**
7244                      * {@inheritDoc}
7245                      */

7246                     public Generic getType() {
7247                         return signatureResolution.resolveParameterTypes(parameterTypeDescriptors, typePool, parameterTypeAnnotationTokens, LazyMethodDescription.this).get(index);
7248                     }
7249
7250                     /**
7251                      * {@inheritDoc}
7252                      */

7253                     public AnnotationList getDeclaredAnnotations() {
7254                         return LazyAnnotationDescription.asListOfNullable(typePool, parameterAnnotationTokens.get(index));
7255                     }
7256                 }
7257
7258                 /**
7259                  * A lazy description of a parameterized receiver type.
7260                  */

7261                 private class LazyParameterizedReceiverType extends Generic.OfParameterizedType {
7262
7263                     /**
7264                      * The erasure of the type to be represented as a parameterized receiver type.
7265                      */

7266                     private final TypeDescription typeDescription;
7267
7268                     /**
7269                      * Creates a new lazy parameterized receiver type of the method's declaring type.
7270                      */

7271                     protected LazyParameterizedReceiverType() {
7272                         this(LazyTypeDescription.this);
7273                     }
7274
7275                     /**
7276                      * Creates a new lazy parameterized receiver type of the supplied receiver type.
7277                      *
7278                      * @param typeDescription The erasure of the type to be represented as a parameterized receiver type.
7279                      */

7280                     protected LazyParameterizedReceiverType(TypeDescription typeDescription) {
7281                         this.typeDescription = typeDescription;
7282                     }
7283
7284                     /**
7285                      * {@inheritDoc}
7286                      */

7287                     public TypeList.Generic getTypeArguments() {
7288                         return new TypeArgumentList(typeDescription.getTypeVariables());
7289                     }
7290
7291                     /**
7292                      * {@inheritDoc}
7293                      */

7294                     public Generic getOwnerType() {
7295                         TypeDescription declaringType = typeDescription.getDeclaringType();
7296                         if (declaringType == null) {
7297                             return Generic.UNDEFINED;
7298                         } else {
7299                             return !typeDescription.isStatic() && declaringType.isGenerified()
7300                                     ? new LazyParameterizedReceiverType(declaringType)
7301                                     : new LazyNonGenericReceiverType(declaringType);
7302                         }
7303                     }
7304
7305                     /**
7306                      * {@inheritDoc}
7307                      */

7308                     public AnnotationList getDeclaredAnnotations() {
7309                         return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(getTypePath()));
7310                     }
7311
7312                     /**
7313                      * Returns the type path for this type.
7314                      *
7315                      * @return This type's type path.
7316                      */

7317                     private String getTypePath() {
7318                         StringBuilder typePath = new StringBuilder();
7319                         for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
7320                             typePath = typePath.append(GenericTypeToken.INNER_CLASS_PATH);
7321                         }
7322                         return typePath.toString();
7323                     }
7324
7325                     /**
7326                      * {@inheritDoc}
7327                      */

7328                     public TypeDescription asErasure() {
7329                         return typeDescription;
7330                     }
7331
7332                     /**
7333                      * A list of generic types representing the receiver type's type arguments.
7334                      */

7335                     protected class TypeArgumentList extends TypeList.Generic.AbstractBase {
7336
7337                         /**
7338                          * The type variables of the represented receiver type.
7339                          */

7340                         private final List<? extends Generic> typeVariables;
7341
7342                         /**
7343                          * Creates a new type argument list.
7344                          *
7345                          * @param typeVariables The type variables of the represented receiver type.
7346                          */

7347                         protected TypeArgumentList(List<? extends Generic> typeVariables) {
7348                             this.typeVariables = typeVariables;
7349                         }
7350
7351                         /**
7352                          * {@inheritDoc}
7353                          */

7354                         public Generic get(int index) {
7355                             return new AnnotatedTypeVariable(typeVariables.get(index), index);
7356                         }
7357
7358                         /**
7359                          * {@inheritDoc}
7360                          */

7361                         public int size() {
7362                             return typeVariables.size();
7363                         }
7364
7365                         /**
7366                          * Represents a type variable as a type argument with type annotations.
7367                          */

7368                         protected class AnnotatedTypeVariable extends OfTypeVariable {
7369
7370                             /**
7371                              * The type variable's description.
7372                              */

7373                             private final Generic typeVariable;
7374
7375                             /**
7376                              * The type variable's index.
7377                              */

7378                             private final int index;
7379
7380                             /**
7381                              * Creates a new description of an annotated type variable as a type argument.
7382                              *
7383                              * @param typeVariable The type variable's description.
7384                              * @param index        The type variable's index.
7385                              */

7386                             protected AnnotatedTypeVariable(Generic typeVariable, int index) {
7387                                 this.typeVariable = typeVariable;
7388                                 this.index = index;
7389                             }
7390
7391                             /**
7392                              * {@inheritDoc}
7393                              */

7394                             public TypeList.Generic getUpperBounds() {
7395                                 return typeVariable.getUpperBounds();
7396                             }
7397
7398                             /**
7399                              * {@inheritDoc}
7400                              */

7401                             public TypeVariableSource getTypeVariableSource() {
7402                                 return typeVariable.getTypeVariableSource();
7403                             }
7404
7405                             /**
7406                              * {@inheritDoc}
7407                              */

7408                             public String getSymbol() {
7409                                 return typeVariable.getSymbol();
7410                             }
7411
7412                             /**
7413                              * {@inheritDoc}
7414                              */

7415                             public AnnotationList getDeclaredAnnotations() {
7416                                 return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(getTypePath()
7417                                         + index
7418                                         + GenericTypeToken.INDEXED_TYPE_DELIMITER));
7419                             }
7420                         }
7421                     }
7422                 }
7423
7424                 /**
7425                  * A lazy description of a non-generic receiver type.
7426                  */

7427                 protected class LazyNonGenericReceiverType extends Generic.OfNonGenericType {
7428
7429                     /**
7430                      * The type description of the non-generic receiver type.
7431                      */

7432                     private final TypeDescription typeDescription;
7433
7434                     /**
7435                      * Creates a new non-generic receiver type of the method's declaring type.
7436                      */

7437                     protected LazyNonGenericReceiverType() {
7438                         this(LazyTypeDescription.this);
7439                     }
7440
7441                     /**
7442                      * Creates a new non-generic receiver type of the supplied type.
7443                      *
7444                      * @param typeDescription The type to represent as a non-generic receiver type.
7445                      */

7446                     protected LazyNonGenericReceiverType(TypeDescription typeDescription) {
7447                         this.typeDescription = typeDescription;
7448                     }
7449
7450                     /**
7451                      * {@inheritDoc}
7452                      */

7453                     public Generic getOwnerType() {
7454                         TypeDescription declaringType = typeDescription.getDeclaringType();
7455                         return declaringType == null
7456                                 ? Generic.UNDEFINED
7457                                 : new LazyNonGenericReceiverType(declaringType);
7458                     }
7459
7460                     /**
7461                      * {@inheritDoc}
7462                      */

7463                     public Generic getComponentType() {
7464                         return Generic.UNDEFINED;
7465                     }
7466
7467                     /**
7468                      * {@inheritDoc}
7469                      */

7470                     public AnnotationList getDeclaredAnnotations() {
7471                         StringBuilder typePath = new StringBuilder();
7472                         for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
7473                             typePath = typePath.append(GenericTypeToken.INNER_CLASS_PATH);
7474                         }
7475                         return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(typePath.toString()));
7476                     }
7477
7478                     /**
7479                      * {@inheritDoc}
7480                      */

7481                     public TypeDescription asErasure() {
7482                         return typeDescription;
7483                     }
7484                 }
7485             }
7486
7487             /**
7488              * A lazy description of a record component.
7489              */

7490             private class LazyRecordComponentDescription extends RecordComponentDescription.InDefinedShape.AbstractBase {
7491
7492                 /**
7493                  * The record component's name.
7494                  */

7495                 private final String name;
7496
7497                 /**
7498                  * The record component's descriptor.
7499                  */

7500                 private final String descriptor;
7501
7502                 /**
7503                  * The record component's generic signature or {@code nullif the record component is non-generic.
7504                  */

7505                 private final String genericSignature;
7506
7507                 /**
7508                  * The record component's signature resolution.
7509                  */

7510                 private final GenericTypeToken.Resolution.ForRecordComponent signatureResolution;
7511
7512                 /**
7513                  * A mapping of the record component's type annotations.
7514                  */

7515                 private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
7516
7517                 /**
7518                  * A list of the record components annotations.
7519                  */

7520                 private final List<AnnotationToken> annotationTokens;
7521
7522                 /**
7523                  * Creates a new lazy description of a record component.
7524                  *
7525                  * @param name                 The record component's name.
7526                  * @param descriptor           The record component's descriptor.
7527                  * @param genericSignature     The record component's generic signature or {@code nullif the record component is non-generic.
7528                  * @param signatureResolution  The record component's signature resolution.
7529                  * @param typeAnnotationTokens A mapping of the record component's type annotations.
7530                  * @param annotationTokens     A list of the record components annotations.
7531                  */

7532                 private LazyRecordComponentDescription(String name,
7533                                                        String descriptor,
7534                                                        String genericSignature,
7535                                                        GenericTypeToken.Resolution.ForRecordComponent signatureResolution,
7536                                                        Map<String, List<AnnotationToken>> typeAnnotationTokens,
7537                                                        List<AnnotationToken> annotationTokens) {
7538                     this.name = name;
7539                     this.descriptor = descriptor;
7540                     this.genericSignature = genericSignature;
7541                     this.signatureResolution = signatureResolution;
7542                     this.typeAnnotationTokens = typeAnnotationTokens;
7543                     this.annotationTokens = annotationTokens;
7544                 }
7545
7546                 /**
7547                  * {@inheritDoc}
7548                  */

7549                 public Generic getType() {
7550                     return signatureResolution.resolveRecordType(descriptor, typePool, typeAnnotationTokens, this);
7551                 }
7552
7553                 /**
7554                  * {@inheritDoc}
7555                  */

7556                 public TypeDescription getDeclaringType() {
7557                     return LazyTypeDescription.this;
7558                 }
7559
7560                 /**
7561                  * {@inheritDoc}
7562                  */

7563                 public String getActualName() {
7564                     return name;
7565                 }
7566
7567                 /**
7568                  * {@inheritDoc}
7569                  */

7570                 public AnnotationList getDeclaredAnnotations() {
7571                     return LazyAnnotationDescription.asList(typePool, annotationTokens);
7572                 }
7573
7574                 @Override
7575                 public String getGenericSignature() {
7576                     return genericSignature;
7577                 }
7578             }
7579         }
7580
7581         /**
7582          * A type extractor reads a class file and collects data that is relevant to create a type description.
7583          */

7584         protected class TypeExtractor extends ClassVisitor {
7585
7586             /**
7587              * A mask that cuts off pseudo flags beyond the second byte that are inserted by ASM.
7588              */

7589             private static final int REAL_MODIFIER_MASK = 0xFFFF;
7590
7591             /**
7592              * A mapping of the super types' type annotation tokens by their indices.
7593              */

7594             private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> superTypeAnnotationTokens;
7595
7596             /**
7597              * A mapping of the type variables' type annotation tokens by their indices.
7598              */

7599             private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> typeVariableAnnotationTokens;
7600
7601             /**
7602              * A mapping of the type variables' bounds' type annotation tokens by their indices and each variables index.
7603              */

7604             private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> typeVariableBoundsAnnotationTokens;
7605
7606             /**
7607              * A list of annotation tokens describing annotations that are found on the visited type.
7608              */

7609             private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
7610
7611             /**
7612              * A list of field tokens describing fields that are found on the visited type.
7613              */

7614             private final List<LazyTypeDescription.FieldToken> fieldTokens;
7615
7616             /**
7617              * A list of method tokens describing annotations that are found on the visited type.
7618              */

7619             private final List<LazyTypeDescription.MethodToken> methodTokens;
7620
7621             /**
7622              * A list of record component tokens that are found on the visited type.
7623              */

7624             private final List<LazyTypeDescription.RecordComponentToken> recordComponentTokens;
7625
7626             /**
7627              * The actual modifiers found for this type.
7628              */

7629             private int actualModifiers;
7630
7631             /**
7632              * The modifiers found for this type.
7633              */

7634             private int modifiers;
7635
7636             /**
7637              * The internal name found for this type.
7638              */

7639             private String internalName;
7640
7641             /**
7642              * The internal name of the super type found for this type or {@code nullif no such type exists.
7643              */

7644             private String superClassName;
7645
7646             /**
7647              * The generic signature of the type or {@code nullif it is not generic.
7648              */

7649             private String genericSignature;
7650
7651             /**
7652              * A list of internal names of interfaces implemented by this type or {@code nullif no interfaces
7653              * are implemented.
7654              */

7655             private String[] interfaceName;
7656
7657             /**
7658              * {@code trueif this type was found to represent an anonymous type.
7659              */

7660             private boolean anonymousType;
7661
7662             /**
7663              * The nest host that was found in the class file or {@code nullif no nest host was specified.
7664              */

7665             private String nestHost;
7666
7667             /**
7668              * A list of nest members that were found in the class file.
7669              */

7670             private final List<String> nestMembers;
7671
7672             /**
7673              * The declaration context found for this type.
7674              */

7675             private LazyTypeDescription.TypeContainment typeContainment;
7676
7677             /**
7678              * The binary name of this type's declaring type or {@code nullif no such type exists.
7679              */

7680             private String declaringTypeName;
7681
7682             /**
7683              * A list of descriptors representing the types that are declared by the parsed type.
7684              */

7685             private final List<String> declaredTypes;
7686
7687             /**
7688              * A list of internal names of permitted subclasses.
7689              */

7690             private final List<String> permittedSubclasses;
7691
7692             /**
7693              * Creates a new type extractor.
7694              */

7695             protected TypeExtractor() {
7696                 super(OpenedClassReader.ASM_API);
7697                 superTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
7698                 typeVariableAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
7699                 typeVariableBoundsAnnotationTokens = new HashMap<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>>();
7700                 annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
7701                 fieldTokens = new ArrayList<LazyTypeDescription.FieldToken>();
7702                 methodTokens = new ArrayList<LazyTypeDescription.MethodToken>();
7703                 recordComponentTokens = new ArrayList<LazyTypeDescription.RecordComponentToken>();
7704                 anonymousType = false;
7705                 typeContainment = LazyTypeDescription.TypeContainment.SelfContained.INSTANCE;
7706                 nestMembers = new ArrayList<String>();
7707                 declaredTypes = new ArrayList<String>();
7708                 permittedSubclasses = new ArrayList<String>();
7709             }
7710
7711             @Override
7712             @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "The array is not to be modified by contract")
7713             public void visit(int classFileVersion,
7714                               int modifiers,
7715                               String internalName,
7716                               String genericSignature,
7717                               String superClassName,
7718                               String[] interfaceName) {
7719                 this.modifiers = modifiers & REAL_MODIFIER_MASK;
7720                 actualModifiers = modifiers;
7721                 this.internalName = internalName;
7722                 this.genericSignature = genericSignature;
7723                 this.superClassName = superClassName;
7724                 this.interfaceName = interfaceName;
7725             }
7726
7727             @Override
7728             public void visitOuterClass(String typeName, String methodName, String methodDescriptor) {
7729                 if (methodName != null) {
7730                     typeContainment = new LazyTypeDescription.TypeContainment.WithinMethod(typeName, methodName, methodDescriptor);
7731                 } else if (typeName != null) {
7732                     typeContainment = new LazyTypeDescription.TypeContainment.WithinType(typeName, true);
7733                 }
7734             }
7735
7736             @Override
7737             public void visitInnerClass(String internalName, String outerName, String innerName, int modifiers) {
7738                 if (internalName.equals(this.internalName)) {
7739                     if (outerName != null) {
7740                         declaringTypeName = outerName;
7741                         if (typeContainment.isSelfContained()) {
7742                             typeContainment = new LazyTypeDescription.TypeContainment.WithinType(outerName, false);
7743                         }
7744                     }
7745                     if (innerName == null && !typeContainment.isSelfContained()) { // Some compilers define this property inconsistently.
7746                         anonymousType = true;
7747                     }
7748                     this.modifiers = modifiers & REAL_MODIFIER_MASK;
7749                 } else if (outerName != null && innerName != null && outerName.equals(this.internalName)) {
7750                     declaredTypes.add("L" + internalName + ";");
7751                 }
7752             }
7753
7754             @Override
7755             public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
7756                 AnnotationRegistrant annotationRegistrant;
7757                 TypeReference typeReference = new TypeReference(rawTypeReference);
7758                 switch (typeReference.getSort()) {
7759                     case TypeReference.CLASS_EXTENDS:
7760                         annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex(descriptor,
7761                                 typePath,
7762                                 typeReference.getSuperTypeIndex(),
7763                                 superTypeAnnotationTokens);
7764                         break;
7765                     case TypeReference.CLASS_TYPE_PARAMETER:
7766                         annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex(descriptor,
7767                                 typePath,
7768                                 typeReference.getTypeParameterIndex(),
7769                                 typeVariableAnnotationTokens);
7770                         break;
7771                     case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
7772                         annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex.DoubleIndexed(descriptor,
7773                                 typePath,
7774                                 typeReference.getTypeParameterBoundIndex(),
7775                                 typeReference.getTypeParameterIndex(),
7776                                 typeVariableBoundsAnnotationTokens);
7777                         break;
7778                     default:
7779                         throw new IllegalArgumentException("Unexpected type reference: " + typeReference.getSort());
7780                 }
7781                 return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
7782             }
7783
7784             @Override
7785             public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
7786                 return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
7787             }
7788
7789             @Override
7790             public FieldVisitor visitField(int modifiers, String internalName, String descriptor, String genericSignature, Object defaultValue) {
7791                 return new FieldExtractor(modifiers & REAL_MODIFIER_MASK, internalName, descriptor, genericSignature);
7792             }
7793
7794             @Override
7795             public MethodVisitor visitMethod(int modifiers, String internalName, String descriptor, String genericSignature, String[] exceptionName) {
7796                 return internalName.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)
7797                         ? IGNORE_METHOD
7798                         : new MethodExtractor(modifiers & REAL_MODIFIER_MASK, internalName, descriptor, genericSignature, exceptionName);
7799             }
7800
7801             @Override
7802             public void visitNestHost(String nestHost) {
7803                 this.nestHost = nestHost;
7804             }
7805
7806             @Override
7807             public void visitNestMember(String nestMember) {
7808                 nestMembers.add(nestMember);
7809             }
7810
7811             @Override
7812             public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) {
7813                 return new RecordComponentExtractor(name, descriptor, signature);
7814             }
7815
7816             @Override
7817             public void visitPermittedSubclass(String permittedSubclass) {
7818                 permittedSubclasses.add(permittedSubclass);
7819             }
7820
7821             /**
7822              * Creates a type description from all data that is currently collected. This method should only be invoked
7823              * after a class file was parsed fully.
7824              *
7825              * @return A type description reflecting the data that was collected by this instance.
7826              */

7827             protected TypeDescription toTypeDescription() {
7828                 return new LazyTypeDescription(Default.this,
7829                         actualModifiers,
7830                         modifiers,
7831                         internalName,
7832                         superClassName,
7833                         interfaceName,
7834                         genericSignature,
7835                         typeContainment,
7836                         declaringTypeName,
7837                         declaredTypes,
7838                         anonymousType,
7839                         nestHost,
7840                         nestMembers,
7841                         superTypeAnnotationTokens,
7842                         typeVariableAnnotationTokens,
7843                         typeVariableBoundsAnnotationTokens,
7844                         annotationTokens,
7845                         fieldTokens,
7846                         methodTokens,
7847                         recordComponentTokens,
7848                         permittedSubclasses);
7849             }
7850
7851             /**
7852              * An annotation extractor reads an annotation found in a class field an collects data that
7853              * is relevant to creating a related annotation description.
7854              */

7855             protected class AnnotationExtractor extends AnnotationVisitor {
7856
7857                 /**
7858                  * The annotation registrant to register found annotation values on.
7859                  */

7860                 private final AnnotationRegistrant annotationRegistrant;
7861
7862                 /**
7863                  * A locator for the component type of any found annotation value.
7864                  */

7865                 private final ComponentTypeLocator componentTypeLocator;
7866
7867                 /**
7868                  * Creates a new annotation extractor for a byte code element without an index.
7869                  *
7870                  * @param descriptor           The annotation descriptor.
7871                  * @param annotationTokens     The collection for storing any discovered annotation tokens.
7872                  * @param componentTypeLocator The component type locator to use.
7873                  */

7874                 protected AnnotationExtractor(String descriptor, List<LazyTypeDescription.AnnotationToken> annotationTokens, ComponentTypeLocator componentTypeLocator) {
7875                     this(new AnnotationRegistrant.ForByteCodeElement(descriptor, annotationTokens), componentTypeLocator);
7876                 }
7877
7878                 /**
7879                  * Creates a new annotation extractor for a byte code element with an index.
7880                  *
7881                  * @param descriptor           The annotation descriptor.
7882                  * @param index                The index of the element for which the annotations are collected.
7883                  * @param annotationTokens     The collection for storing any discovered annotation tokens.
7884                  * @param componentTypeLocator The component type locator to use.
7885                  */

7886                 protected AnnotationExtractor(String descriptor,
7887                                               int index,
7888                                               Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens,
7889                                               ComponentTypeLocator componentTypeLocator) {
7890                     this(new AnnotationRegistrant.ForByteCodeElement.WithIndex(descriptor, index, annotationTokens), componentTypeLocator);
7891                 }
7892
7893                 /**
7894                  * Creates a new annotation extractor.
7895                  *
7896                  * @param annotationRegistrant The annotation registrant to register found annotation values on.
7897                  * @param componentTypeLocator A locator for the component type of any found annotation value.
7898                  */

7899                 protected AnnotationExtractor(AnnotationRegistrant annotationRegistrant, ComponentTypeLocator componentTypeLocator) {
7900                     super(OpenedClassReader.ASM_API);
7901                     this.annotationRegistrant = annotationRegistrant;
7902                     this.componentTypeLocator = componentTypeLocator;
7903                 }
7904
7905                 @Override
7906                 public void visit(String name, Object value) {
7907                     if (value instanceof Type) {
7908                         Type type = (Type) value;
7909                         annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForTypeValue(Default.this, type.getSort() == Type.ARRAY
7910                                 ? type.getInternalName().replace('/', '.')
7911                                 : type.getClassName()));
7912                     } else {
7913                         annotationRegistrant.register(name, AnnotationValue.ForConstant.of(value));
7914                     }
7915                 }
7916
7917                 @Override
7918                 public void visitEnum(String name, String descriptor, String value) {
7919                     annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForEnumerationValue(Default.this,
7920                             descriptor.substring(1, descriptor.length() - 1).replace('/', '.'),
7921                             value));
7922                 }
7923
7924                 @Override
7925                 public AnnotationVisitor visitAnnotation(String name, String descriptor) {
7926                     return new AnnotationExtractor(new AnnotationLookup(descriptor, name), new ComponentTypeLocator.ForAnnotationProperty(TypePool.Default.this, descriptor));
7927                 }
7928
7929                 @Override
7930                 public AnnotationVisitor visitArray(String name) {
7931                     return new AnnotationExtractor(new ArrayLookup(name, componentTypeLocator.bind(name)), ComponentTypeLocator.Illegal.INSTANCE);
7932                 }
7933
7934                 @Override
7935                 public void visitEnd() {
7936                     annotationRegistrant.onComplete();
7937                 }
7938
7939                 /**
7940                  * An annotation registrant for registering values of an array.
7941                  */

7942                 protected class ArrayLookup implements AnnotationRegistrant {
7943
7944                     /**
7945                      * The name of the annotation property the collected array is representing.
7946                      */

7947                     private final String name;
7948
7949                     /**
7950                      * A lazy reference to resolve the component type of the collected array.
7951                      */

7952                     private final ComponentTypeReference componentTypeReference;
7953
7954                     /**
7955                      * A list of all annotation values that are found on this array.
7956                      */

7957                     private final List<AnnotationValue<?, ?>> values;
7958
7959                     /**
7960                      * Creates a new annotation registrant for an array lookup.
7961                      *
7962                      * @param name                   The name of the annotation property the collected array is representing.
7963                      * @param componentTypeReference A lazy reference to resolve the component type of the collected array.
7964                      */

7965                     protected ArrayLookup(String name, ComponentTypeReference componentTypeReference) {
7966                         this.name = name;
7967                         this.componentTypeReference = componentTypeReference;
7968                         values = new ArrayList<AnnotationValue<?, ?>>();
7969                     }
7970
7971                     /**
7972                      * {@inheritDoc}
7973                      */

7974                     public void register(String ignored, AnnotationValue<?, ?> annotationValue) {
7975                         values.add(annotationValue);
7976                     }
7977
7978                     /**
7979                      * {@inheritDoc}
7980                      */

7981                     public void onComplete() {
7982                         annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForNonPrimitiveArray(Default.this, componentTypeReference, values));
7983                     }
7984                 }
7985
7986                 /**
7987                  * An annotation registrant for registering the values on an array that is itself an annotation property.
7988                  */

7989                 protected class AnnotationLookup implements AnnotationRegistrant {
7990
7991                     /**
7992                      * The descriptor of the original annotation for which the annotation values are looked up.
7993                      */

7994                     private final String descriptor;
7995
7996                     /**
7997                      * The name of the original annotation for which the annotation values are looked up.
7998                      */

7999                     private final String name;
8000
8001                     /**
8002                      * This annotation's values mapped by their attribute name.
8003                      */

8004                     private final Map<String, AnnotationValue<?, ?>> values;
8005
8006                     /**
8007                      * Creates a new annotation registrant for a recursive annotation lookup.
8008                      *
8009                      * @param name       The name of the original annotation for which the annotation values are looked up.
8010                      * @param descriptor The descriptor of the original annotation for which the annotation values are looked up.
8011                      */

8012                     protected AnnotationLookup(String descriptor, String name) {
8013                         this.descriptor = descriptor;
8014                         this.name = name;
8015                         values = new HashMap<String, AnnotationValue<?, ?>>();
8016                     }
8017
8018                     /**
8019                      * {@inheritDoc}
8020                      */

8021                     public void register(String name, AnnotationValue<?, ?> annotationValue) {
8022                         values.put(name, annotationValue);
8023                     }
8024
8025                     /**
8026                      * {@inheritDoc}
8027                      */

8028                     public void onComplete() {
8029                         annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForAnnotationValue(Default.this,
8030                                 new LazyTypeDescription.AnnotationToken(descriptor, values)));
8031                     }
8032                 }
8033             }
8034
8035             /**
8036              * A field extractor reads a field within a class file and collects data that is relevant
8037              * to creating a related field description.
8038              */

8039             protected class FieldExtractor extends FieldVisitor {
8040
8041                 /**
8042                  * The modifiers found on the field.
8043                  */

8044                 private final int modifiers;
8045
8046                 /**
8047                  * The name of the field.
8048                  */

8049                 private final String internalName;
8050
8051                 /**
8052                  * The descriptor of the field type.
8053                  */

8054                 private final String descriptor;
8055
8056                 /**
8057                  * The generic signature of the field or {@code nullif it is not generic.
8058                  */

8059                 private final String genericSignature;
8060
8061                 /**
8062                  * A mapping of the field type's type annotations.
8063                  */

8064                 private final Map<String, List<LazyTypeDescription.AnnotationToken>> typeAnnotationTokens;
8065
8066                 /**
8067                  * A list of annotation tokens found for this field.
8068                  */

8069                 private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8070
8071                 /**
8072                  * Creates a new field extractor.
8073                  *
8074                  * @param modifiers        The modifiers found for this field.
8075                  * @param internalName     The name of the field.
8076                  * @param descriptor       The descriptor of the field type.
8077                  * @param genericSignature The generic signature of the field or {@code nullif it is not generic.
8078                  */

8079                 protected FieldExtractor(int modifiers,
8080                                          String internalName,
8081                                          String descriptor,
8082                                          String genericSignature) {
8083                     super(OpenedClassReader.ASM_API);
8084                     this.modifiers = modifiers;
8085                     this.internalName = internalName;
8086                     this.descriptor = descriptor;
8087                     this.genericSignature = genericSignature;
8088                     typeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
8089                     annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
8090                 }
8091
8092                 @Override
8093                 public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
8094                     AnnotationRegistrant annotationRegistrant;
8095                     TypeReference typeReference = new TypeReference(rawTypeReference);
8096                     switch (typeReference.getSort()) {
8097                         case TypeReference.FIELD:
8098                             annotationRegistrant = new AnnotationRegistrant.ForTypeVariable(descriptor, typePath, typeAnnotationTokens);
8099                             break;
8100                         default:
8101                             throw new IllegalStateException("Unexpected type reference on field: " + typeReference.getSort());
8102                     }
8103                     return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8104                 }
8105
8106                 @Override
8107                 public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8108                     return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8109                 }
8110
8111                 @Override
8112                 public void visitEnd() {
8113                     fieldTokens.add(new LazyTypeDescription.FieldToken(internalName,
8114                             modifiers,
8115                             descriptor,
8116                             genericSignature,
8117                             typeAnnotationTokens,
8118                             annotationTokens));
8119                 }
8120             }
8121
8122             /**
8123              * A method extractor reads a method within a class file and collects data that is relevant
8124              * to creating a related method description.
8125              */

8126             protected class MethodExtractor extends MethodVisitor implements AnnotationRegistrant {
8127
8128                 /**
8129                  * The modifiers found for this method.
8130                  */

8131                 private final int modifiers;
8132
8133                 /**
8134                  * The internal name found for this method.
8135                  */

8136                 private final String internalName;
8137
8138                 /**
8139                  * The descriptor found for this method.
8140                  */

8141                 private final String descriptor;
8142
8143                 /**
8144                  * The generic signature of the method or {@code nullif it is not generic.
8145                  */

8146                 private final String genericSignature;
8147
8148                 /**
8149                  * An array of internal names of the exceptions of the found method
8150                  * or {@code nullif there are no such exceptions.
8151                  */

8152                 private final String[] exceptionName;
8153
8154                 /**
8155                  * A mapping of the method's type variables' type annotations by their indices.
8156                  */

8157                 private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> typeVariableAnnotationTokens;
8158
8159                 /**
8160                  * A mapping of the method's type variables' bounds' type annotations by their indices and each variable's index.
8161                  */

8162                 private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> typeVariableBoundAnnotationTokens;
8163
8164                 /**
8165                  * A mapping of the method's return type's type annotations.
8166                  */

8167                 private final Map<String, List<LazyTypeDescription.AnnotationToken>> returnTypeAnnotationTokens;
8168
8169                 /**
8170                  * A mapping of the parameters' type annotations by their indices.
8171                  */

8172                 private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> parameterTypeAnnotationTokens;
8173
8174                 /**
8175                  * A mapping of the exception types' type annotations by their indices.
8176                  */

8177                 private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> exceptionTypeAnnotationTokens;
8178
8179                 /**
8180                  * A mapping of the receiver type's type annotations.
8181                  */

8182                 private final Map<String, List<LazyTypeDescription.AnnotationToken>> receiverTypeAnnotationTokens;
8183
8184                 /**
8185                  * A list of annotation tokens declared on the found method.
8186                  */

8187                 private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8188
8189                 /**
8190                  * A mapping of parameter indices to annotation tokens found for the parameters at these indices.
8191                  */

8192                 private final Map<Integer, List<LazyTypeDescription.AnnotationToken>> parameterAnnotationTokens;
8193
8194                 /**
8195                  * A list of tokens representing meta information of a parameter as it is available for method's
8196                  * that are compiled in the Java 8 version format.
8197                  */

8198                 private final List<LazyTypeDescription.MethodToken.ParameterToken> parameterTokens;
8199
8200                 /**
8201                  * A bag of parameter meta information representing debugging information which allows to extract
8202                  * a method's parameter names.
8203                  */

8204                 private final ParameterBag legacyParameterBag;
8205
8206                 /**
8207                  * The first label that is found in the method's body, if any, denoting the start of the method.
8208                  * This label can be used to identify names of local variables that describe the method's parameters.
8209                  */

8210                 private Label firstLabel;
8211
8212                 /**
8213                  * A shift index for visible parameters that indicates a deviation of the actual parameter index.
8214                  */

8215                 private int visibleParameterShift;
8216
8217                 /**
8218                  * A shift index for invisible parameters that indicates a deviation of the actual parameter index.
8219                  */

8220                 private int invisibleParameterShift;
8221
8222                 /**
8223                  * The default value of the found method or {@code nullif no such value exists.
8224                  */

8225                 private AnnotationValue<?, ?> defaultValue;
8226
8227                 /**
8228                  * Creates a method extractor.
8229                  *
8230                  * @param modifiers        The modifiers found for this method.
8231                  * @param internalName     The internal name found for this method.
8232                  * @param descriptor       The descriptor found for this method.
8233                  * @param genericSignature The generic signature of the method or {@code nullif it is not generic.
8234                  * @param exceptionName    An array of internal names of the exceptions of the found method
8235                  *                         or {@code nullif there are no such exceptions.
8236                  */

8237                 protected MethodExtractor(int modifiers,
8238                                           String internalName,
8239                                           String descriptor,
8240                                           String genericSignature,
8241                                           String[] exceptionName) {
8242                     super(OpenedClassReader.ASM_API);
8243                     this.modifiers = modifiers;
8244                     this.internalName = internalName;
8245                     this.descriptor = descriptor;
8246                     this.genericSignature = genericSignature;
8247                     this.exceptionName = exceptionName;
8248                     typeVariableAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
8249                     typeVariableBoundAnnotationTokens = new HashMap<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>>();
8250                     returnTypeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
8251                     parameterTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
8252                     exceptionTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
8253                     receiverTypeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
8254                     annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
8255                     parameterAnnotationTokens = new HashMap<Integer, List<LazyTypeDescription.AnnotationToken>>();
8256                     parameterTokens = new ArrayList<LazyTypeDescription.MethodToken.ParameterToken>();
8257                     legacyParameterBag = new ParameterBag(Type.getMethodType(descriptor).getArgumentTypes());
8258                 }
8259
8260                 @Override
8261                 public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
8262                     AnnotationRegistrant annotationRegistrant;
8263                     TypeReference typeReference = new TypeReference(rawTypeReference);
8264                     switch (typeReference.getSort()) {
8265                         case TypeReference.METHOD_TYPE_PARAMETER:
8266                             annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
8267                                     typePath,
8268                                     typeReference.getTypeParameterIndex(),
8269                                     typeVariableAnnotationTokens);
8270                             break;
8271                         case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
8272                             annotationRegistrant = new ForTypeVariable.WithIndex.DoubleIndexed(descriptor,
8273                                     typePath,
8274                                     typeReference.getTypeParameterBoundIndex(),
8275                                     typeReference.getTypeParameterIndex(),
8276                                     typeVariableBoundAnnotationTokens);
8277                             break;
8278                         case TypeReference.METHOD_RETURN:
8279                             annotationRegistrant = new ForTypeVariable(descriptor,
8280                                     typePath,
8281                                     returnTypeAnnotationTokens);
8282                             break;
8283                         case TypeReference.METHOD_FORMAL_PARAMETER:
8284                             annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
8285                                     typePath,
8286                                     typeReference.getFormalParameterIndex(),
8287                                     parameterTypeAnnotationTokens);
8288                             break;
8289                         case TypeReference.THROWS:
8290                             annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
8291                                     typePath,
8292                                     typeReference.getExceptionIndex(),
8293                                     exceptionTypeAnnotationTokens);
8294                             break;
8295                         case TypeReference.METHOD_RECEIVER:
8296                             annotationRegistrant = new ForTypeVariable(descriptor,
8297                                     typePath,
8298                                     receiverTypeAnnotationTokens);
8299                             break;
8300                         case TypeReference.FIELD: // Emitted by mistake by javac for records in Java 14.
8301                             return null;
8302                         default:
8303                             throw new IllegalStateException("Unexpected type reference on method: " + typeReference.getSort());
8304                     }
8305                     return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8306                 }
8307
8308                 @Override
8309                 public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8310                     return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8311                 }
8312
8313                 @Override
8314                 public void visitAnnotableParameterCount(int count, boolean visible) {
8315                     if (visible) {
8316                         visibleParameterShift = Type.getMethodType(descriptor).getArgumentTypes().length - count;
8317                     } else {
8318                         invisibleParameterShift = Type.getMethodType(descriptor).getArgumentTypes().length - count;
8319                     }
8320                 }
8321
8322                 @Override
8323                 public AnnotationVisitor visitParameterAnnotation(int index, String descriptor, boolean visible) {
8324                     return new AnnotationExtractor(descriptor,
8325                             index + (visible ? visibleParameterShift : invisibleParameterShift),
8326                             parameterAnnotationTokens,
8327                             new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8328                 }
8329
8330                 @Override
8331                 public void visitLabel(Label label) {
8332                     if (readerMode.isExtended() && firstLabel == null) {
8333                         firstLabel = label;
8334                     }
8335                 }
8336
8337                 @Override
8338                 public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
8339                     if (readerMode.isExtended() && start == firstLabel) {
8340                         legacyParameterBag.register(index, name);
8341                     }
8342                 }
8343
8344                 @Override
8345                 public void visitParameter(String name, int modifiers) {
8346                     parameterTokens.add(new LazyTypeDescription.MethodToken.ParameterToken(name, modifiers));
8347                 }
8348
8349                 @Override
8350                 public AnnotationVisitor visitAnnotationDefault() {
8351                     return new AnnotationExtractor(thisnew ComponentTypeLocator.ForArrayType(descriptor));
8352                 }
8353
8354                 /**
8355                  * {@inheritDoc}
8356                  */

8357                 public void register(String ignored, AnnotationValue<?, ?> annotationValue) {
8358                     defaultValue = annotationValue;
8359                 }
8360
8361                 /**
8362                  * {@inheritDoc}
8363                  */

8364                 public void onComplete() {
8365                     /* do nothing, as the register method is called at most once for default values */
8366                 }
8367
8368                 @Override
8369                 public void visitEnd() {
8370                     methodTokens.add(new LazyTypeDescription.MethodToken(internalName,
8371                             modifiers,
8372                             descriptor,
8373                             genericSignature,
8374                             exceptionName,
8375                             typeVariableAnnotationTokens,
8376                             typeVariableBoundAnnotationTokens,
8377                             returnTypeAnnotationTokens,
8378                             parameterTypeAnnotationTokens,
8379                             exceptionTypeAnnotationTokens,
8380                             receiverTypeAnnotationTokens,
8381                             annotationTokens,
8382                             parameterAnnotationTokens,
8383                             parameterTokens.isEmpty()
8384                                     ? legacyParameterBag.resolve((modifiers & Opcodes.ACC_STATIC) != 0)
8385                                     : parameterTokens,
8386                             defaultValue));
8387                 }
8388             }
8389
8390             /**
8391              * A record component extractor reads a record component's information within a class file.
8392              */

8393             protected class RecordComponentExtractor extends RecordComponentVisitor {
8394
8395                 /**
8396                  * The record component's name.
8397                  */

8398                 private final String name;
8399
8400                 /**
8401                  * The record component's descriptor.
8402                  */

8403                 private final String descriptor;
8404
8405                 /**
8406                  * The record component's generic signature.
8407                  */

8408                 private final String genericSignature;
8409
8410                 /**
8411                  * A mapping of the record component's type annotations.
8412                  */

8413                 private final Map<String, List<LazyTypeDescription.AnnotationToken>> typeAnnotationTokens;
8414
8415                 /**
8416                  * A list of the record component's annotations.
8417                  */

8418                 private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8419
8420                 /**
8421                  * Creates a new record component extractor.
8422                  *
8423                  * @param name             The record component's name.
8424                  * @param descriptor       The record component's descriptor.
8425                  * @param genericSignature The record component's generic signature.
8426                  */

8427                 protected RecordComponentExtractor(String name, String descriptor, String genericSignature) {
8428                     super(OpenedClassReader.ASM_API);
8429                     this.name = name;
8430                     this.descriptor = descriptor;
8431                     this.genericSignature = genericSignature;
8432                     typeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
8433                     annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
8434                 }
8435
8436                 @Override
8437                 public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
8438                     AnnotationRegistrant annotationRegistrant;
8439                     TypeReference typeReference = new TypeReference(rawTypeReference);
8440                     switch (typeReference.getSort()) {
8441                         case TypeReference.FIELD:
8442                             annotationRegistrant = new AnnotationRegistrant.ForTypeVariable(descriptor, typePath, typeAnnotationTokens);
8443                             break;
8444                         default:
8445                             throw new IllegalStateException("Unexpected type reference on record component: " + typeReference.getSort());
8446                     }
8447                     return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8448                 }
8449
8450                 @Override
8451                 public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8452                     return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8453                 }
8454
8455                 @Override
8456                 public void visitEnd() {
8457                     recordComponentTokens.add(new LazyTypeDescription.RecordComponentToken(name,
8458                             descriptor,
8459                             genericSignature,
8460                             typeAnnotationTokens,
8461                             annotationTokens));
8462                 }
8463             }
8464         }
8465     }
8466
8467     /**
8468      * A lazy facade of a type pool that delegates any lookups to another type pool only if another value than the type's name is looked up.
8469      */

8470     @HashCodeAndEqualsPlugin.Enhance
8471     class LazyFacade extends AbstractBase {
8472
8473         /**
8474          * The type pool to delegate to.
8475          */

8476         private final TypePool typePool;
8477
8478         /**
8479          * Creates a lazy facade for a type pool.
8480          *
8481          * @param typePool The type pool to delegate to.
8482          */

8483         public LazyFacade(TypePool typePool) {
8484             super(CacheProvider.NoOp.INSTANCE);
8485             this.typePool = typePool;
8486         }
8487
8488         @Override
8489         protected Resolution doDescribe(String name) {
8490             return new LazyResolution(typePool, name);
8491         }
8492
8493         /**
8494          * {@inheritDoc}
8495          */

8496         public void clear() {
8497             typePool.clear();
8498         }
8499
8500         /**
8501          * The lazy resolution for a lazy facade for a type pool.
8502          */

8503         @HashCodeAndEqualsPlugin.Enhance
8504         protected static class LazyResolution implements Resolution {
8505
8506             /**
8507              * The type pool to delegate to.
8508              */

8509             private final TypePool typePool;
8510
8511             /**
8512              * The name of the type that is represented by this resolution.
8513              */

8514             private final String name;
8515
8516             /**
8517              * Creates a lazy resolution for a lazy facade for a type pool.
8518              *
8519              * @param typePool The type pool to delegate to.
8520              * @param name     The name of the type that is represented by this resolution.
8521              */

8522             protected LazyResolution(TypePool typePool, String name) {
8523                 this.typePool = typePool;
8524                 this.name = name;
8525             }
8526
8527             /**
8528              * {@inheritDoc}
8529              */

8530             public boolean isResolved() {
8531                 return typePool.describe(name).isResolved();
8532             }
8533
8534             /**
8535              * {@inheritDoc}
8536              */

8537             public TypeDescription resolve() {
8538                 return new LazyTypeDescription(typePool, name);
8539             }
8540         }
8541
8542         /**
8543          * A description of a type that delegates to another type pool once a property that is not the name is resolved.
8544          */

8545         protected static class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType.WithDelegation {
8546
8547             /**
8548              * The type pool to delegate to.
8549              */

8550             private final TypePool typePool;
8551
8552             /**
8553              * The name of the type that is represented by this resolution.
8554              */

8555             private final String name;
8556
8557             /**
8558              * Creates a new lazy type resolution.
8559              *
8560              * @param typePool The type pool to delegate to.
8561              * @param name     The name of the type.
8562              */

8563             protected LazyTypeDescription(TypePool typePool, String name) {
8564                 this.typePool = typePool;
8565                 this.name = name;
8566             }
8567
8568             /**
8569              * {@inheritDoc}
8570              */

8571             public String getName() {
8572                 return name;
8573             }
8574
8575             @Override
8576             @CachedReturnPlugin.Enhance("delegate")
8577             protected TypeDescription delegate() {
8578                 return typePool.describe(name).resolve();
8579             }
8580         }
8581     }
8582
8583     /**
8584      * A type pool that attempts to load a class.
8585      */

8586     @HashCodeAndEqualsPlugin.Enhance
8587     class ClassLoading extends AbstractBase.Hierarchical {
8588
8589         /**
8590          * Type-safe representation of the bootstrap class loader which is {@code null}.
8591          */

8592         private static final ClassLoader BOOTSTRAP_CLASS_LOADER = null;
8593
8594         /**
8595          * The class loader to query.
8596          */

8597         private final ClassLoader classLoader;
8598
8599         /**
8600          * Creates a class loadings type pool.
8601          *
8602          * @param cacheProvider The cache provider to use.
8603          * @param parent        The parent type pool.
8604          * @param classLoader   The class loader to use for locating files.
8605          */

8606         public ClassLoading(CacheProvider cacheProvider, TypePool parent, ClassLoader classLoader) {
8607             super(cacheProvider, parent);
8608             this.classLoader = classLoader;
8609         }
8610
8611         /**
8612          * Returns a type pool that attempts type descriptions by loadings types from the given class loader.
8613          *
8614          * @param classLoader The class loader to use.
8615          * @return An class loading type pool.
8616          */

8617         public static TypePool of(ClassLoader classLoader) {
8618             return of(classLoader, Empty.INSTANCE);
8619         }
8620
8621         /**
8622          * Returns a type pool that attempts type descriptions by loadings types from the given class loader.
8623          *
8624          * @param classLoader The class loader to use.
8625          * @param parent      The parent type pool to use.
8626          * @return An class loading type pool.
8627          */

8628         public static TypePool of(ClassLoader classLoader, TypePool parent) {
8629             return new ClassLoading(new CacheProvider.Simple(), parent, classLoader);
8630         }
8631
8632         /**
8633          * Returns a type pool that attempts type descriptions by loadings types from the system class loader.
8634          *
8635          * @return An class loading type pool for the system class loader.
8636          */

8637         public static TypePool ofSystemLoader() {
8638             return of(ClassLoader.getSystemClassLoader());
8639         }
8640
8641         /**
8642          * Returns a type pool that attempts type descriptions by loadings types from the platform class loader.
8643          * If the current VM is Java 8 or older, the extension class loader is represented instead.
8644          *
8645          * @return An class loading type pool for the system class loader.
8646          */

8647         public static TypePool ofPlatformLoader() {
8648             return of(ClassLoader.getSystemClassLoader().getParent());
8649         }
8650
8651         /**
8652          * Returns a type pool that attempts type descriptions by loadings types from the bootstrap class loader.
8653          *
8654          * @return An class loading type pool for the bootstrap class loader.
8655          */

8656         public static TypePool ofBootLoader() {
8657             return of(BOOTSTRAP_CLASS_LOADER);
8658         }
8659
8660         @Override
8661         protected Resolution doDescribe(String name) {
8662             try {
8663                 return new Resolution.Simple(TypeDescription.ForLoadedType.of(Class.forName(name, false, classLoader)));
8664             } catch (ClassNotFoundException ignored) {
8665                 return new Resolution.Illegal(name);
8666             }
8667         }
8668     }
8669
8670     /**
8671      * A type pool that supplies explicitly known type descriptions.
8672      */

8673     @HashCodeAndEqualsPlugin.Enhance
8674     class Explicit extends AbstractBase.Hierarchical {
8675
8676         /**
8677          * A mapping from type names to type descriptions of that name.
8678          */

8679         private final Map<String, TypeDescription> types;
8680
8681         /**
8682          * Creates a new explicit type pool without a parent.
8683          *
8684          * @param types A mapping from type names to type descriptions of that name.
8685          */

8686         public Explicit(Map<String, TypeDescription> types) {
8687             this(Empty.INSTANCE, types);
8688         }
8689
8690         /**
8691          * Creates a new explicit type pool.
8692          *
8693          * @param parent The parent type pool.
8694          * @param types  A mapping from type names to type descriptions of that name.
8695          */

8696         public Explicit(TypePool parent, Map<String, TypeDescription> types) {
8697             super(CacheProvider.NoOp.INSTANCE, parent);
8698             this.types = types;
8699         }
8700
8701         @Override
8702         protected Resolution doDescribe(String name) {
8703             TypeDescription typeDescription = types.get(name);
8704             return typeDescription == null
8705                     ? new Resolution.Illegal(name)
8706                     : new Resolution.Simple(typeDescription);
8707         }
8708     }
8709 }
8710