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 true} if 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 null} if 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 true} if 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 true} if 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 true} if this token describes a type with parameters.
1741 *
1742 * @return {@code true} if 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 null} if 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 null} if 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 null} if 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 true} if this type is an anonymous type.
2419 */
2420 private final boolean anonymousType;
2421
2422 /**
2423 * The binary name of the nest host or {@code null} if 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 null} if no such super type is defined.
2480 * @param interfaceInternalName An array of this type's interfaces or {@code null} if this type does not define any interfaces.
2481 * @param genericSignature The type's generic signature as found in the class file or {@code null} if 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 null} if no such type exists.
2484 * @param declaredTypes A list of descriptors representing the types that are declared by this type.
2485 * @param anonymousType {@code true} if this type is an anonymous type.
2486 * @param nestHostInternalName The internal name of the nest host or {@code null} if 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 null} if 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 null} if 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 true} if the type is self-contained.
2812 *
2813 * @return {@code true} if the type is self-contained.
2814 */
2815 boolean isSelfContained();
2816
2817 /**
2818 * Returns {@code true} if the type is a local type unless it is an anonymous type.
2819 *
2820 * @return {@code true} if 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 true} if 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 true} if 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 true} if 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 null} if 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 true} if the represented annotation could be resolved.
5364 *
5365 * @return {@code true} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if the method is not generic.
5627 * @param exceptionName An array of internal names of the exceptions of the represented method or {@code null} if
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 null} if 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 null} if 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 null} if 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 null} if there is no such name.
5758 *
5759 * @return The name of the parameter or {@code null} if 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 null} if no modifiers are known.
5767 *
5768 * @return The modifiers of the parameter or {@code null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if no modifiers is known.
6954 */
6955 private final Integer[] parameterModifiers;
6956
6957 /**
6958 * The default value of this method or {@code null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if no such type exists.
7643 */
7644 private String superClassName;
7645
7646 /**
7647 * The generic signature of the type or {@code null} if 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 null} if no interfaces
7653 * are implemented.
7654 */
7655 private String[] interfaceName;
7656
7657 /**
7658 * {@code true} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if 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 null} if it is not generic.
8234 * @param exceptionName An array of internal names of the exceptions of the found method
8235 * or {@code null} if 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(this, new 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