• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

raphw / byte-buddy / #523

17 Aug 2023 10:13PM CUT coverage: 85.602% (-0.009%) from 85.611%
#523

push

raphw
Add method that allows the resolution of type names of annotations even if the annotations themselves are not resolvable.

15 of 15 new or added lines in 2 files covered. (100.0%)

28610 of 33422 relevant lines covered (85.6%)

0.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.45
/byte-buddy-dep/src/main/java/net/bytebuddy/pool/TypePool.java
1
/*
2
 * Copyright 2014 - Present 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.ClassFileVersion;
20
import net.bytebuddy.build.CachedReturnPlugin;
21
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
22
import net.bytebuddy.description.TypeVariableSource;
23
import net.bytebuddy.description.annotation.AnnotationDescription;
24
import net.bytebuddy.description.annotation.AnnotationList;
25
import net.bytebuddy.description.annotation.AnnotationValue;
26
import net.bytebuddy.description.enumeration.EnumerationDescription;
27
import net.bytebuddy.description.field.FieldDescription;
28
import net.bytebuddy.description.field.FieldList;
29
import net.bytebuddy.description.method.MethodDescription;
30
import net.bytebuddy.description.method.MethodList;
31
import net.bytebuddy.description.method.ParameterDescription;
32
import net.bytebuddy.description.method.ParameterList;
33
import net.bytebuddy.description.type.PackageDescription;
34
import net.bytebuddy.description.type.RecordComponentDescription;
35
import net.bytebuddy.description.type.RecordComponentList;
36
import net.bytebuddy.description.type.TypeDefinition;
37
import net.bytebuddy.description.type.TypeDescription;
38
import net.bytebuddy.description.type.TypeList;
39
import net.bytebuddy.dynamic.ClassFileLocator;
40
import net.bytebuddy.dynamic.DynamicType;
41
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
42
import net.bytebuddy.implementation.bytecode.StackSize;
43
import net.bytebuddy.matcher.ElementMatcher;
44
import net.bytebuddy.utility.JavaType;
45
import net.bytebuddy.utility.OpenedClassReader;
46
import net.bytebuddy.utility.nullability.AlwaysNull;
47
import net.bytebuddy.utility.nullability.MaybeNull;
48
import net.bytebuddy.utility.nullability.UnknownNull;
49
import org.objectweb.asm.AnnotationVisitor;
50
import org.objectweb.asm.ClassReader;
51
import org.objectweb.asm.ClassVisitor;
52
import org.objectweb.asm.FieldVisitor;
53
import org.objectweb.asm.Label;
54
import org.objectweb.asm.MethodVisitor;
55
import org.objectweb.asm.Opcodes;
56
import org.objectweb.asm.RecordComponentVisitor;
57
import org.objectweb.asm.Type;
58
import org.objectweb.asm.TypePath;
59
import org.objectweb.asm.TypeReference;
60
import org.objectweb.asm.signature.SignatureReader;
61
import org.objectweb.asm.signature.SignatureVisitor;
62

63
import javax.annotation.Nonnull;
64
import java.io.IOException;
65
import java.lang.annotation.Annotation;
66
import java.lang.ref.SoftReference;
67
import java.lang.reflect.GenericSignatureFormatError;
68
import java.util.ArrayList;
69
import java.util.Collections;
70
import java.util.HashMap;
71
import java.util.List;
72
import java.util.ListIterator;
73
import java.util.Map;
74
import java.util.concurrent.ConcurrentHashMap;
75
import java.util.concurrent.ConcurrentMap;
76
import java.util.concurrent.atomic.AtomicReference;
77

78
import static net.bytebuddy.matcher.ElementMatchers.hasDescriptor;
79
import static net.bytebuddy.matcher.ElementMatchers.hasMethodName;
80
import static net.bytebuddy.matcher.ElementMatchers.is;
81
import static net.bytebuddy.matcher.ElementMatchers.named;
82

83
/**
84
 * A type pool allows the retrieval of {@link TypeDescription} by its name.
85
 */
86
public interface TypePool {
87

88
    /**
89
     * Locates and describes the given type by its name.
90
     *
91
     * @param name The name of the type to describe. The name is to be written as when calling {@link Class#getName()}.
92
     * @return A resolution of the type to describe. If the type to be described was found, the returned
93
     * {@link net.bytebuddy.pool.TypePool.Resolution} represents this type. Otherwise, an illegal resolution is returned.
94
     */
95
    Resolution describe(String name);
96

97
    /**
98
     * Clears this type pool's cache.
99
     */
100
    void clear();
101

102
    /**
103
     * A resolution of a {@link net.bytebuddy.pool.TypePool} which was queried for a description.
104
     */
105
    interface Resolution {
106

107
        /**
108
         * Determines if this resolution represents a fully-resolved {@link TypeDescription}.
109
         *
110
         * @return {@code true} if the queried type could be resolved.
111
         */
112
        boolean isResolved();
113

114
        /**
115
         * Resolves this resolution to a {@link TypeDescription}. If this resolution is unresolved, this
116
         * method throws an exception either upon invoking this method or upon invoking at least one method
117
         * of the returned type description.
118
         *
119
         * @return The type description that is represented by this resolution.
120
         * @throws NoSuchTypeException If this resolution is unresolved.
121
         */
122
        TypeDescription resolve();
123

124
        /**
125
         * A simple resolution that represents a given {@link TypeDescription}.
126
         */
127
        @HashCodeAndEqualsPlugin.Enhance
128
        class Simple implements Resolution {
129

130
            /**
131
             * The represented type description.
132
             */
133
            private final TypeDescription typeDescription;
134

135
            /**
136
             * Creates a new successful resolution of a given type description.
137
             *
138
             * @param typeDescription The represented type description.
139
             */
140
            public Simple(TypeDescription typeDescription) {
1✔
141
                this.typeDescription = typeDescription;
1✔
142
            }
1✔
143

144
            /**
145
             * {@inheritDoc}
146
             */
147
            public boolean isResolved() {
148
                return true;
1✔
149
            }
150

151
            /**
152
             * {@inheritDoc}
153
             */
154
            public TypeDescription resolve() {
155
                return typeDescription;
1✔
156
            }
157
        }
158

159
        /**
160
         * A canonical representation of a non-successful resolution of a {@link net.bytebuddy.pool.TypePool}.
161
         */
162
        @HashCodeAndEqualsPlugin.Enhance
163
        class Illegal implements Resolution {
164

165
            /**
166
             * The name of the unresolved type.
167
             */
168
            private final String name;
169

170
            /**
171
             * Creates a new illegal resolution.
172
             *
173
             * @param name The name of the unresolved type.
174
             */
175
            public Illegal(String name) {
1✔
176
                this.name = name;
1✔
177
            }
1✔
178

179
            /**
180
             * {@inheritDoc}
181
             */
182
            public boolean isResolved() {
183
                return false;
1✔
184
            }
185

186
            /**
187
             * {@inheritDoc}
188
             */
189
            public TypeDescription resolve() {
190
                throw new NoSuchTypeException(name);
1✔
191
            }
192
        }
193

194
        /**
195
         * An exception that indicates that a {@link TypePool} could not resolve a {@link TypeDescription} for a given name.
196
         */
197
        class NoSuchTypeException extends IllegalStateException {
198

199
            /**
200
             * The serial version UID.
201
             */
202
            private static final long serialVersionUID = 1L;
203

204
            /**
205
             * The name of the type that could not be resolved.
206
             */
207
            private final String name;
208

209
            /**
210
             * Creates a new exception to indicate an unresolved type.
211
             *
212
             * @param name The name of the type that could not be resolved.
213
             */
214
            public NoSuchTypeException(String name) {
215
                super("Cannot resolve type description for " + name);
1✔
216
                this.name = name;
1✔
217
            }
1✔
218

219
            /**
220
             * Returns the name of the type that could not be resolved.
221
             *
222
             * @return The name of the type that could not be resolved.
223
             */
224
            public String getName() {
225
                return name;
1✔
226
            }
227
        }
228
    }
229

230
    /**
231
     * A cache provider for a {@link net.bytebuddy.pool.TypePool}.
232
     */
233
    interface CacheProvider {
234

235
        /**
236
         * The value that is returned on a cache-miss.
237
         */
238
        @MaybeNull
239
        Resolution UNRESOLVED = null;
1✔
240

241
        /**
242
         * Attempts to find a resolution in this cache.
243
         *
244
         * @param name The name of the type to describe.
245
         * @return A resolution of the type or {@code null} if no such resolution can be found in the cache.
246
         */
247
        @MaybeNull
248
        Resolution find(String name);
249

250
        /**
251
         * Registers a resolution in this cache. If a resolution to the given name already exists in the
252
         * cache, it should be discarded.
253
         *
254
         * @param name       The name of the type that is to be registered.
255
         * @param resolution The resolution to register.
256
         * @return The oldest version of a resolution that is currently registered in the cache which might
257
         * be the given resolution or another resolution that was previously registered.
258
         */
259
        Resolution register(String name, Resolution resolution);
260

261
        /**
262
         * Clears this cache.
263
         */
264
        void clear();
265

266
        /**
267
         * A non-operational cache that does not store any type descriptions.
268
         */
269
        enum NoOp implements CacheProvider {
1✔
270

271
            /**
272
             * The singleton instance.
273
             */
274
            INSTANCE;
1✔
275

276
            /**
277
             * {@inheritDoc}
278
             */
279
            @MaybeNull
280
            public Resolution find(String name) {
281
                return UNRESOLVED;
1✔
282
            }
283

284
            /**
285
             * {@inheritDoc}
286
             */
287
            public Resolution register(String name, Resolution resolution) {
288
                return resolution;
1✔
289
            }
290

291
            /**
292
             * {@inheritDoc}
293
             */
294
            public void clear() {
295
                /* do nothing */
296
            }
1✔
297
        }
298

299
        /**
300
         * A simple, thread-safe type cache based on a {@link java.util.concurrent.ConcurrentHashMap}.
301
         */
302
        class Simple implements CacheProvider {
303

304
            /**
305
             * A map containing all cached resolutions by their names.
306
             */
307
            private final ConcurrentMap<String, Resolution> storage;
308

309
            /**
310
             * Creates a new simple cache.
311
             */
312
            public Simple() {
313
                this(new ConcurrentHashMap<String, Resolution>());
1✔
314
            }
1✔
315

316
            /**
317
             * Creates a new simple cache.
318
             *
319
             * @param storage A map that is used for locating and storing resolutions.
320
             */
321
            public Simple(ConcurrentMap<String, Resolution> storage) {
1✔
322
                this.storage = storage;
1✔
323
            }
1✔
324

325
            /**
326
             * Returns a simple cache provider that is prepopulated with the {@link Object} type.
327
             *
328
             * @return A simple cache provider that is prepopulated with the {@link Object} type.
329
             */
330
            public static CacheProvider withObjectType() {
331
                CacheProvider cacheProvider = new Simple();
1✔
332
                cacheProvider.register(Object.class.getName(), new Resolution.Simple(TypeDescription.ForLoadedType.of(Object.class)));
1✔
333
                return cacheProvider;
1✔
334
            }
335

336
            /**
337
             * {@inheritDoc}
338
             */
339
            @MaybeNull
340
            public Resolution find(String name) {
341
                return storage.get(name);
1✔
342
            }
343

344
            /**
345
             * {@inheritDoc}
346
             */
347
            public Resolution register(String name, Resolution resolution) {
348
                Resolution cached = storage.putIfAbsent(name, resolution);
1✔
349
                return cached == null
1✔
350
                        ? resolution
351
                        : cached;
352
            }
353

354
            /**
355
             * {@inheritDoc}
356
             */
357
            public void clear() {
358
                storage.clear();
1✔
359
            }
1✔
360

361
            /**
362
             * Returns the underlying storage map of this simple cache provider.
363
             *
364
             * @return A map containing all cached resolutions by their names.
365
             */
366
            public ConcurrentMap<String, Resolution> getStorage() {
367
                return storage;
1✔
368
            }
369

370
            /**
371
             * A {@link Simple} cache provider that clears its storage if the heap is filled, by using a soft reference.
372
             */
373
            public static class UsingSoftReference implements CacheProvider {
374

375
                /**
376
                 * A reference for the actual cache provider.
377
                 */
378
                private final AtomicReference<SoftReference<Simple>> delegate;
379

380
                /**
381
                 * Creates a softly referenced {@link Simple} cache provider.
382
                 */
383
                public UsingSoftReference() {
1✔
384
                    delegate = new AtomicReference<SoftReference<Simple>>(new SoftReference<Simple>(new Simple()));
1✔
385
                }
1✔
386

387
                /**
388
                 * {@inheritDoc}
389
                 */
390
                @MaybeNull
391
                public Resolution find(String name) {
392
                    CacheProvider provider = delegate.get().get();
1✔
393
                    return provider == null
1✔
394
                            ? UNRESOLVED
395
                            : provider.find(name);
1✔
396
                }
397

398
                /**
399
                 * {@inheritDoc}
400
                 */
401
                public Resolution register(String name, Resolution resolution) {
402
                    SoftReference<Simple> reference = delegate.get();
1✔
403
                    Simple provider = reference.get();
1✔
404
                    if (provider == null) {
1✔
405
                        provider = new Simple();
×
406
                        while (!delegate.compareAndSet(reference, new SoftReference<Simple>(provider))) {
×
407
                            reference = delegate.get();
×
408
                            Simple previous = reference.get();
×
409
                            if (previous != null) {
×
410
                                provider = previous;
×
411
                                break;
×
412
                            }
413
                        }
×
414
                    }
415
                    return provider.register(name, resolution);
1✔
416
                }
417

418
                /**
419
                 * {@inheritDoc}
420
                 */
421
                public void clear() {
422
                    CacheProvider provider = delegate.get().get();
1✔
423
                    if (provider != null) {
1✔
424
                        provider.clear();
1✔
425
                    }
426
                }
1✔
427
            }
428
        }
429

430
        /**
431
         * A discriminating cache provider that delegates a type name to one of two caches.
432
         */
433
        class Discriminating implements CacheProvider {
434

435
            /**
436
             * The matcher that determines which cache to use.
437
             */
438
            private final ElementMatcher<String> matcher;
439

440
            /**
441
             * The cache provider to use for matched types.
442
             */
443
            private final CacheProvider matched;
444

445
            /**
446
             * The cache provider to use for unmatched types.
447
             */
448
            private final CacheProvider unmatched;
449

450
            /**
451
             * Creates a new discriminating cache provider.
452
             *
453
             * @param matcher   The matcher that determines which cache to use.
454
             * @param matched   The cache provider to use for matched types.
455
             * @param unmatched The cache provider to use for unmatched types.
456
             */
457
            public Discriminating(ElementMatcher<String> matcher, CacheProvider matched, CacheProvider unmatched) {
1✔
458
                this.matcher = matcher;
1✔
459
                this.matched = matched;
1✔
460
                this.unmatched = unmatched;
1✔
461
            }
1✔
462

463
            /**
464
             * {@inheritDoc}
465
             */
466
            @MaybeNull
467
            public Resolution find(String name) {
468
                return (matcher.matches(name) ? matched : unmatched).find(name);
×
469
            }
470

471
            /**
472
             * {@inheritDoc}
473
             */
474
            public Resolution register(String name, Resolution resolution) {
475
                return (matcher.matches(name) ? matched : unmatched).register(name, resolution);
1✔
476
            }
477

478
            /**
479
             * {@inheritDoc}
480
             */
481
            public void clear() {
482
                try {
483
                    unmatched.clear();
1✔
484
                } finally {
1✔
485
                    matched.clear();
1✔
486
                }
1✔
487
            }
1✔
488
        }
489
    }
490

491
    /**
492
     * An empty type pool that cannot describe any type.
493
     */
494
    enum Empty implements TypePool {
1✔
495

496
        /**
497
         * The singleton instance.
498
         */
499
        INSTANCE;
1✔
500

501
        /**
502
         * {@inheritDoc}
503
         */
504
        public Resolution describe(String name) {
505
            return new Resolution.Illegal(name);
1✔
506
        }
507

508
        /**
509
         * {@inheritDoc}
510
         */
511
        public void clear() {
512
            /* do nothing */
513
        }
1✔
514
    }
515

516
    /**
517
     * A base implementation of a {@link net.bytebuddy.pool.TypePool} that is managing a cache provider and
518
     * that handles the description of array and primitive types.
519
     */
520
    @HashCodeAndEqualsPlugin.Enhance
521
    abstract class AbstractBase implements TypePool {
522

523
        /**
524
         * A map of primitive types by their name.
525
         */
526
        protected static final Map<String, TypeDescription> PRIMITIVE_TYPES;
527

528
        /**
529
         * A map of primitive types by their descriptor.
530
         */
531
        protected static final Map<String, String> PRIMITIVE_DESCRIPTORS;
532

533
        /**
534
         * The array symbol as used by Java descriptors.
535
         */
536
        private static final String ARRAY_SYMBOL = "[";
537

538
        /*
539
         * Initializes the maps of primitive type names and descriptors.
540
         */
541
        static {
542
            Map<String, TypeDescription> primitiveTypes = new HashMap<String, TypeDescription>();
1✔
543
            Map<String, String> primitiveDescriptors = new HashMap<String, String>();
1✔
544
            for (Class<?> type : new Class<?>[]{boolean.class,
1✔
545
                    byte.class,
546
                    short.class,
547
                    char.class,
548
                    int.class,
549
                    long.class,
550
                    float.class,
551
                    double.class,
552
                    void.class}) {
553
                primitiveTypes.put(type.getName(), TypeDescription.ForLoadedType.of(type));
1✔
554
                primitiveDescriptors.put(Type.getDescriptor(type), type.getName());
1✔
555
            }
556
            PRIMITIVE_TYPES = Collections.unmodifiableMap(primitiveTypes);
1✔
557
            PRIMITIVE_DESCRIPTORS = Collections.unmodifiableMap(primitiveDescriptors);
1✔
558
        }
1✔
559

560
        /**
561
         * The cache provider of this instance.
562
         */
563
        protected final CacheProvider cacheProvider;
564

565
        /**
566
         * Creates a new instance.
567
         *
568
         * @param cacheProvider The cache provider to be used.
569
         */
570
        protected AbstractBase(CacheProvider cacheProvider) {
1✔
571
            this.cacheProvider = cacheProvider;
1✔
572
        }
1✔
573

574
        /**
575
         * {@inheritDoc}
576
         */
577
        public Resolution describe(String name) {
578
            if (name.contains("/")) {
1✔
579
                throw new IllegalArgumentException(name + " contains the illegal character '/'");
1✔
580
            }
581
            int arity = 0;
1✔
582
            while (name.startsWith(ARRAY_SYMBOL)) {
1✔
583
                arity++;
1✔
584
                name = name.substring(1);
1✔
585
            }
586
            if (arity > 0) {
1✔
587
                String primitiveName = PRIMITIVE_DESCRIPTORS.get(name);
1✔
588
                name = primitiveName == null
1✔
589
                        ? name.substring(1, name.length() - 1)
1✔
590
                        : primitiveName;
591
            }
592
            TypeDescription typeDescription = PRIMITIVE_TYPES.get(name);
1✔
593
            Resolution resolution = typeDescription == null
1✔
594
                    ? cacheProvider.find(name)
1✔
595
                    : new Resolution.Simple(typeDescription);
596
            if (resolution == null) {
1✔
597
                resolution = doCache(name, doDescribe(name));
1✔
598
            }
599
            return ArrayTypeResolution.of(resolution, arity);
1✔
600
        }
601

602
        /**
603
         * Writes the resolution to the cache. This method should be overridden if the directly
604
         * resolved instance should not be added to the cache.
605
         *
606
         * @param name       The name of the type.
607
         * @param resolution The resolution for this type.
608
         * @return The actual resolution for the type of this name that is stored in the cache.
609
         */
610
        protected Resolution doCache(String name, Resolution resolution) {
611
            return cacheProvider.register(name, resolution);
1✔
612
        }
613

614
        /**
615
         * {@inheritDoc}
616
         */
617
        public void clear() {
618
            cacheProvider.clear();
1✔
619
        }
1✔
620

621
        /**
622
         * Determines a resolution to a non-primitive, non-array type.
623
         *
624
         * @param name The name of the type to describe.
625
         * @return A resolution to the type to describe.
626
         */
627
        protected abstract Resolution doDescribe(String name);
628

629
        /**
630
         * A lazy representation of the component type of an array.
631
         */
632
        protected interface ComponentTypeReference {
633

634
            /**
635
             * Indicates that no component type is defined for the property.
636
             */
637
            @MaybeNull
638
            String NO_ARRAY = null;
1✔
639

640
            /**
641
             * Lazily resolves the binary name of the array component type of an annotation value.
642
             *
643
             * @return The binary name of the component type of the array or {@code null} if the referenced type is not an array.
644
             */
645
            @MaybeNull
646
            String resolve();
647
        }
648

649
        /**
650
         * Implements a hierarchical view of type pools, similarly to class loader hierarchies. For every lookup, the parent type pool
651
         * is asked first if it can resolve a type. Only if the parent (and potentially its parents) are unable to resolve a type,
652
         * this instance is queried for a type description.
653
         */
654
        @HashCodeAndEqualsPlugin.Enhance
655
        public abstract static class Hierarchical extends AbstractBase {
656

657
            /**
658
             * The parent type pool.
659
             */
660
            private final TypePool parent;
661

662
            /**
663
             * Creates a hierarchical type pool.
664
             *
665
             * @param cacheProvider The cache provider to be used.
666
             * @param parent        The parent type pool to be used.
667
             */
668
            protected Hierarchical(CacheProvider cacheProvider, TypePool parent) {
669
                super(cacheProvider);
1✔
670
                this.parent = parent;
1✔
671
            }
1✔
672

673
            /**
674
             * {@inheritDoc}
675
             */
676
            public Resolution describe(String name) {
677
                Resolution resolution = parent.describe(name);
1✔
678
                return resolution.isResolved()
1✔
679
                        ? resolution
680
                        : super.describe(name);
1✔
681
            }
682

683
            /**
684
             * {@inheritDoc}
685
             */
686
            public void clear() {
687
                try {
688
                    parent.clear();
1✔
689
                } finally {
1✔
690
                    super.clear();
1✔
691
                }
1✔
692
            }
1✔
693
        }
694

695
        /**
696
         * A resolution for a type that, if resolved, represents an array type.
697
         */
698
        @HashCodeAndEqualsPlugin.Enhance
699
        protected static class ArrayTypeResolution implements Resolution {
700

701
            /**
702
             * The underlying resolution that is represented by this instance.
703
             */
704
            private final Resolution resolution;
705

706
            /**
707
             * The arity of the represented array.
708
             */
709
            private final int arity;
710

711
            /**
712
             * Creates a wrapper for another resolution that, if resolved, represents an array type.
713
             *
714
             * @param resolution The underlying resolution that is represented by this instance.
715
             * @param arity      The arity of the represented array.
716
             */
717
            protected ArrayTypeResolution(Resolution resolution, int arity) {
1✔
718
                this.resolution = resolution;
1✔
719
                this.arity = arity;
1✔
720
            }
1✔
721

722
            /**
723
             * Creates a wrapper for another resolution that, if resolved, represents an array type. The wrapper
724
             * is only created if the arity is not zero. If the arity is zero, the given resolution is simply
725
             * returned instead.
726
             *
727
             * @param resolution The underlying resolution that is represented by this instance.
728
             * @param arity      The arity of the represented array.
729
             * @return A wrapper for another resolution that, if resolved, represents an array type or the
730
             * given resolution if the given arity is zero.
731
             */
732
            protected static Resolution of(Resolution resolution, int arity) {
733
                return arity == 0
1✔
734
                        ? resolution
735
                        : new ArrayTypeResolution(resolution, arity);
736
            }
737

738
            /**
739
             * {@inheritDoc}
740
             */
741
            public boolean isResolved() {
742
                return resolution.isResolved();
1✔
743
            }
744

745
            /**
746
             * {@inheritDoc}
747
             */
748
            public TypeDescription resolve() {
749
                return TypeDescription.ArrayProjection.of(resolution.resolve(), arity);
1✔
750
            }
751
        }
752
    }
753

754
    /**
755
     * <p>
756
     * A default implementation of a {@link net.bytebuddy.pool.TypePool} that models binary data in the Java byte code format
757
     * into a {@link TypeDescription}. The data lookup is delegated to a {@link net.bytebuddy.dynamic.ClassFileLocator}.
758
     * </p>
759
     * <p>
760
     * {@link Resolution}s that are produced by this type pool are either fully resolved or not resolved at all.
761
     * </p>
762
     */
763
    @HashCodeAndEqualsPlugin.Enhance
764
    class Default extends AbstractBase.Hierarchical {
765

766
        /**
767
         * Indicates that a visited method should be ignored.
768
         */
769
        @AlwaysNull
770
        private static final MethodVisitor IGNORE_METHOD = null;
1✔
771

772
        /**
773
         * The locator to query for finding binary data of a type.
774
         */
775
        protected final ClassFileLocator classFileLocator;
776

777
        /**
778
         * The reader mode to apply by this default type pool.
779
         */
780
        protected final ReaderMode readerMode;
781

782
        /**
783
         * Creates a new default type pool without a parent pool.
784
         *
785
         * @param cacheProvider    The cache provider to be used.
786
         * @param classFileLocator The class file locator to be used.
787
         * @param readerMode       The reader mode to apply by this default type pool.
788
         */
789
        public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode) {
790
            this(cacheProvider, classFileLocator, readerMode, Empty.INSTANCE);
1✔
791
        }
1✔
792

793
        /**
794
         * Creates a new default type pool.
795
         *
796
         * @param cacheProvider    The cache provider to be used.
797
         * @param classFileLocator The class file locator to be used.
798
         * @param readerMode       The reader mode to apply by this default type pool.
799
         * @param parentPool       The parent type pool.
800
         */
801
        public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, TypePool parentPool) {
802
            super(cacheProvider, parentPool);
1✔
803
            this.classFileLocator = classFileLocator;
1✔
804
            this.readerMode = readerMode;
1✔
805
        }
1✔
806

807
        /**
808
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the system class
809
         * loader. The returned instance is configured to use a fast reading mode and a simple cache.
810
         *
811
         * @return A type pool that reads its data from the system class loader.
812
         */
813
        public static TypePool ofSystemLoader() {
814
            return of(ClassFileLocator.ForClassLoader.ofSystemLoader());
1✔
815
        }
816

817
        /**
818
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the plaform class
819
         * loader. The returned instance is configured to use a fast reading mode and a simple cache. If the current
820
         * VM is of version 8 or older, the extension class loader is represented instead.
821
         *
822
         * @return A type pool that reads its data from the platform class path.
823
         */
824
        public static TypePool ofPlatformLoader() {
825
            return of(ClassFileLocator.ForClassLoader.ofPlatformLoader());
×
826
        }
827

828
        /**
829
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the boot class
830
         * loader. The returned instance is configured to use a fast reading mode and a simple cache.
831
         *
832
         * @return A type pool that reads its data from the boot class loader.
833
         */
834
        public static TypePool ofBootLoader() {
835
            return of(ClassFileLocator.ForClassLoader.ofBootLoader());
×
836
        }
837

838
        /**
839
         * Returns a type pool for the provided class loader.
840
         *
841
         * @param classLoader The class loader for which this class pool is representing types.
842
         * @return An appropriate type pool.
843
         */
844
        public static TypePool of(@MaybeNull ClassLoader classLoader) {
845
            return of(ClassFileLocator.ForClassLoader.of(classLoader));
1✔
846
        }
847

848
        /**
849
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the supplied class
850
         * file locator. The returned instance is configured to use a fast reading mode and a simple cache.
851
         *
852
         * @param classFileLocator The class file locator to use.
853
         * @return A type pool that reads its data from the system class path.
854
         */
855
        public static TypePool of(ClassFileLocator classFileLocator) {
856
            return new Default(new CacheProvider.Simple(), classFileLocator, ReaderMode.FAST);
1✔
857
        }
858

859
        @Override
860
        protected Resolution doDescribe(String name) {
861
            try {
862
                ClassFileLocator.Resolution resolution = classFileLocator.locate(name);
1✔
863
                return resolution.isResolved()
1✔
864
                        ? new Resolution.Simple(parse(resolution.resolve()))
1✔
865
                        : new Resolution.Illegal(name);
866
            } catch (IOException exception) {
×
867
                throw new IllegalStateException("Error while reading class file", exception);
×
868
            }
869
        }
870

871
        /**
872
         * Parses a binary representation and transforms it into a type description.
873
         *
874
         * @param binaryRepresentation The binary data to be parsed.
875
         * @return A type description of the binary data.
876
         */
877
        private TypeDescription parse(byte[] binaryRepresentation) {
878
            ClassReader classReader = OpenedClassReader.of(binaryRepresentation);
1✔
879
            TypeExtractor typeExtractor = new TypeExtractor();
1✔
880
            classReader.accept(typeExtractor, readerMode.getFlags());
1✔
881
            return typeExtractor.toTypeDescription();
1✔
882
        }
883

884
        /**
885
         * Determines the granularity of the class file parsing that is conducted by a {@link net.bytebuddy.pool.TypePool.Default}.
886
         */
887
        public enum ReaderMode {
1✔
888

889
            /**
890
             * The extended reader mode parses the code segment of each method in order to detect parameter names
891
             * that are only stored in a method's debugging information but are not explicitly included.
892
             */
893
            EXTENDED(ClassReader.SKIP_FRAMES),
1✔
894

895
            /**
896
             * The fast reader mode skips the code segment of each method and cannot detect parameter names that are
897
             * only contained within the debugging information. This mode still detects explicitly included method
898
             * parameter names.
899
             */
900
            FAST(ClassReader.SKIP_CODE);
1✔
901

902
            /**
903
             * The flags to provide to a {@link ClassReader} for parsing a file.
904
             */
905
            private final int flags;
906

907
            /**
908
             * Creates a new reader mode constant.
909
             *
910
             * @param flags The flags to provide to a {@link ClassReader} for parsing a file.
911
             */
912
            ReaderMode(int flags) {
1✔
913
                this.flags = flags;
1✔
914
            }
1✔
915

916
            /**
917
             * Returns the flags to provide to a {@link ClassReader} for parsing a file.
918
             *
919
             * @return The flags to provide to a {@link ClassReader} for parsing a file.
920
             */
921
            protected int getFlags() {
922
                return flags;
1✔
923
            }
924

925
            /**
926
             * Determines if this reader mode represents extended reading.
927
             *
928
             * @return {@code true} if this reader mode represents extended reading.
929
             */
930
            public boolean isExtended() {
931
                return this == EXTENDED;
1✔
932
            }
933
        }
934

935
        /**
936
         * <p>
937
         * A variant of {@link TypePool.Default} that resolves type descriptions lazily. A lazy resolution respects this type
938
         * pool's {@link CacheProvider} but requeries this cache pool for every access of a property of a {@link TypeDescription}.
939
         * </p>
940
         * <p>
941
         * {@link Resolution}s of this type pool are only fully resolved if a property that is not the type's name is required.
942
         * </p>
943
         */
944
        public static class WithLazyResolution extends Default {
945

946
            /**
947
             * Creates a new default type pool with lazy resolution and without a parent pool.
948
             *
949
             * @param cacheProvider    The cache provider to be used.
950
             * @param classFileLocator The class file locator to be used.
951
             * @param readerMode       The reader mode to apply by this default type pool.
952
             */
953
            public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode) {
954
                this(cacheProvider, classFileLocator, readerMode, Empty.INSTANCE);
1✔
955
            }
1✔
956

957
            /**
958
             * Creates a new default type pool with lazy resolution.
959
             *
960
             * @param cacheProvider    The cache provider to be used.
961
             * @param classFileLocator The class file locator to be used.
962
             * @param readerMode       The reader mode to apply by this default type pool.
963
             * @param parentPool       The parent type pool.
964
             */
965
            public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, TypePool parentPool) {
966
                super(cacheProvider, classFileLocator, readerMode, parentPool);
1✔
967
            }
1✔
968

969
            /**
970
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the system class
971
             * loader. The returned instance is configured to use a fast reading mode and a simple cache.
972
             *
973
             * @return A type pool that reads its data from the system class loader.
974
             */
975
            public static TypePool ofSystemLoader() {
976
                return of(ClassFileLocator.ForClassLoader.ofSystemLoader());
×
977
            }
978

979
            /**
980
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the platform class
981
             * 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,
982
             * the type pool represents the extension class loader.
983
             *
984
             * @return A type pool that reads its data from the boot class loader.
985
             */
986
            public static TypePool ofPlatformLoader() {
987
                return of(ClassFileLocator.ForClassLoader.ofPlatformLoader());
×
988
            }
989

990
            /**
991
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the boot class
992
             * loader. The returned instance is configured to use a fast reading mode and a simple cache.
993
             *
994
             * @return A type pool that reads its data from the boot class loader.
995
             */
996
            public static TypePool ofBootLoader() {
997
                return of(ClassFileLocator.ForClassLoader.ofBootLoader());
×
998
            }
999

1000
            /**
1001
             * Returns a default {@link TypePool} with lazy resolution for the provided class loader.
1002
             *
1003
             * @param classLoader The class loader for which this class pool is representing types.
1004
             * @return An appropriate type pool.
1005
             */
1006
            public static TypePool of(@MaybeNull ClassLoader classLoader) {
1007
                return of(ClassFileLocator.ForClassLoader.of(classLoader));
×
1008
            }
1009

1010
            /**
1011
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the supplied class
1012
             * file locator. The returned instance is configured to use a fast reading mode and a simple cache.
1013
             *
1014
             * @param classFileLocator The class file locator to use.
1015
             * @return A type pool that reads its data from the system class path.
1016
             */
1017
            public static TypePool of(ClassFileLocator classFileLocator) {
1018
                return new WithLazyResolution(new CacheProvider.Simple(), classFileLocator, ReaderMode.FAST);
1✔
1019
            }
1020

1021
            @Override
1022
            protected Resolution doDescribe(String name) {
1023
                return new LazyResolution(name);
1✔
1024
            }
1025

1026
            /**
1027
             * {@inheritDoc}
1028
             */
1029
            protected Resolution doCache(String name, Resolution resolution) {
1030
                return resolution;
1✔
1031
            }
1032

1033
            /**
1034
             * Non-lazily resolves a type name.
1035
             *
1036
             * @param name The name of the type to resolve.
1037
             * @return The resolution for the type of this name.
1038
             */
1039
            protected Resolution doResolve(String name) {
1040
                Resolution resolution = cacheProvider.find(name);
1✔
1041
                if (resolution == null) {
1✔
1042
                    resolution = cacheProvider.register(name, WithLazyResolution.super.doDescribe(name));
1✔
1043
                }
1044
                return resolution;
1✔
1045
            }
1046

1047
            /**
1048
             * A lazy resolution of a type that the enclosing type pool attempts to resolve.
1049
             */
1050
            @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
1051
            protected class LazyResolution implements Resolution {
1052

1053
                /**
1054
                 * The type's name.
1055
                 */
1056
                private final String name;
1057

1058
                /**
1059
                 * Creates a new lazy resolution.
1060
                 *
1061
                 * @param name The type's name.
1062
                 */
1063
                protected LazyResolution(String name) {
1✔
1064
                    this.name = name;
1✔
1065
                }
1✔
1066

1067
                /**
1068
                 * {@inheritDoc}
1069
                 */
1070
                public boolean isResolved() {
1071
                    return doResolve(name).isResolved();
1✔
1072
                }
1073

1074
                /**
1075
                 * {@inheritDoc}
1076
                 */
1077
                public TypeDescription resolve() {
1078
                    return new LazyTypeDescription(name);
1✔
1079
                }
1080
            }
1081

1082
            /**
1083
             * A lazy type description that resolves any property that is not the name only when requested.
1084
             */
1085
            protected class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType.WithDelegation {
1086

1087
                /**
1088
                 * The type's name.
1089
                 */
1090
                private final String name;
1091

1092
                /**
1093
                 * Creates a new lazy type description.
1094
                 *
1095
                 * @param name The type's name.
1096
                 */
1097
                protected LazyTypeDescription(String name) {
1✔
1098
                    this.name = name;
1✔
1099
                }
1✔
1100

1101
                /**
1102
                 * {@inheritDoc}
1103
                 */
1104
                public String getName() {
1105
                    return name;
1✔
1106
                }
1107

1108
                @Override
1109
                @CachedReturnPlugin.Enhance("delegate")
1110
                protected TypeDescription delegate() {
1111
                    return doResolve(name).resolve();
1✔
1112
                }
1113
            }
1114
        }
1115

1116
        /**
1117
         * An annotation registrant implements a visitor pattern for reading an unknown amount of values of annotations.
1118
         */
1119
        protected interface AnnotationRegistrant {
1120

1121
            /**
1122
             * Registers an annotation value.
1123
             *
1124
             * @param name            The name of the annotation value.
1125
             * @param annotationValue The value of the annotation.
1126
             */
1127
            void register(String name, AnnotationValue<?, ?> annotationValue);
1128

1129
            /**
1130
             * Called once all annotation values are visited.
1131
             */
1132
            void onComplete();
1133

1134
            /**
1135
             * An abstract base implementation of an annotation registrant.
1136
             */
1137
            abstract class AbstractBase implements AnnotationRegistrant {
1138

1139
                /**
1140
                 * The annotation descriptor.
1141
                 */
1142
                private final String descriptor;
1143

1144
                /**
1145
                 * The values that were collected so far.
1146
                 */
1147
                private final Map<String, AnnotationValue<?, ?>> values;
1148

1149
                /**
1150
                 * Creates a new annotation registrant.
1151
                 *
1152
                 * @param descriptor The annotation descriptor.
1153
                 */
1154
                protected AbstractBase(String descriptor) {
1✔
1155
                    this.descriptor = descriptor;
1✔
1156
                    values = new HashMap<String, AnnotationValue<?, ?>>();
1✔
1157
                }
1✔
1158

1159
                /**
1160
                 * {@inheritDoc}
1161
                 */
1162
                public void register(String name, AnnotationValue<?, ?> annotationValue) {
1163
                    values.put(name, annotationValue);
1✔
1164
                }
1✔
1165

1166
                /**
1167
                 * {@inheritDoc}
1168
                 */
1169
                public void onComplete() {
1170
                    getTokens().add(new LazyTypeDescription.AnnotationToken(descriptor, values));
1✔
1171
                }
1✔
1172

1173
                /**
1174
                 * Returns the token list for this collector.
1175
                 *
1176
                 * @return The token list for this collector.
1177
                 */
1178
                protected abstract List<LazyTypeDescription.AnnotationToken> getTokens();
1179

1180
                /**
1181
                 * A base implementation for a collector for a type variable.
1182
                 */
1183
                protected abstract static class ForTypeVariable extends AbstractBase {
1184

1185
                    /**
1186
                     * The type variable's type path.
1187
                     */
1188
                    private final String typePath;
1189

1190
                    /**
1191
                     * Creates a new annotation collector.
1192
                     *
1193
                     * @param descriptor The annotation descriptor.
1194
                     * @param typePath   The type variable's type path.
1195
                     */
1196
                    protected ForTypeVariable(String descriptor, @MaybeNull TypePath typePath) {
1197
                        super(descriptor);
1✔
1198
                        this.typePath = typePath == null
1✔
1199
                                ? LazyTypeDescription.GenericTypeToken.EMPTY_TYPE_PATH
1200
                                : typePath.toString();
1✔
1201
                    }
1✔
1202

1203
                    @Override
1204
                    protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1205
                        Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap = getPathMap();
1✔
1206
                        List<LazyTypeDescription.AnnotationToken> tokens = pathMap.get(typePath);
1✔
1207
                        if (tokens == null) {
1✔
1208
                            tokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
1209
                            pathMap.put(typePath, tokens);
1✔
1210
                        }
1211
                        return tokens;
1✔
1212
                    }
1213

1214
                    /**
1215
                     * Returns this collector's path map.
1216
                     *
1217
                     * @return This collector's path map.
1218
                     */
1219
                    protected abstract Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap();
1220

1221
                    /**
1222
                     * A base implementation for a collector for a type variable with an index.
1223
                     */
1224
                    protected abstract static class WithIndex extends AbstractBase.ForTypeVariable {
1225

1226
                        /**
1227
                         * The type variable's index.
1228
                         */
1229
                        private final int index;
1230

1231
                        /**
1232
                         * Creates a new annotation collector.
1233
                         *
1234
                         * @param descriptor The annotation descriptor.
1235
                         * @param typePath   The type variable's type path.
1236
                         * @param index      The type variable's index.
1237
                         */
1238
                        protected WithIndex(String descriptor, @MaybeNull TypePath typePath, int index) {
1239
                            super(descriptor, typePath);
1✔
1240
                            this.index = index;
1✔
1241
                        }
1✔
1242

1243
                        @Override
1244
                        protected Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap() {
1245
                            Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap = getIndexedPathMap();
1✔
1246
                            Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap = indexedPathMap.get(index);
1✔
1247
                            if (pathMap == null) {
1✔
1248
                                pathMap = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
1249
                                indexedPathMap.put(index, pathMap);
1✔
1250
                            }
1251
                            return pathMap;
1✔
1252
                        }
1253

1254
                        /**
1255
                         * Returns this collector's indexed path map.
1256
                         *
1257
                         * @return This collector's indexed path map.
1258
                         */
1259
                        protected abstract Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap();
1260

1261
                        /**
1262
                         * A base implementation for a collector for a type variable with two indices.
1263
                         */
1264
                        protected abstract static class DoubleIndexed extends WithIndex {
1265

1266
                            /**
1267
                             * The type variable's first index.
1268
                             */
1269
                            private final int preIndex;
1270

1271
                            /**
1272
                             * Creates a new annotation collector.
1273
                             *
1274
                             * @param descriptor The annotation descriptor.
1275
                             * @param typePath   The type variable's type path.
1276
                             * @param index      The type variable's index.
1277
                             * @param preIndex   The type variable's first index.
1278
                             */
1279
                            protected DoubleIndexed(String descriptor, @MaybeNull TypePath typePath, int index, int preIndex) {
1280
                                super(descriptor, typePath, index);
1✔
1281
                                this.preIndex = preIndex;
1✔
1282
                            }
1✔
1283

1284
                            @Override
1285
                            protected Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap() {
1286
                                Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexPathMap = getDoubleIndexedPathMap();
1✔
1287
                                Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap = doubleIndexPathMap.get(preIndex);
1✔
1288
                                if (indexedPathMap == null) {
1✔
1289
                                    indexedPathMap = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
1290
                                    doubleIndexPathMap.put(preIndex, indexedPathMap);
1✔
1291
                                }
1292
                                return indexedPathMap;
1✔
1293
                            }
1294

1295
                            /**
1296
                             * Returns this collector's double indexed path map.
1297
                             *
1298
                             * @return This collector's double indexed path map.
1299
                             */
1300
                            protected abstract Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> getDoubleIndexedPathMap();
1301
                        }
1302
                    }
1303
                }
1304
            }
1305

1306
            /**
1307
             * An annotation collector for a byte code element.
1308
             */
1309
            class ForByteCodeElement extends AbstractBase {
1310

1311
                /**
1312
                 * The target collection.
1313
                 */
1314
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
1315

1316
                /**
1317
                 * Creates a new annotation collector for a byte code element.
1318
                 *
1319
                 * @param descriptor       The annotation descriptor.
1320
                 * @param annotationTokens The target collection.
1321
                 */
1322
                protected ForByteCodeElement(String descriptor, List<LazyTypeDescription.AnnotationToken> annotationTokens) {
1323
                    super(descriptor);
1✔
1324
                    this.annotationTokens = annotationTokens;
1✔
1325
                }
1✔
1326

1327
                @Override
1328
                protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1329
                    return annotationTokens;
1✔
1330
                }
1331

1332
                /**
1333
                 * An annotation collector for a byte code element with an index.
1334
                 */
1335
                public static class WithIndex extends AbstractBase {
1336

1337
                    /**
1338
                     * The byte code element's index.
1339
                     */
1340
                    private final int index;
1341

1342
                    /**
1343
                     * The target collection.
1344
                     */
1345
                    private final Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens;
1346

1347
                    /**
1348
                     * Creates a new annotation collector for a byte code element with an index.
1349
                     *
1350
                     * @param descriptor       The annotation descriptor.
1351
                     * @param index            The byte code element's index.
1352
                     * @param annotationTokens The target collection.
1353
                     */
1354
                    protected WithIndex(String descriptor, int index, Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens) {
1355
                        super(descriptor);
1✔
1356
                        this.index = index;
1✔
1357
                        this.annotationTokens = annotationTokens;
1✔
1358
                    }
1✔
1359

1360
                    @Override
1361
                    protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1362
                        List<LazyTypeDescription.AnnotationToken> annotationTokens = this.annotationTokens.get(index);
1✔
1363
                        if (annotationTokens == null) {
1✔
1364
                            annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
1365
                            this.annotationTokens.put(index, annotationTokens);
1✔
1366
                        }
1367
                        return annotationTokens;
1✔
1368
                    }
1369
                }
1370
            }
1371

1372
            /**
1373
             * An annotation collector for a type variable.
1374
             */
1375
            class ForTypeVariable extends AbstractBase.ForTypeVariable {
1376

1377
                /**
1378
                 * The target collection.
1379
                 */
1380
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap;
1381

1382
                /**
1383
                 * Creates a new annotation collector.
1384
                 *
1385
                 * @param descriptor The annotation descriptor.
1386
                 * @param typePath   The type variable's type path.
1387
                 * @param pathMap    The target collection.
1388
                 */
1389
                protected ForTypeVariable(String descriptor, @MaybeNull TypePath typePath, Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap) {
1390
                    super(descriptor, typePath);
1✔
1391
                    this.pathMap = pathMap;
1✔
1392
                }
1✔
1393

1394
                @Override
1395
                protected Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap() {
1396
                    return pathMap;
1✔
1397
                }
1398

1399
                /**
1400
                 * An annotation collector for a type variable with an index.
1401
                 */
1402
                public static class WithIndex extends AbstractBase.ForTypeVariable.WithIndex {
1403

1404
                    /**
1405
                     * The target collection.
1406
                     */
1407
                    private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap;
1408

1409
                    /**
1410
                     * Creates a new annotation collector.
1411
                     *
1412
                     * @param descriptor     The annotation descriptor.
1413
                     * @param typePath       The type variable's type path.
1414
                     * @param index          The target index.
1415
                     * @param indexedPathMap The target collection.
1416
                     */
1417
                    protected WithIndex(String descriptor,
1418
                                        @MaybeNull TypePath typePath,
1419
                                        int index,
1420
                                        Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap) {
1421
                        super(descriptor, typePath, index);
1✔
1422
                        this.indexedPathMap = indexedPathMap;
1✔
1423
                    }
1✔
1424

1425
                    @Override
1426
                    protected Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap() {
1427
                        return indexedPathMap;
1✔
1428
                    }
1429

1430
                    /**
1431
                     * An annotation collector for a type variable with two indices.
1432
                     */
1433
                    public static class DoubleIndexed extends AbstractBase.ForTypeVariable.WithIndex.DoubleIndexed {
1434

1435
                        /**
1436
                         * The target collection.
1437
                         */
1438
                        private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexedPathMap;
1439

1440
                        /**
1441
                         * Creates a new annotation collector.
1442
                         *
1443
                         * @param descriptor           The annotation descriptor.
1444
                         * @param typePath             The type variable's type path.
1445
                         * @param index                The target index.
1446
                         * @param preIndex             The initial target index.
1447
                         * @param doubleIndexedPathMap The target collection.
1448
                         */
1449
                        protected DoubleIndexed(String descriptor,
1450
                                                @MaybeNull TypePath typePath,
1451
                                                int index,
1452
                                                int preIndex,
1453
                                                Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexedPathMap) {
1454
                            super(descriptor, typePath, index, preIndex);
1✔
1455
                            this.doubleIndexedPathMap = doubleIndexedPathMap;
1✔
1456
                        }
1✔
1457

1458
                        @Override
1459
                        protected Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> getDoubleIndexedPathMap() {
1460
                            return doubleIndexedPathMap;
1✔
1461
                        }
1462
                    }
1463
                }
1464
            }
1465
        }
1466

1467
        /**
1468
         * A component type locator allows for the lazy location of an array's component type.
1469
         */
1470
        protected interface ComponentTypeLocator {
1471

1472
            /**
1473
             * Binds this component type to a given property name of an annotation.
1474
             *
1475
             * @param name The name of an annotation property which the returned component type reference should
1476
             *             query for resolving an array's component type.
1477
             * @return A component type reference to an annotation value's component type.
1478
             */
1479
            ComponentTypeReference bind(String name);
1480

1481
            /**
1482
             * A component type locator which cannot legally resolve an array's component type.
1483
             */
1484
            enum Illegal implements ComponentTypeLocator {
1✔
1485

1486
                /**
1487
                 * The singleton instance.
1488
                 */
1489
                INSTANCE;
1✔
1490

1491
                /**
1492
                 * {@inheritDoc}
1493
                 */
1494
                public ComponentTypeReference bind(String name) {
1495
                    throw new IllegalStateException("Unexpected lookup of component type for " + name);
1✔
1496
                }
1497
            }
1498

1499
            /**
1500
             * A component type locator that lazily analyses an annotation for resolving an annotation property's
1501
             * array value's component type.
1502
             */
1503
            @HashCodeAndEqualsPlugin.Enhance
1504
            class ForAnnotationProperty implements ComponentTypeLocator {
1505

1506
                /**
1507
                 * The type pool to query for type descriptions.
1508
                 */
1509
                private final TypePool typePool;
1510

1511
                /**
1512
                 * The name of the annotation to analyze.
1513
                 */
1514
                private final String annotationName;
1515

1516
                /**
1517
                 * Creates a new component type locator for an array value.
1518
                 *
1519
                 * @param typePool             The type pool to be used for looking up linked types.
1520
                 * @param annotationDescriptor A descriptor of the annotation to analyze.
1521
                 */
1522
                public ForAnnotationProperty(TypePool typePool, String annotationDescriptor) {
1✔
1523
                    this.typePool = typePool;
1✔
1524
                    annotationName = annotationDescriptor.substring(1, annotationDescriptor.length() - 1).replace('/', '.');
1✔
1525
                }
1✔
1526

1527
                /**
1528
                 * {@inheritDoc}
1529
                 */
1530
                public ComponentTypeReference bind(String name) {
1531
                    return new Bound(name);
1✔
1532
                }
1533

1534
                /**
1535
                 * A bound representation of a
1536
                 * {@link net.bytebuddy.pool.TypePool.Default.ComponentTypeLocator.ForAnnotationProperty}.
1537
                 */
1538
                @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
1539
                protected class Bound implements ComponentTypeReference {
1540

1541
                    /**
1542
                     * The name of the annotation property.
1543
                     */
1544
                    private final String name;
1545

1546
                    /**
1547
                     * Creates a new bound component type locator for an annotation property.
1548
                     *
1549
                     * @param name The name of the annotation property.
1550
                     */
1551
                    protected Bound(String name) {
1✔
1552
                        this.name = name;
1✔
1553
                    }
1✔
1554

1555
                    /**
1556
                     * {@inheritDoc}
1557
                     */
1558
                    @MaybeNull
1559
                    public String resolve() {
1560
                        TypeDescription componentType = typePool.describe(annotationName)
1✔
1561
                                .resolve()
1✔
1562
                                .getDeclaredMethods()
1✔
1563
                                .filter(named(name))
1✔
1564
                                .getOnly()
1✔
1565
                                .getReturnType()
1✔
1566
                                .asErasure()
1✔
1567
                                .getComponentType();
1✔
1568
                        return componentType == null
1✔
1569
                                ? NO_ARRAY
1570
                                : componentType.getName();
1✔
1571
                    }
1572
                }
1573
            }
1574

1575
            /**
1576
             * A component type locator that locates an array type by a method's return value from its method descriptor.
1577
             */
1578
            @HashCodeAndEqualsPlugin.Enhance
1579
            class ForArrayType implements ComponentTypeLocator, ComponentTypeReference {
1580

1581
                /**
1582
                 * The resolved component type's binary name.
1583
                 */
1584
                private final String componentType;
1585

1586
                /**
1587
                 * Creates a new component type locator for an array type.
1588
                 *
1589
                 * @param methodDescriptor The method descriptor to resolve.
1590
                 */
1591
                public ForArrayType(String methodDescriptor) {
1✔
1592
                    String arrayType = Type.getMethodType(methodDescriptor).getReturnType().getClassName();
1✔
1593
                    componentType = arrayType.substring(0, arrayType.length() - 2);
1✔
1594
                }
1✔
1595

1596
                /**
1597
                 * {@inheritDoc}
1598
                 */
1599
                public ComponentTypeReference bind(String name) {
1600
                    return this;
1✔
1601
                }
1602

1603
                /**
1604
                 * {@inheritDoc}
1605
                 */
1606
                public String resolve() {
1607
                    return componentType;
1✔
1608
                }
1609
            }
1610
        }
1611

1612
        /**
1613
         * A type registrant allows to register a generic type token.
1614
         */
1615
        protected interface GenericTypeRegistrant {
1616

1617
            /**
1618
             * Registers a discovered generic type token.
1619
             *
1620
             * @param token The token to be registered.
1621
             */
1622
            void register(LazyTypeDescription.GenericTypeToken token);
1623

1624
            /**
1625
             * A signature visitor that rejects any discovered generic type.
1626
             */
1627
            class RejectingSignatureVisitor extends SignatureVisitor {
1628

1629
                /**
1630
                 * The message of the error message.
1631
                 */
1632
                private static final String MESSAGE = "Unexpected token in generic signature";
1633

1634
                /**
1635
                 * Creates a new rejecting signature visitor.
1636
                 */
1637
                public RejectingSignatureVisitor() {
1638
                    super(OpenedClassReader.ASM_API);
1✔
1639
                }
1✔
1640

1641
                /**
1642
                 * {@inheritDoc}
1643
                 */
1644
                public void visitFormalTypeParameter(String name) {
1645
                    throw new IllegalStateException(MESSAGE);
×
1646
                }
1647

1648
                /**
1649
                 * {@inheritDoc}
1650
                 */
1651
                public SignatureVisitor visitClassBound() {
1652
                    throw new IllegalStateException(MESSAGE);
×
1653
                }
1654

1655
                /**
1656
                 * {@inheritDoc}
1657
                 */
1658
                public SignatureVisitor visitInterfaceBound() {
1659
                    throw new IllegalStateException(MESSAGE);
×
1660
                }
1661

1662
                /**
1663
                 * {@inheritDoc}
1664
                 */
1665
                public SignatureVisitor visitSuperclass() {
1666
                    throw new IllegalStateException(MESSAGE);
1✔
1667
                }
1668

1669
                /**
1670
                 * {@inheritDoc}
1671
                 */
1672
                public SignatureVisitor visitInterface() {
1673
                    throw new IllegalStateException(MESSAGE);
×
1674
                }
1675

1676
                /**
1677
                 * {@inheritDoc}
1678
                 */
1679
                public SignatureVisitor visitParameterType() {
1680
                    throw new IllegalStateException(MESSAGE);
×
1681
                }
1682

1683
                /**
1684
                 * {@inheritDoc}
1685
                 */
1686
                public SignatureVisitor visitReturnType() {
1687
                    throw new IllegalStateException(MESSAGE);
×
1688
                }
1689

1690
                /**
1691
                 * {@inheritDoc}
1692
                 */
1693
                public SignatureVisitor visitExceptionType() {
1694
                    throw new IllegalStateException(MESSAGE);
×
1695
                }
1696

1697
                /**
1698
                 * {@inheritDoc}
1699
                 */
1700
                public void visitBaseType(char descriptor) {
1701
                    throw new IllegalStateException(MESSAGE);
×
1702
                }
1703

1704
                /**
1705
                 * {@inheritDoc}
1706
                 */
1707
                public void visitTypeVariable(String name) {
1708
                    throw new IllegalStateException(MESSAGE);
×
1709
                }
1710

1711
                /**
1712
                 * {@inheritDoc}
1713
                 */
1714
                public SignatureVisitor visitArrayType() {
1715
                    throw new IllegalStateException(MESSAGE);
×
1716
                }
1717

1718
                /**
1719
                 * {@inheritDoc}
1720
                 */
1721
                public void visitClassType(String name) {
1722
                    throw new IllegalStateException(MESSAGE);
×
1723
                }
1724

1725
                /**
1726
                 * {@inheritDoc}
1727
                 */
1728
                public void visitInnerClassType(String name) {
1729
                    throw new IllegalStateException(MESSAGE);
×
1730
                }
1731

1732
                /**
1733
                 * {@inheritDoc}
1734
                 */
1735
                public void visitTypeArgument() {
1736
                    throw new IllegalStateException(MESSAGE);
×
1737
                }
1738

1739
                /**
1740
                 * {@inheritDoc}
1741
                 */
1742
                public SignatureVisitor visitTypeArgument(char wildcard) {
1743
                    throw new IllegalStateException(MESSAGE);
×
1744
                }
1745

1746
                /**
1747
                 * {@inheritDoc}
1748
                 */
1749
                public void visitEnd() {
1750
                    throw new IllegalStateException(MESSAGE);
×
1751
                }
1752
            }
1753
        }
1754

1755
        /**
1756
         * A bag for collecting parameter meta information that is stored as debug information for implemented
1757
         * methods.
1758
         */
1759
        protected static class ParameterBag {
1760

1761
            /**
1762
             * An array of the method's parameter types.
1763
             */
1764
            private final Type[] parameterType;
1765

1766
            /**
1767
             * A map containing the tokens that were collected until now.
1768
             */
1769
            private final Map<Integer, String> parameterRegistry;
1770

1771
            /**
1772
             * Creates a new bag.
1773
             *
1774
             * @param parameterType An array of parameter types for the method on which this parameter bag
1775
             *                      is used.
1776
             */
1777
            protected ParameterBag(Type[] parameterType) {
1✔
1778
                this.parameterType = parameterType;
1✔
1779
                parameterRegistry = new HashMap<Integer, String>();
1✔
1780
            }
1✔
1781

1782
            /**
1783
             * Registers a new parameter.
1784
             *
1785
             * @param offset The offset of the registered entry on the local variable array of the method.
1786
             * @param name   The name of the parameter.
1787
             */
1788
            protected void register(int offset, String name) {
1789
                parameterRegistry.put(offset, name);
1✔
1790
            }
1✔
1791

1792
            /**
1793
             * Resolves the collected parameters as a list of parameter tokens.
1794
             *
1795
             * @param isStatic {@code true} if the analyzed method is static.
1796
             * @return A list of parameter tokens based on the collected information.
1797
             */
1798
            protected List<LazyTypeDescription.MethodToken.ParameterToken> resolve(boolean isStatic) {
1799
                List<LazyTypeDescription.MethodToken.ParameterToken> parameterTokens = new ArrayList<LazyTypeDescription.MethodToken.ParameterToken>(parameterType.length);
1✔
1800
                int offset = isStatic
1✔
1801
                        ? StackSize.ZERO.getSize()
1✔
1802
                        : StackSize.SINGLE.getSize();
1✔
1803
                for (Type aParameterType : parameterType) {
1✔
1804
                    String name = this.parameterRegistry.get(offset);
1✔
1805
                    parameterTokens.add(name == null
1✔
1806
                            ? new LazyTypeDescription.MethodToken.ParameterToken()
1807
                            : new LazyTypeDescription.MethodToken.ParameterToken(name));
1808
                    offset += aParameterType.getSize();
1✔
1809
                }
1810
                return parameterTokens;
1✔
1811
            }
1812
        }
1813

1814
        /**
1815
         * A generic type extractor allows for an iterative extraction of generic type information.
1816
         */
1817
        protected static class GenericTypeExtractor extends GenericTypeRegistrant.RejectingSignatureVisitor implements GenericTypeRegistrant {
1818

1819
            /**
1820
             * A registrant that receives any discovered type.
1821
             */
1822
            private final GenericTypeRegistrant genericTypeRegistrant;
1823

1824
            /**
1825
             * The current token that is in the process of creation.
1826
             */
1827
            @UnknownNull
1828
            private IncompleteToken incompleteToken;
1829

1830
            /**
1831
             * Creates a new generic type extractor.
1832
             *
1833
             * @param genericTypeRegistrant The target to receive the complete type.
1834
             */
1835
            protected GenericTypeExtractor(GenericTypeRegistrant genericTypeRegistrant) {
1✔
1836
                this.genericTypeRegistrant = genericTypeRegistrant;
1✔
1837
            }
1✔
1838

1839
            /**
1840
             * {@inheritDoc}
1841
             */
1842
            public void visitBaseType(char descriptor) {
1843
                genericTypeRegistrant.register(LazyTypeDescription.GenericTypeToken.ForPrimitiveType.of(descriptor));
1✔
1844
            }
1✔
1845

1846
            /**
1847
             * {@inheritDoc}
1848
             */
1849
            public void visitTypeVariable(String name) {
1850
                genericTypeRegistrant.register(new LazyTypeDescription.GenericTypeToken.ForTypeVariable(name));
1✔
1851
            }
1✔
1852

1853
            /**
1854
             * {@inheritDoc}
1855
             */
1856
            public SignatureVisitor visitArrayType() {
1857
                return new GenericTypeExtractor(this);
1✔
1858
            }
1859

1860
            /**
1861
             * {@inheritDoc}
1862
             */
1863
            public void register(LazyTypeDescription.GenericTypeToken componentTypeToken) {
1864
                genericTypeRegistrant.register(new LazyTypeDescription.GenericTypeToken.ForGenericArray(componentTypeToken));
1✔
1865
            }
1✔
1866

1867
            /**
1868
             * {@inheritDoc}
1869
             */
1870
            public void visitClassType(String name) {
1871
                incompleteToken = new IncompleteToken.ForTopLevelType(name);
1✔
1872
            }
1✔
1873

1874
            /**
1875
             * {@inheritDoc}
1876
             */
1877
            public void visitInnerClassType(String name) {
1878
                incompleteToken = new IncompleteToken.ForInnerClass(name, incompleteToken);
1✔
1879
            }
1✔
1880

1881
            /**
1882
             * {@inheritDoc}
1883
             */
1884
            public void visitTypeArgument() {
1885
                incompleteToken.appendPlaceholder();
1✔
1886
            }
1✔
1887

1888
            /**
1889
             * {@inheritDoc}
1890
             */
1891
            public SignatureVisitor visitTypeArgument(char wildcard) {
1892
                switch (wildcard) {
1✔
1893
                    case SignatureVisitor.SUPER:
1894
                        return incompleteToken.appendLowerBound();
1✔
1895
                    case SignatureVisitor.EXTENDS:
1896
                        return incompleteToken.appendUpperBound();
1✔
1897
                    case SignatureVisitor.INSTANCEOF:
1898
                        return incompleteToken.appendDirectBound();
1✔
1899
                    default:
1900
                        throw new IllegalArgumentException("Unknown wildcard: " + wildcard);
×
1901
                }
1902
            }
1903

1904
            /**
1905
             * {@inheritDoc}
1906
             */
1907
            public void visitEnd() {
1908
                genericTypeRegistrant.register(incompleteToken.toToken());
1✔
1909
            }
1✔
1910

1911
            /**
1912
             * An incomplete {@link LazyTypeDescription.GenericTypeToken}.
1913
             */
1914
            protected interface IncompleteToken {
1915

1916
                /**
1917
                 * Appends a lower bound to this token.
1918
                 *
1919
                 * @return A signature visitor for visiting the lower bound's type.
1920
                 */
1921
                SignatureVisitor appendLowerBound();
1922

1923
                /**
1924
                 * Appends an upper bound to this token.
1925
                 *
1926
                 * @return A signature visitor for visiting the upper bound's type.
1927
                 */
1928
                SignatureVisitor appendUpperBound();
1929

1930
                /**
1931
                 * Appends a direct bound to this token.
1932
                 *
1933
                 * @return A signature visitor for visiting the direct bound's type.
1934
                 */
1935
                SignatureVisitor appendDirectBound();
1936

1937
                /**
1938
                 * Appends a placeholder to this token.
1939
                 */
1940
                void appendPlaceholder();
1941

1942
                /**
1943
                 * Returns {@code true} if this token describes a type with parameters.
1944
                 *
1945
                 * @return {@code true} if this token describes a type with parameters.
1946
                 */
1947
                boolean isParameterized();
1948

1949
                /**
1950
                 * Returns the name of this token.
1951
                 *
1952
                 * @return The name of this token.
1953
                 */
1954
                String getName();
1955

1956
                /**
1957
                 * Converts this incomplete token to a completed token.
1958
                 *
1959
                 * @return The finalized token.
1960
                 */
1961
                LazyTypeDescription.GenericTypeToken toToken();
1962

1963
                /**
1964
                 * An abstract base implementation of an incomplete token.
1965
                 */
1966
                abstract class AbstractBase implements IncompleteToken {
1967

1968
                    /**
1969
                     * The parameters of this token.
1970
                     */
1971
                    protected final List<LazyTypeDescription.GenericTypeToken> parameters;
1972

1973
                    /**
1974
                     * Creates a new base implementation of an incomplete token.
1975
                     */
1976
                    public AbstractBase() {
1✔
1977
                        parameters = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
1978
                    }
1✔
1979

1980
                    /**
1981
                     * {@inheritDoc}
1982
                     */
1983
                    public SignatureVisitor appendDirectBound() {
1984
                        return new GenericTypeExtractor(new ForDirectBound());
1✔
1985
                    }
1986

1987
                    /**
1988
                     * {@inheritDoc}
1989
                     */
1990
                    public SignatureVisitor appendUpperBound() {
1991
                        return new GenericTypeExtractor(new ForUpperBound());
1✔
1992
                    }
1993

1994
                    /**
1995
                     * {@inheritDoc}
1996
                     */
1997
                    public SignatureVisitor appendLowerBound() {
1998
                        return new GenericTypeExtractor(new ForLowerBound());
1✔
1999
                    }
2000

2001
                    /**
2002
                     * {@inheritDoc}
2003
                     */
2004
                    public void appendPlaceholder() {
2005
                        parameters.add(LazyTypeDescription.GenericTypeToken.ForUnboundWildcard.INSTANCE);
1✔
2006
                    }
1✔
2007

2008
                    /**
2009
                     * A token for registering a direct bound.
2010
                     */
2011
                    protected class ForDirectBound implements GenericTypeRegistrant {
1✔
2012

2013
                        /**
2014
                         * {@inheritDoc}
2015
                         */
2016
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2017
                            parameters.add(token);
1✔
2018
                        }
1✔
2019
                    }
2020

2021
                    /**
2022
                     * A token for registering a wildcard with an upper bound.
2023
                     */
2024
                    protected class ForUpperBound implements GenericTypeRegistrant {
1✔
2025

2026
                        /**
2027
                         * {@inheritDoc}
2028
                         */
2029
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2030
                            parameters.add(new LazyTypeDescription.GenericTypeToken.ForUpperBoundWildcard(token));
1✔
2031
                        }
1✔
2032
                    }
2033

2034
                    /**
2035
                     * A token for registering a wildcard with a lower bound.
2036
                     */
2037
                    protected class ForLowerBound implements GenericTypeRegistrant {
1✔
2038

2039
                        /**
2040
                         * {@inheritDoc}
2041
                         */
2042
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2043
                            parameters.add(new LazyTypeDescription.GenericTypeToken.ForLowerBoundWildcard(token));
1✔
2044
                        }
1✔
2045
                    }
2046
                }
2047

2048
                /**
2049
                 * An incomplete token representing a generic type without an outer type.
2050
                 */
2051
                @HashCodeAndEqualsPlugin.Enhance
2052
                class ForTopLevelType extends AbstractBase {
2053

2054
                    /**
2055
                     * The internal name of the type.
2056
                     */
2057
                    private final String internalName;
2058

2059
                    /**
2060
                     * Creates a new incomplete token representing a type without an outer type.
2061
                     *
2062
                     * @param internalName The internal name of the type.
2063
                     */
2064
                    public ForTopLevelType(String internalName) {
1✔
2065
                        this.internalName = internalName;
1✔
2066
                    }
1✔
2067

2068
                    /**
2069
                     * {@inheritDoc}
2070
                     */
2071
                    public LazyTypeDescription.GenericTypeToken toToken() {
2072
                        return isParameterized()
1✔
2073
                                ? new LazyTypeDescription.GenericTypeToken.ForParameterizedType(getName(), parameters)
1✔
2074
                                : new LazyTypeDescription.GenericTypeToken.ForRawType(getName());
1✔
2075
                    }
2076

2077
                    /**
2078
                     * {@inheritDoc}
2079
                     */
2080
                    public boolean isParameterized() {
2081
                        return !parameters.isEmpty();
1✔
2082
                    }
2083

2084
                    /**
2085
                     * {@inheritDoc}
2086
                     */
2087
                    public String getName() {
2088
                        return internalName.replace('/', '.');
1✔
2089
                    }
2090
                }
2091

2092
                /**
2093
                 * An incomplete generic type token representing a type with an outer type.
2094
                 */
2095
                @HashCodeAndEqualsPlugin.Enhance
2096
                class ForInnerClass extends AbstractBase {
2097

2098
                    /**
2099
                     * The separator that indicates an inner type.
2100
                     */
2101
                    private static final char INNER_CLASS_SEPARATOR = '$';
2102

2103
                    /**
2104
                     * The internal name of the type.
2105
                     */
2106
                    private final String internalName;
2107

2108
                    /**
2109
                     * The token representing the outer type.
2110
                     */
2111
                    private final IncompleteToken outerTypeToken;
2112

2113
                    /**
2114
                     * Creates a new incomplete token representing a type without an outer type.
2115
                     *
2116
                     * @param internalName   The internal name of the type.
2117
                     * @param outerTypeToken The incomplete token representing the outer type.
2118
                     */
2119
                    public ForInnerClass(String internalName, IncompleteToken outerTypeToken) {
1✔
2120
                        this.internalName = internalName;
1✔
2121
                        this.outerTypeToken = outerTypeToken;
1✔
2122
                    }
1✔
2123

2124
                    /**
2125
                     * {@inheritDoc}
2126
                     */
2127
                    public LazyTypeDescription.GenericTypeToken toToken() {
2128
                        return isParameterized() || outerTypeToken.isParameterized()
1✔
2129
                                ? new LazyTypeDescription.GenericTypeToken.ForParameterizedType.Nested(getName(), parameters, outerTypeToken.toToken())
1✔
2130
                                : new LazyTypeDescription.GenericTypeToken.ForRawType(getName());
×
2131
                    }
2132

2133
                    /**
2134
                     * {@inheritDoc}
2135
                     */
2136
                    public boolean isParameterized() {
2137
                        return !parameters.isEmpty() || !outerTypeToken.isParameterized();
1✔
2138
                    }
2139

2140
                    /**
2141
                     * {@inheritDoc}
2142
                     */
2143
                    public String getName() {
2144
                        return outerTypeToken.getName() + INNER_CLASS_SEPARATOR + internalName.replace('/', '.');
1✔
2145
                    }
2146
                }
2147
            }
2148

2149
            /**
2150
             * A signature visitor for extracting a generic type resolution.
2151
             *
2152
             * @param <T> The type of the resolution this visitor extracts.
2153
             */
2154
            protected abstract static class ForSignature<T extends LazyTypeDescription.GenericTypeToken.Resolution>
2155
                    extends RejectingSignatureVisitor
2156
                    implements GenericTypeRegistrant {
2157

2158
                /**
2159
                 * The resolved type variable tokens.
2160
                 */
2161
                protected final List<LazyTypeDescription.GenericTypeToken.OfFormalTypeVariable> typeVariableTokens;
2162

2163
                /**
2164
                 * The name of the currently constructed type.
2165
                 */
2166
                @MaybeNull
2167
                protected String currentTypeParameter;
2168

2169
                /**
2170
                 * The bounds of the currently constructed type.
2171
                 */
2172
                @UnknownNull
2173
                protected List<LazyTypeDescription.GenericTypeToken> currentBounds;
2174

2175
                /**
2176
                 * Creates a new signature visitor.
2177
                 */
2178
                public ForSignature() {
1✔
2179
                    typeVariableTokens = new ArrayList<LazyTypeDescription.GenericTypeToken.OfFormalTypeVariable>();
1✔
2180
                }
1✔
2181

2182
                /**
2183
                 * Applies an extraction of a generic signature given the supplied visitor.
2184
                 *
2185
                 * @param genericSignature The generic signature to interpret.
2186
                 * @param visitor          The visitor to apply.
2187
                 * @param <S>              The type of the generated resolution.
2188
                 * @return The resolution of the supplied signature.
2189
                 */
2190
                protected static <S extends LazyTypeDescription.GenericTypeToken.Resolution> S extract(String genericSignature, ForSignature<S> visitor) {
2191
                    SignatureReader signatureReader = new SignatureReader(genericSignature);
1✔
2192
                    signatureReader.accept(visitor);
1✔
2193
                    return visitor.resolve();
1✔
2194
                }
2195

2196
                /**
2197
                 * {@inheritDoc}
2198
                 */
2199
                public void visitFormalTypeParameter(String name) {
2200
                    collectTypeParameter();
1✔
2201
                    currentTypeParameter = name;
1✔
2202
                    currentBounds = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2203
                }
1✔
2204

2205
                /**
2206
                 * {@inheritDoc}
2207
                 */
2208
                public SignatureVisitor visitClassBound() {
2209
                    return new GenericTypeExtractor(this);
1✔
2210
                }
2211

2212
                /**
2213
                 * {@inheritDoc}
2214
                 */
2215
                public SignatureVisitor visitInterfaceBound() {
2216
                    return new GenericTypeExtractor(this);
1✔
2217
                }
2218

2219
                /**
2220
                 * {@inheritDoc}
2221
                 */
2222
                public void register(LazyTypeDescription.GenericTypeToken token) {
2223
                    if (currentBounds == null) {
1✔
2224
                        throw new IllegalStateException("Did not expect " + token + " before finding formal parameter");
×
2225
                    }
2226
                    currentBounds.add(token);
1✔
2227
                }
1✔
2228

2229
                /**
2230
                 * Collects the currently constructed type.
2231
                 */
2232
                protected void collectTypeParameter() {
2233
                    if (currentTypeParameter != null) {
1✔
2234
                        typeVariableTokens.add(new LazyTypeDescription.GenericTypeToken.ForTypeVariable.Formal(currentTypeParameter, currentBounds));
1✔
2235
                    }
2236
                }
1✔
2237

2238
                /**
2239
                 * Completes the current resolution.
2240
                 *
2241
                 * @return The resolved generic signature.
2242
                 */
2243
                public abstract T resolve();
2244

2245
                /**
2246
                 * A parser for a generic type signature.
2247
                 */
2248
                protected static class OfType extends ForSignature<LazyTypeDescription.GenericTypeToken.Resolution.ForType> {
2249

2250
                    /**
2251
                     * The interface type's generic signatures.
2252
                     */
2253
                    private final List<LazyTypeDescription.GenericTypeToken> interfaceTypeTokens;
2254

2255
                    /**
2256
                     * The super type's generic signature.
2257
                     */
2258
                    @UnknownNull
2259
                    private LazyTypeDescription.GenericTypeToken superClassToken;
2260

2261
                    /**
2262
                     * Creates a new parser for a type signature.
2263
                     */
2264
                    protected OfType() {
1✔
2265
                        interfaceTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2266
                    }
1✔
2267

2268
                    /**
2269
                     * Extracts a generic type resolution of a type signature.
2270
                     *
2271
                     * @param genericSignature The signature to interpret.
2272
                     * @return The interpreted type signature.
2273
                     */
2274
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForType extract(@MaybeNull String genericSignature) {
2275
                        try {
2276
                            return genericSignature == null
1✔
2277
                                    ? LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE
2278
                                    : ForSignature.extract(genericSignature, new OfType());
1✔
2279
                        } catch (RuntimeException ignored) {
1✔
2280
                            return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
1✔
2281
                        }
2282
                    }
2283

2284
                    /**
2285
                     * {@inheritDoc}
2286
                     */
2287
                    public SignatureVisitor visitSuperclass() {
2288
                        collectTypeParameter();
1✔
2289
                        return new GenericTypeExtractor(new SuperClassRegistrant());
1✔
2290
                    }
2291

2292
                    /**
2293
                     * {@inheritDoc}
2294
                     */
2295
                    public SignatureVisitor visitInterface() {
2296
                        return new GenericTypeExtractor(new InterfaceTypeRegistrant());
1✔
2297
                    }
2298

2299
                    /**
2300
                     * {@inheritDoc}
2301
                     */
2302
                    public LazyTypeDescription.GenericTypeToken.Resolution.ForType resolve() {
2303
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForType.Tokenized(superClassToken, interfaceTypeTokens, typeVariableTokens);
1✔
2304
                    }
2305

2306
                    /**
2307
                     * A registrant for the super type.
2308
                     */
2309
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2310
                    protected class SuperClassRegistrant implements GenericTypeRegistrant {
1✔
2311

2312
                        /**
2313
                         * {@inheritDoc}
2314
                         */
2315
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2316
                            superClassToken = token;
1✔
2317
                        }
1✔
2318
                    }
2319

2320
                    /**
2321
                     * A registrant for the interface types.
2322
                     */
2323
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2324
                    protected class InterfaceTypeRegistrant implements GenericTypeRegistrant {
1✔
2325

2326
                        /**
2327
                         * {@inheritDoc}
2328
                         */
2329
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2330
                            interfaceTypeTokens.add(token);
1✔
2331
                        }
1✔
2332
                    }
2333
                }
2334

2335
                /**
2336
                 * A parser for a generic field signature.
2337
                 */
2338
                protected static class OfField implements GenericTypeRegistrant {
1✔
2339

2340
                    /**
2341
                     * The generic field type.
2342
                     */
2343
                    @UnknownNull
2344
                    private LazyTypeDescription.GenericTypeToken fieldTypeToken;
2345

2346
                    /**
2347
                     * Extracts a generic field resolution of a field signature.
2348
                     *
2349
                     * @param genericSignature The signature to interpret.
2350
                     * @return The interpreted field signature.
2351
                     */
2352
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForField extract(@MaybeNull String genericSignature) {
2353
                        if (genericSignature == null) {
1✔
2354
                            return LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE;
1✔
2355
                        } else {
2356
                            SignatureReader signatureReader = new SignatureReader(genericSignature);
1✔
2357
                            OfField visitor = new OfField();
1✔
2358
                            try {
2359
                                signatureReader.acceptType(new GenericTypeExtractor(visitor));
1✔
2360
                                return visitor.resolve();
1✔
2361
                            } catch (RuntimeException ignored) {
1✔
2362
                                return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
1✔
2363
                            }
2364
                        }
2365
                    }
2366

2367
                    /**
2368
                     * {@inheritDoc}
2369
                     */
2370
                    public void register(LazyTypeDescription.GenericTypeToken token) {
2371
                        fieldTypeToken = token;
1✔
2372
                    }
1✔
2373

2374
                    /**
2375
                     * Completes the current resolution.
2376
                     *
2377
                     * @return The resolved generic signature.
2378
                     */
2379
                    protected LazyTypeDescription.GenericTypeToken.Resolution.ForField resolve() {
2380
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForField.Tokenized(fieldTypeToken);
1✔
2381
                    }
2382
                }
2383

2384
                /**
2385
                 * A parser for a generic method signature.
2386
                 */
2387
                protected static class OfMethod extends ForSignature<LazyTypeDescription.GenericTypeToken.Resolution.ForMethod> {
2388

2389
                    /**
2390
                     * The generic parameter types.
2391
                     */
2392
                    private final List<LazyTypeDescription.GenericTypeToken> parameterTypeTokens;
2393

2394
                    /**
2395
                     * The generic exception types.
2396
                     */
2397
                    private final List<LazyTypeDescription.GenericTypeToken> exceptionTypeTokens;
2398

2399
                    /**
2400
                     * The generic return type.
2401
                     */
2402
                    @UnknownNull
2403
                    private LazyTypeDescription.GenericTypeToken returnTypeToken;
2404

2405
                    /**
2406
                     * Creates a parser for a generic method signature.
2407
                     */
2408
                    public OfMethod() {
1✔
2409
                        parameterTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2410
                        exceptionTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2411
                    }
1✔
2412

2413
                    /**
2414
                     * Extracts a generic method resolution of a method signature.
2415
                     *
2416
                     * @param genericSignature The signature to interpret.
2417
                     * @return The interpreted method signature.
2418
                     */
2419
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForMethod extract(@MaybeNull String genericSignature) {
2420
                        try {
2421
                            return genericSignature == null
1✔
2422
                                    ? LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE
2423
                                    : ForSignature.extract(genericSignature, new OfMethod());
1✔
2424
                        } catch (RuntimeException ignored) {
1✔
2425
                            return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
1✔
2426
                        }
2427
                    }
2428

2429
                    /**
2430
                     * {@inheritDoc}
2431
                     */
2432
                    public SignatureVisitor visitParameterType() {
2433
                        return new GenericTypeExtractor(new ParameterTypeRegistrant());
1✔
2434
                    }
2435

2436
                    /**
2437
                     * {@inheritDoc}
2438
                     */
2439
                    public SignatureVisitor visitReturnType() {
2440
                        collectTypeParameter();
1✔
2441
                        return new GenericTypeExtractor(new ReturnTypeTypeRegistrant());
1✔
2442
                    }
2443

2444
                    /**
2445
                     * {@inheritDoc}
2446
                     */
2447
                    public SignatureVisitor visitExceptionType() {
2448
                        return new GenericTypeExtractor(new ExceptionTypeRegistrant());
1✔
2449
                    }
2450

2451
                    /**
2452
                     * {@inheritDoc}
2453
                     */
2454
                    public LazyTypeDescription.GenericTypeToken.Resolution.ForMethod resolve() {
2455
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForMethod.Tokenized(returnTypeToken,
1✔
2456
                                parameterTypeTokens,
2457
                                exceptionTypeTokens,
2458
                                typeVariableTokens);
2459
                    }
2460

2461
                    /**
2462
                     * A registrant for a parameter type.
2463
                     */
2464
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2465
                    protected class ParameterTypeRegistrant implements GenericTypeRegistrant {
1✔
2466

2467
                        /**
2468
                         * {@inheritDoc}
2469
                         */
2470
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2471
                            parameterTypeTokens.add(token);
1✔
2472
                        }
1✔
2473
                    }
2474

2475
                    /**
2476
                     * A registrant for a return type.
2477
                     */
2478
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2479
                    protected class ReturnTypeTypeRegistrant implements GenericTypeRegistrant {
1✔
2480

2481
                        /**
2482
                         * {@inheritDoc}
2483
                         */
2484
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2485
                            returnTypeToken = token;
1✔
2486
                        }
1✔
2487
                    }
2488

2489
                    /**
2490
                     * A registrant for an exception type.
2491
                     */
2492
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2493
                    protected class ExceptionTypeRegistrant implements GenericTypeRegistrant {
1✔
2494

2495
                        /**
2496
                         * {@inheritDoc}
2497
                         */
2498
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2499
                            exceptionTypeTokens.add(token);
1✔
2500
                        }
1✔
2501
                    }
2502
                }
2503

2504
                /**
2505
                 * A parser for a generic field signature.
2506
                 */
2507
                protected static class OfRecordComponent implements GenericTypeRegistrant {
×
2508

2509
                    /**
2510
                     * The generic field type.
2511
                     */
2512
                    @UnknownNull
2513
                    private LazyTypeDescription.GenericTypeToken recordComponentType;
2514

2515
                    /**
2516
                     * Extracts a generic field resolution of a field signature.
2517
                     *
2518
                     * @param genericSignature The signature to interpret.
2519
                     * @return The interpreted field signature.
2520
                     */
2521
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent extract(@MaybeNull String genericSignature) {
2522
                        if (genericSignature == null) {
×
2523
                            return LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE;
×
2524
                        } else {
2525
                            SignatureReader signatureReader = new SignatureReader(genericSignature);
×
2526
                            OfRecordComponent visitor = new OfRecordComponent();
×
2527
                            try {
2528
                                signatureReader.acceptType(new GenericTypeExtractor(visitor));
×
2529
                                return visitor.resolve();
×
2530
                            } catch (RuntimeException ignored) {
×
2531
                                return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
×
2532
                            }
2533
                        }
2534
                    }
2535

2536
                    /**
2537
                     * {@inheritDoc}
2538
                     */
2539
                    public void register(LazyTypeDescription.GenericTypeToken token) {
2540
                        recordComponentType = token;
×
2541
                    }
×
2542

2543
                    /**
2544
                     * Completes the current resolution.
2545
                     *
2546
                     * @return The resolved generic signature.
2547
                     */
2548
                    protected LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent resolve() {
2549
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent.Tokenized(recordComponentType);
×
2550
                    }
2551
                }
2552
            }
2553
        }
2554

2555
        /**
2556
         * A type description that looks up any referenced {@link net.bytebuddy.description.ByteCodeElement} or
2557
         * {@link AnnotationDescription} by querying a type pool at lookup time.
2558
         */
2559
        protected static class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType {
2560

2561
            /**
2562
             * Indicates that a type does not exist and does therefore not have a name.
2563
             */
2564
            @AlwaysNull
2565
            private static final String NO_TYPE = null;
1✔
2566

2567
            /**
2568
             * The type pool to be used for looking up linked types.
2569
             */
2570
            private final TypePool typePool;
2571

2572
            /**
2573
             * The actual modifiers of this type.
2574
             */
2575
            private final int actualModifiers;
2576

2577
            /**
2578
             * The modifiers of this type.
2579
             */
2580
            private final int modifiers;
2581

2582
            /**
2583
             * The binary name of this type.
2584
             */
2585
            private final String name;
2586

2587
            /**
2588
             * The type's super type's descriptor or {@code null} if this type does not define a super type.
2589
             */
2590
            @MaybeNull
2591
            private final String superClassDescriptor;
2592

2593
            /**
2594
             * The type's generic signature as found in the class file or {@code null} if the type is not generic.
2595
             */
2596
            @MaybeNull
2597
            private final String genericSignature;
2598

2599
            /**
2600
             * The resolution of this type's generic type.
2601
             */
2602
            private final GenericTypeToken.Resolution.ForType signatureResolution;
2603

2604
            /**
2605
             * The descriptor of this type's interfaces.
2606
             */
2607
            private final List<String> interfaceTypeDescriptors;
2608

2609
            /**
2610
             * A definition of this type's containment within another type or method.
2611
             */
2612
            private final TypeContainment typeContainment;
2613

2614
            /**
2615
             * The binary name of this type's declaring type or {@code null} if no such type exists.
2616
             */
2617
            @MaybeNull
2618
            private final String declaringTypeName;
2619

2620
            /**
2621
             * A list of descriptors representing the types that are declared by this type.
2622
             */
2623
            private final List<String> declaredTypes;
2624

2625
            /**
2626
             * {@code true} if this type is an anonymous type.
2627
             */
2628
            private final boolean anonymousType;
2629

2630
            /**
2631
             * The binary name of the nest host or {@code null} if no nest host was specified.
2632
             */
2633
            @MaybeNull
2634
            private final String nestHost;
2635

2636
            /**
2637
             * A list of binary names of all specified nest members.
2638
             */
2639
            private final List<String> nestMembers;
2640

2641
            /**
2642
             * A mapping of the super class's annotation tokens.
2643
             */
2644
            private final Map<String, List<AnnotationToken>> superClassAnnotationTokens;
2645

2646
            /**
2647
             * A mapping of type annotations for this type's interface types by their indices.
2648
             */
2649
            private final Map<Integer, Map<String, List<AnnotationToken>>> interfaceAnnotationTokens;
2650

2651
            /**
2652
             * A mapping of type annotations of the type variables' type annotations by their indices.
2653
             */
2654
            private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
2655

2656
            /**
2657
             * A mapping of type annotations of the type variables' bounds' type annotations by their indices and each variable's index.
2658
             */
2659
            private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundsAnnotationTokens;
2660

2661
            /**
2662
             * A list of tokens that represent the annotations of this type.
2663
             */
2664
            private final List<AnnotationToken> annotationTokens;
2665

2666
            /**
2667
             * A list of field tokens describing the field's of this type.
2668
             */
2669
            private final List<FieldToken> fieldTokens;
2670

2671
            /**
2672
             * A list of method tokens describing the method's of this type.
2673
             */
2674
            private final List<MethodToken> methodTokens;
2675

2676
            /**
2677
             * A list of record component tokens describing the record components of this type.
2678
             */
2679
            private final List<RecordComponentToken> recordComponentTokens;
2680

2681
            /**
2682
             * A list of internal names of permitted subclasses.
2683
             */
2684
            private final List<String> permittedSubclasses;
2685

2686
            /**
2687
             * The type's class file version.
2688
             */
2689
            private final ClassFileVersion classFileVersion;
2690

2691
            /**
2692
             * Creates a new lazy type description.
2693
             *
2694
             * @param typePool                           The type pool to be used for looking up linked types.
2695
             * @param actualModifiers                    The actual modifiers of this type.
2696
             * @param modifiers                          The modifiers of this type.
2697
             * @param name                               The binary name of this type.
2698
             * @param superClassInternalName             The internal name of this type's super type or {@code null} if no such super type is defined.
2699
             * @param interfaceInternalName              An array of this type's interfaces or {@code null} if this type does not define any interfaces.
2700
             * @param genericSignature                   The type's generic signature as found in the class file or {@code null} if the type is not generic.
2701
             * @param typeContainment                    A definition of this type's containment within another type or method.
2702
             * @param declaringTypeInternalName          The internal name of this type's declaring type or {@code null} if no such type exists.
2703
             * @param declaredTypes                      A list of descriptors representing the types that are declared by this type.
2704
             * @param anonymousType                      {@code true} if this type is an anonymous type.
2705
             * @param nestHostInternalName               The internal name of the nest host or {@code null} if no nest host was specified.
2706
             * @param nestMemberInternalNames            A list of internal names of the nest members.
2707
             * @param superClassAnnotationTokens         A mapping of the super class's annotation tokens.
2708
             * @param interfaceAnnotationTokens          A mapping of type annotations for this type's interface types by their indices.
2709
             * @param typeVariableAnnotationTokens       A mapping of type annotations of the type variables' type annotations by their indices.
2710
             * @param typeVariableBoundsAnnotationTokens A mapping of type annotations of the type variables' bounds' type annotations by their indices
2711
             *                                           and each variable's index.
2712
             * @param annotationTokens                   A list of tokens that represent the annotations of this type.
2713
             * @param fieldTokens                        A list of field tokens describing the field's of this type.
2714
             * @param methodTokens                       A list of method tokens describing the method's of this type.
2715
             * @param recordComponentTokens              A list of record component tokens describing the record components of this type.
2716
             * @param permittedSubclasses                A list of internal names of permitted subclasses.
2717
             * @param classFileVersion                   The type's class file version.
2718
             */
2719
            protected LazyTypeDescription(TypePool typePool,
2720
                                          int actualModifiers,
2721
                                          int modifiers,
2722
                                          String name,
2723
                                          @MaybeNull String superClassInternalName,
2724
                                          @MaybeNull String[] interfaceInternalName,
2725
                                          @MaybeNull String genericSignature,
2726
                                          TypeContainment typeContainment,
2727
                                          @MaybeNull String declaringTypeInternalName,
2728
                                          List<String> declaredTypes,
2729
                                          boolean anonymousType,
2730
                                          @MaybeNull String nestHostInternalName,
2731
                                          List<String> nestMemberInternalNames,
2732
                                          Map<String, List<AnnotationToken>> superClassAnnotationTokens,
2733
                                          Map<Integer, Map<String, List<AnnotationToken>>> interfaceAnnotationTokens,
2734
                                          Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
2735
                                          Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundsAnnotationTokens,
2736
                                          List<AnnotationToken> annotationTokens,
2737
                                          List<FieldToken> fieldTokens,
2738
                                          List<MethodToken> methodTokens,
2739
                                          List<RecordComponentToken> recordComponentTokens,
2740
                                          List<String> permittedSubclasses,
2741
                                          ClassFileVersion classFileVersion) {
1✔
2742
                this.typePool = typePool;
1✔
2743
                this.actualModifiers = actualModifiers & ~Opcodes.ACC_SUPER;
1✔
2744
                this.modifiers = modifiers & ~(Opcodes.ACC_SUPER | Opcodes.ACC_DEPRECATED);
1✔
2745
                this.name = Type.getObjectType(name).getClassName();
1✔
2746
                this.superClassDescriptor = superClassInternalName == null
1✔
2747
                        ? NO_TYPE
2748
                        : Type.getObjectType(superClassInternalName).getDescriptor();
1✔
2749
                this.genericSignature = genericSignature;
1✔
2750
                signatureResolution = RAW_TYPES
1✔
2751
                        ? GenericTypeToken.Resolution.Raw.INSTANCE
2752
                        : GenericTypeExtractor.ForSignature.OfType.extract(genericSignature);
1✔
2753
                if (interfaceInternalName == null) {
1✔
2754
                    interfaceTypeDescriptors = Collections.emptyList();
×
2755
                } else {
2756
                    interfaceTypeDescriptors = new ArrayList<String>(interfaceInternalName.length);
1✔
2757
                    for (String internalName : interfaceInternalName) {
1✔
2758
                        interfaceTypeDescriptors.add(Type.getObjectType(internalName).getDescriptor());
1✔
2759
                    }
2760
                }
2761
                this.typeContainment = typeContainment;
1✔
2762
                declaringTypeName = declaringTypeInternalName == null
1✔
2763
                        ? NO_TYPE
2764
                        : declaringTypeInternalName.replace('/', '.');
1✔
2765
                this.declaredTypes = declaredTypes;
1✔
2766
                this.anonymousType = anonymousType;
1✔
2767
                nestHost = nestHostInternalName == null
1✔
2768
                        ? NO_TYPE
2769
                        : Type.getObjectType(nestHostInternalName).getClassName();
1✔
2770
                nestMembers = new ArrayList<String>(nestMemberInternalNames.size());
1✔
2771
                for (String nestMemberInternalName : nestMemberInternalNames) {
1✔
2772
                    nestMembers.add(Type.getObjectType(nestMemberInternalName).getClassName());
×
2773
                }
×
2774
                this.superClassAnnotationTokens = superClassAnnotationTokens;
1✔
2775
                this.interfaceAnnotationTokens = interfaceAnnotationTokens;
1✔
2776
                this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
1✔
2777
                this.typeVariableBoundsAnnotationTokens = typeVariableBoundsAnnotationTokens;
1✔
2778
                this.annotationTokens = annotationTokens;
1✔
2779
                this.fieldTokens = fieldTokens;
1✔
2780
                this.methodTokens = methodTokens;
1✔
2781
                this.recordComponentTokens = recordComponentTokens;
1✔
2782
                this.permittedSubclasses = new ArrayList<String>(permittedSubclasses.size());
1✔
2783
                for (String internalName : permittedSubclasses) {
1✔
2784
                    this.permittedSubclasses.add(Type.getObjectType(internalName).getDescriptor());
×
2785
                }
×
2786
                this.classFileVersion = classFileVersion;
1✔
2787
            }
1✔
2788

2789
            /**
2790
             * {@inheritDoc}
2791
             */
2792
            @MaybeNull
2793
            public Generic getSuperClass() {
2794
                return superClassDescriptor == null || isInterface()
1✔
2795
                        ? Generic.UNDEFINED
2796
                        : signatureResolution.resolveSuperClass(superClassDescriptor, typePool, superClassAnnotationTokens, this);
1✔
2797
            }
2798

2799
            /**
2800
             * {@inheritDoc}
2801
             */
2802
            public TypeList.Generic getInterfaces() {
2803
                return signatureResolution.resolveInterfaceTypes(interfaceTypeDescriptors, typePool, interfaceAnnotationTokens, this);
1✔
2804
            }
2805

2806
            /**
2807
             * {@inheritDoc}
2808
             */
2809
            @MaybeNull
2810
            public MethodDescription.InDefinedShape getEnclosingMethod() {
2811
                return typeContainment.getEnclosingMethod(typePool);
1✔
2812
            }
2813

2814
            /**
2815
             * {@inheritDoc}
2816
             */
2817
            @MaybeNull
2818
            public TypeDescription getEnclosingType() {
2819
                return typeContainment.getEnclosingType(typePool);
1✔
2820
            }
2821

2822
            /**
2823
             * {@inheritDoc}
2824
             */
2825
            public TypeList getDeclaredTypes() {
2826
                return new LazyTypeList(typePool, declaredTypes);
1✔
2827
            }
2828

2829
            /**
2830
             * {@inheritDoc}
2831
             */
2832
            public boolean isAnonymousType() {
2833
                return anonymousType;
1✔
2834
            }
2835

2836
            /**
2837
             * {@inheritDoc}
2838
             */
2839
            public boolean isLocalType() {
2840
                return !anonymousType && typeContainment.isLocalType();
1✔
2841
            }
2842

2843
            /**
2844
             * {@inheritDoc}
2845
             */
2846
            public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
2847
                return new FieldTokenList();
1✔
2848
            }
2849

2850
            /**
2851
             * {@inheritDoc}
2852
             */
2853
            public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
2854
                return new MethodTokenList();
1✔
2855
            }
2856

2857
            /**
2858
             * {@inheritDoc}
2859
             */
2860
            @MaybeNull
2861
            public PackageDescription getPackage() {
2862
                String name = getName();
1✔
2863
                int index = name.lastIndexOf('.');
1✔
2864
                return new LazyPackageDescription(typePool, index == -1
1✔
2865
                        ? EMPTY_NAME
2866
                        : name.substring(0, index));
1✔
2867
            }
2868

2869
            /**
2870
             * {@inheritDoc}
2871
             */
2872
            public String getName() {
2873
                return name;
1✔
2874
            }
2875

2876
            /**
2877
             * {@inheritDoc}
2878
             */
2879
            @MaybeNull
2880
            public TypeDescription getDeclaringType() {
2881
                return declaringTypeName == null
1✔
2882
                        ? TypeDescription.UNDEFINED
2883
                        : typePool.describe(declaringTypeName).resolve();
1✔
2884
            }
2885

2886
            /**
2887
             * {@inheritDoc}
2888
             */
2889
            public int getModifiers() {
2890
                return modifiers;
1✔
2891
            }
2892

2893
            /**
2894
             * {@inheritDoc}
2895
             */
2896
            public int getActualModifiers(boolean superFlag) {
2897
                return superFlag ? (actualModifiers | Opcodes.ACC_SUPER) : actualModifiers;
1✔
2898
            }
2899

2900
            /**
2901
             * {@inheritDoc}
2902
             */
2903
            public TypeDescription getNestHost() {
2904
                return nestHost == null
1✔
2905
                        ? this
2906
                        : typePool.describe(nestHost).resolve();
×
2907
            }
2908

2909
            /**
2910
             * {@inheritDoc}
2911
             */
2912
            public TypeList getNestMembers() {
2913
                return nestHost == null
1✔
2914
                        ? new LazyNestMemberList(this, typePool, nestMembers)
2915
                        : typePool.describe(nestHost).resolve().getNestMembers();
×
2916
            }
2917

2918
            /**
2919
             * {@inheritDoc}
2920
             */
2921
            public AnnotationList getDeclaredAnnotations() {
2922
                return LazyAnnotationDescription.asList(typePool, annotationTokens);
1✔
2923
            }
2924

2925
            /**
2926
             * {@inheritDoc}
2927
             */
2928
            public TypeList.Generic getTypeVariables() {
2929
                return signatureResolution.resolveTypeVariables(typePool, this, typeVariableAnnotationTokens, typeVariableBoundsAnnotationTokens);
1✔
2930
            }
2931

2932
            @Override
2933
            @MaybeNull
2934
            public String getGenericSignature() {
2935
                return genericSignature;
1✔
2936
            }
2937

2938
            /**
2939
             * {@inheritDoc}
2940
             */
2941
            public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
2942
                return new RecordComponentTokenList();
1✔
2943
            }
2944

2945
            /**
2946
             * {@inheritDoc}
2947
             */
2948
            public boolean isRecord() {
2949
                return (actualModifiers & Opcodes.ACC_RECORD) != 0 && JavaType.RECORD.getTypeStub().getDescriptor().equals(superClassDescriptor);
1✔
2950
            }
2951

2952
            @Override
2953
            public boolean isSealed() {
2954
                return !permittedSubclasses.isEmpty();
1✔
2955
            }
2956

2957
            /**
2958
             * {@inheritDoc}
2959
             */
2960
            public TypeList getPermittedSubtypes() {
2961
                return new LazyTypeList(typePool, permittedSubclasses);
1✔
2962
            }
2963

2964
            @Override
2965
            public ClassFileVersion getClassFileVersion() {
2966
                return classFileVersion;
×
2967
            }
2968

2969
            /**
2970
             * A list of field tokens representing each entry as a field description.
2971
             */
2972
            protected class FieldTokenList extends FieldList.AbstractBase<FieldDescription.InDefinedShape> {
1✔
2973

2974
                /**
2975
                 * {@inheritDoc}
2976
                 */
2977
                public FieldDescription.InDefinedShape get(int index) {
2978
                    return fieldTokens.get(index).toFieldDescription(LazyTypeDescription.this);
1✔
2979
                }
2980

2981
                /**
2982
                 * {@inheritDoc}
2983
                 */
2984
                public int size() {
2985
                    return fieldTokens.size();
1✔
2986
                }
2987
            }
2988

2989
            /**
2990
             * A list of method tokens representing each entry as a method description.
2991
             */
2992
            protected class MethodTokenList extends MethodList.AbstractBase<MethodDescription.InDefinedShape> {
1✔
2993

2994
                /**
2995
                 * {@inheritDoc}
2996
                 */
2997
                public MethodDescription.InDefinedShape get(int index) {
2998
                    return methodTokens.get(index).toMethodDescription(LazyTypeDescription.this);
1✔
2999
                }
3000

3001
                /**
3002
                 * {@inheritDoc}
3003
                 */
3004
                public int size() {
3005
                    return methodTokens.size();
1✔
3006
                }
3007
            }
3008

3009
            /**
3010
             * A list of record component tokens representing each record component as a description.
3011
             */
3012
            protected class RecordComponentTokenList extends RecordComponentList.AbstractBase<RecordComponentDescription.InDefinedShape> {
1✔
3013

3014
                /**
3015
                 * {@inheritDoc}
3016
                 */
3017
                public RecordComponentDescription.InDefinedShape get(int index) {
3018
                    return recordComponentTokens.get(index).toRecordComponentDescription(LazyTypeDescription.this);
×
3019
                }
3020

3021
                /**
3022
                 * {@inheritDoc}
3023
                 */
3024
                public int size() {
3025
                    return recordComponentTokens.size();
1✔
3026
                }
3027
            }
3028

3029
            /**
3030
             * A declaration context encapsulates information about whether a type was declared within another type
3031
             * or within a method of another type.
3032
             */
3033
            protected interface TypeContainment {
3034

3035
                /**
3036
                 * Returns the enclosing method or {@code null} if no such method exists.
3037
                 *
3038
                 * @param typePool The type pool to be used for looking up linked types.
3039
                 * @return A method description describing the linked type or {@code null}.
3040
                 */
3041
                @MaybeNull
3042
                MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool);
3043

3044
                /**
3045
                 * Returns the enclosing type or {@code null} if no such type exists.
3046
                 *
3047
                 * @param typePool The type pool to be used for looking up linked types.
3048
                 * @return A type description describing the linked type or {@code null}.
3049
                 */
3050
                @MaybeNull
3051
                TypeDescription getEnclosingType(TypePool typePool);
3052

3053
                /**
3054
                 * Returns {@code true} if the type is self-contained.
3055
                 *
3056
                 * @return {@code true} if the type is self-contained.
3057
                 */
3058
                boolean isSelfContained();
3059

3060
                /**
3061
                 * Returns {@code true} if the type is a local type unless it is an anonymous type.
3062
                 *
3063
                 * @return {@code true} if the type is a local type unless it is an anonymous type
3064
                 */
3065
                boolean isLocalType();
3066

3067
                /**
3068
                 * Describes a type that is not contained within another type, a method or a constructor.
3069
                 */
3070
                enum SelfContained implements TypeContainment {
1✔
3071

3072
                    /**
3073
                     * The singleton instance.
3074
                     */
3075
                    INSTANCE;
1✔
3076

3077
                    /**
3078
                     * {@inheritDoc}
3079
                     */
3080
                    @MaybeNull
3081
                    public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
3082
                        return MethodDescription.UNDEFINED;
1✔
3083
                    }
3084

3085
                    /**
3086
                     * {@inheritDoc}
3087
                     */
3088
                    @MaybeNull
3089
                    public TypeDescription getEnclosingType(TypePool typePool) {
3090
                        return TypeDescription.UNDEFINED;
1✔
3091
                    }
3092

3093
                    /**
3094
                     * {@inheritDoc}
3095
                     */
3096
                    public boolean isSelfContained() {
3097
                        return true;
1✔
3098
                    }
3099

3100
                    /**
3101
                     * {@inheritDoc}
3102
                     */
3103
                    public boolean isLocalType() {
3104
                        return false;
1✔
3105
                    }
3106
                }
3107

3108
                /**
3109
                 * Describes a type that is contained within another type.
3110
                 */
3111
                @HashCodeAndEqualsPlugin.Enhance
3112
                class WithinType implements TypeContainment {
3113

3114
                    /**
3115
                     * The type's binary name.
3116
                     */
3117
                    private final String name;
3118

3119
                    /**
3120
                     * {@code true} if the type is a local type unless it is an anonymous type.
3121
                     */
3122
                    private final boolean localType;
3123

3124
                    /**
3125
                     * Creates a new type containment for a type that is declared within another type.
3126
                     *
3127
                     * @param internalName The type's internal name.
3128
                     * @param localType    {@code true} if the type is a local type unless it is an anonymous type.
3129
                     */
3130
                    protected WithinType(String internalName, boolean localType) {
1✔
3131
                        name = internalName.replace('/', '.');
1✔
3132
                        this.localType = localType;
1✔
3133
                    }
1✔
3134

3135
                    /**
3136
                     * {@inheritDoc}
3137
                     */
3138
                    @MaybeNull
3139
                    public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
3140
                        return MethodDescription.UNDEFINED;
1✔
3141
                    }
3142

3143
                    /**
3144
                     * {@inheritDoc}
3145
                     */
3146
                    public TypeDescription getEnclosingType(TypePool typePool) {
3147
                        return typePool.describe(name).resolve();
1✔
3148
                    }
3149

3150
                    /**
3151
                     * {@inheritDoc}
3152
                     */
3153
                    public boolean isSelfContained() {
3154
                        return false;
1✔
3155
                    }
3156

3157
                    /**
3158
                     * {@inheritDoc}
3159
                     */
3160
                    public boolean isLocalType() {
3161
                        return localType;
1✔
3162
                    }
3163
                }
3164

3165
                /**
3166
                 * Describes a type that is contained within a method or constructor.
3167
                 */
3168
                @HashCodeAndEqualsPlugin.Enhance
3169
                class WithinMethod implements TypeContainment {
3170

3171
                    /**
3172
                     * The method's declaring type's internal name.
3173
                     */
3174
                    private final String name;
3175

3176
                    /**
3177
                     * The method's internal name.
3178
                     */
3179
                    private final String methodName;
3180

3181
                    /**
3182
                     * The method's descriptor.
3183
                     */
3184
                    private final String methodDescriptor;
3185

3186
                    /**
3187
                     * Creates a new type containment for a type that is declared within a method.
3188
                     *
3189
                     * @param internalName     The method's declaring type's internal name.
3190
                     * @param methodName       The method's internal name.
3191
                     * @param methodDescriptor The method's descriptor.
3192
                     */
3193
                    protected WithinMethod(String internalName, String methodName, String methodDescriptor) {
1✔
3194
                        name = internalName.replace('/', '.');
1✔
3195
                        this.methodName = methodName;
1✔
3196
                        this.methodDescriptor = methodDescriptor;
1✔
3197
                    }
1✔
3198

3199
                    /**
3200
                     * {@inheritDoc}
3201
                     */
3202
                    public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
3203
                        TypeDescription enclosingType = getEnclosingType(typePool);
1✔
3204
                        if (enclosingType == null) {
1✔
3205
                            throw new IllegalStateException("Could not resolve enclosing type " + name);
×
3206
                        }
3207
                        MethodList<MethodDescription.InDefinedShape> enclosingMethod = enclosingType.getDeclaredMethods()
1✔
3208
                                .filter(hasMethodName(methodName).and(hasDescriptor(methodDescriptor)));
1✔
3209
                        if (enclosingMethod.isEmpty()) {
1✔
3210
                            throw new IllegalStateException(methodName + methodDescriptor + " not declared by " + enclosingType);
×
3211
                        }
3212
                        return enclosingMethod.getOnly();
1✔
3213
                    }
3214

3215
                    /**
3216
                     * {@inheritDoc}
3217
                     */
3218
                    public TypeDescription getEnclosingType(TypePool typePool) {
3219
                        return typePool.describe(name).resolve();
1✔
3220
                    }
3221

3222
                    /**
3223
                     * {@inheritDoc}
3224
                     */
3225
                    public boolean isSelfContained() {
3226
                        return false;
1✔
3227
                    }
3228

3229
                    /**
3230
                     * {@inheritDoc}
3231
                     */
3232
                    public boolean isLocalType() {
3233
                        return true;
1✔
3234
                    }
3235
                }
3236
            }
3237

3238
            /**
3239
             * A token that represents a generic Java type.
3240
             */
3241
            protected interface GenericTypeToken {
3242

3243
                /**
3244
                 * Represents an empty type path.
3245
                 */
3246
                String EMPTY_TYPE_PATH = "";
3247

3248
                /**
3249
                 * Represents a step to a component type within a type path.
3250
                 */
3251
                char COMPONENT_TYPE_PATH = '[';
3252

3253
                /**
3254
                 * Represents a wildcard type step within a type path.
3255
                 */
3256
                char WILDCARD_TYPE_PATH = '*';
3257

3258
                /**
3259
                 * Represents a (reversed) step to an inner class within a type path.
3260
                 */
3261
                char INNER_CLASS_PATH = '.';
3262

3263
                /**
3264
                 * Represents an index type delimiter within a type path.
3265
                 */
3266
                char INDEXED_TYPE_DELIMITER = ';';
3267

3268
                /**
3269
                 * Transforms this token into a generic type representation.
3270
                 *
3271
                 * @param typePool           The type pool to be used for locating non-generic type descriptions.
3272
                 * @param typeVariableSource The type variable source.
3273
                 * @param typePath           The type path of the resolved generic type.
3274
                 * @param annotationTokens   A mapping of the type's annotation tokens by their type path.
3275
                 * @return A description of the represented generic type.
3276
                 */
3277
                Generic toGenericType(TypePool typePool,
3278
                                      TypeVariableSource typeVariableSource,
3279
                                      String typePath,
3280
                                      Map<String, List<AnnotationToken>> annotationTokens);
3281

3282
                /**
3283
                 * Determines if a generic type tokens represents a primary bound of a type variable. This method must only be invoked on types
3284
                 * that represent a {@link Sort#NON_GENERIC},
3285
                 * {@link Sort#PARAMETERIZED} or {@link Sort#VARIABLE}.
3286
                 *
3287
                 * @param typePool The type pool to use.
3288
                 * @return {@code true} if this token represents a primary bound.
3289
                 */
3290
                boolean isPrimaryBound(TypePool typePool);
3291

3292
                /**
3293
                 * Returns the type path prefix that needs to be appended to the existing type path before any further navigation on the parameterized
3294
                 * type. This method must only be called on type tokens that represent parameterized type
3295
                 *
3296
                 * @return A type path segment that needs to be appended to the base type path before any further navigation on the parameterized type.
3297
                 */
3298
                String getTypePathPrefix();
3299

3300
                /**
3301
                 * Represents a generic type token for a formal type variable.
3302
                 */
3303
                interface OfFormalTypeVariable {
3304

3305
                    /**
3306
                     * Transforms this token into a generic type representation.
3307
                     *
3308
                     * @param typePool                 The type pool to be used for locating non-generic type descriptions.
3309
                     * @param typeVariableSource       The type variable source.
3310
                     * @param annotationTokens         A mapping of the type variables' type annotations.
3311
                     * @param boundaryAnnotationTokens A mapping of the type variables' bounds' type annotation by their bound index.
3312
                     * @return A generic type representation of this formal type variable.
3313
                     */
3314
                    Generic toGenericType(TypePool typePool,
3315
                                          TypeVariableSource typeVariableSource,
3316
                                          Map<String, List<AnnotationToken>> annotationTokens,
3317
                                          Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens);
3318
                }
3319

3320
                /**
3321
                 * A generic type token that represents a primitive type.
3322
                 */
3323
                enum ForPrimitiveType implements GenericTypeToken {
1✔
3324

3325
                    /**
3326
                     * The generic type token describing the {@code boolean} type.
3327
                     */
3328
                    BOOLEAN(boolean.class),
1✔
3329

3330
                    /**
3331
                     * The generic type token describing the {@code byte} type.
3332
                     */
3333
                    BYTE(byte.class),
1✔
3334

3335
                    /**
3336
                     * The generic type token describing the {@code short} type.
3337
                     */
3338
                    SHORT(short.class),
1✔
3339

3340
                    /**
3341
                     * The generic type token describing the {@code char} type.
3342
                     */
3343
                    CHAR(char.class),
1✔
3344

3345
                    /**
3346
                     * The generic type token describing the {@code int} type.
3347
                     */
3348
                    INTEGER(int.class),
1✔
3349

3350
                    /**
3351
                     * The generic type token describing the {@code long} type.
3352
                     */
3353
                    LONG(long.class),
1✔
3354

3355
                    /**
3356
                     * The generic type token describing the {@code float} type.
3357
                     */
3358
                    FLOAT(float.class),
1✔
3359

3360
                    /**
3361
                     * The generic type token describing the {@code double} type.
3362
                     */
3363
                    DOUBLE(double.class),
1✔
3364

3365
                    /**
3366
                     * The generic type token describing the {@code void} type.
3367
                     */
3368
                    VOID(void.class);
1✔
3369

3370
                    /**
3371
                     * A description of this primitive type token.
3372
                     */
3373
                    private final TypeDescription typeDescription;
3374

3375
                    /**
3376
                     * Creates a new primitive type token.
3377
                     *
3378
                     * @param type The loaded type representing this primitive.
3379
                     */
3380
                    ForPrimitiveType(Class<?> type) {
1✔
3381
                        typeDescription = ForLoadedType.of(type);
1✔
3382
                    }
1✔
3383

3384
                    /**
3385
                     * Resolves a generic type token of a primitive type.
3386
                     *
3387
                     * @param descriptor The descriptor of the primitive type.
3388
                     * @return The corresponding generic type token.
3389
                     */
3390
                    public static GenericTypeToken of(char descriptor) {
3391
                        switch (descriptor) {
1✔
3392
                            case 'V':
3393
                                return VOID;
1✔
3394
                            case 'Z':
3395
                                return BOOLEAN;
1✔
3396
                            case 'B':
3397
                                return BYTE;
1✔
3398
                            case 'S':
3399
                                return SHORT;
1✔
3400
                            case 'C':
3401
                                return CHAR;
1✔
3402
                            case 'I':
3403
                                return INTEGER;
1✔
3404
                            case 'J':
3405
                                return LONG;
1✔
3406
                            case 'F':
3407
                                return FLOAT;
1✔
3408
                            case 'D':
3409
                                return DOUBLE;
1✔
3410
                            default:
3411
                                throw new IllegalArgumentException("Not a valid primitive type descriptor: " + descriptor);
×
3412
                        }
3413
                    }
3414

3415
                    /**
3416
                     * {@inheritDoc}
3417
                     */
3418
                    public Generic toGenericType(TypePool typePool,
3419
                                                 TypeVariableSource typeVariableSource,
3420
                                                 String typePath,
3421
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
3422
                        return new LazyPrimitiveType(typePool,
1✔
3423
                                typePath,
3424
                                annotationTokens,
3425
                                typeDescription);
3426
                    }
3427

3428
                    /**
3429
                     * {@inheritDoc}
3430
                     */
3431
                    public boolean isPrimaryBound(TypePool typePool) {
3432
                        throw new IllegalStateException("A primitive type cannot be a type variable bound: " + this);
1✔
3433
                    }
3434

3435
                    /**
3436
                     * {@inheritDoc}
3437
                     */
3438
                    public String getTypePathPrefix() {
3439
                        throw new IllegalStateException("A primitive type cannot be the owner of a nested type: " + this);
1✔
3440
                    }
3441

3442
                    /**
3443
                     * A representation of a lazy primitive type.
3444
                     */
3445
                    protected static class LazyPrimitiveType extends Generic.OfNonGenericType {
3446

3447
                        /**
3448
                         * The type pool to use.
3449
                         */
3450
                        private final TypePool typePool;
3451

3452
                        /**
3453
                         * This type's type path.
3454
                         */
3455
                        private final String typePath;
3456

3457
                        /**
3458
                         * This type's type annotation tokens.
3459
                         */
3460
                        private final Map<String, List<AnnotationToken>> annotationTokens;
3461

3462
                        /**
3463
                         * The represented type's description.
3464
                         */
3465
                        private final TypeDescription typeDescription;
3466

3467
                        /**
3468
                         * Creates a new lazy primitive type.
3469
                         *
3470
                         * @param typePool         The type pool to use.
3471
                         * @param typePath         This type's type path.
3472
                         * @param annotationTokens This type's type annotation tokens.
3473
                         * @param typeDescription  The represented type's description.
3474
                         */
3475
                        protected LazyPrimitiveType(TypePool typePool,
3476
                                                    String typePath,
3477
                                                    Map<String, List<AnnotationToken>> annotationTokens,
3478
                                                    TypeDescription typeDescription) {
1✔
3479
                            this.typePool = typePool;
1✔
3480
                            this.typePath = typePath;
1✔
3481
                            this.annotationTokens = annotationTokens;
1✔
3482
                            this.typeDescription = typeDescription;
1✔
3483
                        }
1✔
3484

3485
                        /**
3486
                         * {@inheritDoc}
3487
                         */
3488
                        public TypeDescription asErasure() {
3489
                            return typeDescription;
×
3490
                        }
3491

3492
                        /**
3493
                         * {@inheritDoc}
3494
                         */
3495
                        @MaybeNull
3496
                        public Generic getOwnerType() {
3497
                            return Generic.UNDEFINED;
×
3498
                        }
3499

3500
                        /**
3501
                         * {@inheritDoc}
3502
                         */
3503
                        @MaybeNull
3504
                        public Generic getComponentType() {
3505
                            return Generic.UNDEFINED;
×
3506
                        }
3507

3508
                        /**
3509
                         * {@inheritDoc}
3510
                         */
3511
                        public AnnotationList getDeclaredAnnotations() {
3512
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
3513
                        }
3514
                    }
3515
                }
3516

3517
                /**
3518
                 * A generic type token that represents an unbound wildcard.
3519
                 */
3520
                enum ForUnboundWildcard implements GenericTypeToken {
1✔
3521

3522
                    /**
3523
                     * The singleton instance.
3524
                     */
3525
                    INSTANCE;
1✔
3526

3527
                    /**
3528
                     * {@inheritDoc}
3529
                     */
3530
                    public Generic toGenericType(TypePool typePool,
3531
                                                 TypeVariableSource typeVariableSource,
3532
                                                 String typePath,
3533
                                                 @MaybeNull Map<String, List<AnnotationToken>> annotationTokens) {
3534
                        return new LazyUnboundWildcard(typePool,
1✔
3535
                                typePath,
3536
                                annotationTokens == null
3537
                                        ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
3538
                                        : annotationTokens);
3539
                    }
3540

3541
                    /**
3542
                     * {@inheritDoc}
3543
                     */
3544
                    public boolean isPrimaryBound(TypePool typePool) {
3545
                        throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
1✔
3546
                    }
3547

3548
                    /**
3549
                     * {@inheritDoc}
3550
                     */
3551
                    public String getTypePathPrefix() {
3552
                        throw new IllegalStateException("An unbound wildcard cannot be the owner of a nested type: " + this);
1✔
3553
                    }
3554

3555
                    /**
3556
                     * A generic type representation of a generic unbound wildcard.
3557
                     */
3558
                    protected static class LazyUnboundWildcard extends Generic.OfWildcardType {
3559

3560
                        /**
3561
                         * The type pool to use.
3562
                         */
3563
                        private final TypePool typePool;
3564

3565
                        /**
3566
                         * This type's type path.
3567
                         */
3568
                        private final String typePath;
3569

3570
                        /**
3571
                         * The type's type annotations.
3572
                         */
3573
                        private final Map<String, List<AnnotationToken>> annotationTokens;
3574

3575
                        /**
3576
                         * Creates a new lazy unbound wildcard.
3577
                         *
3578
                         * @param typePool         The type pool to use.
3579
                         * @param typePath         This type's type path.
3580
                         * @param annotationTokens The type's type annotations.
3581
                         */
3582
                        protected LazyUnboundWildcard(TypePool typePool, String typePath, Map<String, List<AnnotationToken>> annotationTokens) {
1✔
3583
                            this.typePool = typePool;
1✔
3584
                            this.typePath = typePath;
1✔
3585
                            this.annotationTokens = annotationTokens;
1✔
3586
                        }
1✔
3587

3588
                        /**
3589
                         * {@inheritDoc}
3590
                         */
3591
                        public TypeList.Generic getUpperBounds() {
3592
                            return new TypeList.Generic.Explicit(Generic.OfNonGenericType.ForLoadedType.of(Object.class));
1✔
3593
                        }
3594

3595
                        /**
3596
                         * {@inheritDoc}
3597
                         */
3598
                        public TypeList.Generic getLowerBounds() {
3599
                            return new TypeList.Generic.Empty();
1✔
3600
                        }
3601

3602
                        /**
3603
                         * {@inheritDoc}
3604
                         */
3605
                        public AnnotationList getDeclaredAnnotations() {
3606
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
3607
                        }
3608
                    }
3609
                }
3610

3611
                /**
3612
                 * A resolution of a type's, method's or field's generic types.
3613
                 */
3614
                interface Resolution {
3615

3616
                    /**
3617
                     * Resolves the type variables of the represented element.
3618
                     *
3619
                     * @param typePool              The type pool to be used for locating non-generic type descriptions.
3620
                     * @param typeVariableSource    The type variable source to use for resolving type variables.
3621
                     * @param annotationTokens      A mapping of the type variables' type annotation tokens by their indices.
3622
                     * @param boundAnnotationTokens A mapping of the type variables' bounds' type annotation tokens by their indices
3623
                     *                              and each type variable's index.
3624
                     * @return A list describing the resolved generic types.
3625
                     */
3626
                    TypeList.Generic resolveTypeVariables(TypePool typePool,
3627
                                                          TypeVariableSource typeVariableSource,
3628
                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3629
                                                          Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens);
3630

3631
                    /**
3632
                     * A resolution of a type's, method's or field's generic types if all of the represented element's are raw.
3633
                     */
3634
                    enum Raw implements ForType, ForField, ForMethod, ForRecordComponent {
1✔
3635

3636
                        /**
3637
                         * The singleton instance.
3638
                         */
3639
                        INSTANCE;
1✔
3640

3641
                        /**
3642
                         * {@inheritDoc}
3643
                         */
3644
                        public Generic resolveSuperClass(String superClassDescriptor,
3645
                                                         TypePool typePool,
3646
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3647
                                                         TypeDescription definingType) {
3648
                            return RawAnnotatedType.of(typePool, annotationTokens, superClassDescriptor);
1✔
3649
                        }
3650

3651
                        /**
3652
                         * {@inheritDoc}
3653
                         */
3654
                        public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
3655
                                                                      TypePool typePool,
3656
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3657
                                                                      TypeDescription definingType) {
3658
                            return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, interfaceTypeDescriptors);
1✔
3659
                        }
3660

3661
                        /**
3662
                         * {@inheritDoc}
3663
                         */
3664
                        public TypeList.Generic resolveTypeVariables(TypePool typePool,
3665
                                                                     TypeVariableSource typeVariableSource,
3666
                                                                     Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3667
                                                                     Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
3668
                            return new TypeList.Generic.Empty();
1✔
3669
                        }
3670

3671
                        /**
3672
                         * {@inheritDoc}
3673
                         */
3674
                        public Generic resolveFieldType(String fieldTypeDescriptor,
3675
                                                        TypePool typePool,
3676
                                                        Map<String, List<AnnotationToken>> annotationTokens,
3677
                                                        FieldDescription.InDefinedShape definingField) {
3678
                            return RawAnnotatedType.of(typePool, annotationTokens, fieldTypeDescriptor);
1✔
3679
                        }
3680

3681
                        /**
3682
                         * {@inheritDoc}
3683
                         */
3684
                        public Generic resolveReturnType(String returnTypeDescriptor,
3685
                                                         TypePool typePool,
3686
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3687
                                                         MethodDescription.InDefinedShape definingMethod) {
3688
                            return RawAnnotatedType.of(typePool, annotationTokens, returnTypeDescriptor);
1✔
3689
                        }
3690

3691
                        /**
3692
                         * {@inheritDoc}
3693
                         */
3694
                        public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
3695
                                                                      TypePool typePool,
3696
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3697
                                                                      MethodDescription.InDefinedShape definingMethod) {
3698
                            return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, parameterTypeDescriptors);
1✔
3699
                        }
3700

3701
                        /**
3702
                         * {@inheritDoc}
3703
                         */
3704
                        public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
3705
                                                                      TypePool typePool,
3706
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3707
                                                                      MethodDescription.InDefinedShape definingMethod) {
3708
                            return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, exceptionTypeDescriptors);
1✔
3709
                        }
3710

3711
                        /**
3712
                         * {@inheritDoc}
3713
                         */
3714
                        public Generic resolveRecordType(String recordTypeDescriptor,
3715
                                                         TypePool typePool,
3716
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3717
                                                         RecordComponentDescription.InDefinedShape definingRecordComponent) {
3718
                            return RawAnnotatedType.of(typePool, annotationTokens, recordTypeDescriptor);
×
3719
                        }
3720

3721
                        /**
3722
                         * Represents a non-generic type that defines type annotations.
3723
                         */
3724
                        protected static class RawAnnotatedType extends Generic.OfNonGenericType {
3725

3726
                            /**
3727
                             * The type pool to use.
3728
                             */
3729
                            private final TypePool typePool;
3730

3731
                            /**
3732
                             * The type's type path.
3733
                             */
3734
                            private final String typePath;
3735

3736
                            /**
3737
                             * A mapping of this type's type annotations.
3738
                             */
3739
                            private final Map<String, List<AnnotationToken>> annotationTokens;
3740

3741
                            /**
3742
                             * The represented non-generic type.
3743
                             */
3744
                            private final TypeDescription typeDescription;
3745

3746
                            /**
3747
                             * Creates a new raw annotated type.
3748
                             *
3749
                             * @param typePool         The type pool to use.
3750
                             * @param typePath         The type's type path.
3751
                             * @param annotationTokens A mapping of this type's type annotations.
3752
                             * @param typeDescription  The represented non-generic type.
3753
                             */
3754
                            protected RawAnnotatedType(TypePool typePool,
3755
                                                       String typePath,
3756
                                                       Map<String, List<AnnotationToken>> annotationTokens,
3757
                                                       TypeDescription typeDescription) {
1✔
3758
                                this.typePool = typePool;
1✔
3759
                                this.typePath = typePath;
1✔
3760
                                this.annotationTokens = annotationTokens;
1✔
3761
                                this.typeDescription = typeDescription;
1✔
3762
                            }
1✔
3763

3764
                            /**
3765
                             * Creates a new raw annotated type.
3766
                             *
3767
                             * @param typePool         The type pool to use.
3768
                             * @param annotationTokens A mapping of this type's type annotations.
3769
                             * @param descriptor       The descriptor of the represented non-generic type.
3770
                             * @return An annotated non-generic type.
3771
                             */
3772
                            protected static Generic of(TypePool typePool,
3773
                                                        @MaybeNull Map<String, List<AnnotationToken>> annotationTokens,
3774
                                                        String descriptor) {
3775
                                return new RawAnnotatedType(typePool,
1✔
3776
                                        EMPTY_TYPE_PATH,
3777
                                        annotationTokens == null
3778
                                                ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
3779
                                                : annotationTokens,
3780
                                        TokenizedGenericType.toErasure(typePool, descriptor));
1✔
3781
                            }
3782

3783
                            /**
3784
                             * {@inheritDoc}
3785
                             */
3786
                            public TypeDescription asErasure() {
3787
                                return typeDescription;
1✔
3788
                            }
3789

3790
                            /**
3791
                             * {@inheritDoc}
3792
                             */
3793
                            @MaybeNull
3794
                            public Generic getOwnerType() {
3795
                                TypeDescription declaringType = typeDescription.getDeclaringType();
1✔
3796
                                return declaringType == null
1✔
3797
                                        ? Generic.UNDEFINED
3798
                                        : new RawAnnotatedType(typePool, typePath, annotationTokens, declaringType);
3799
                            }
3800

3801
                            /**
3802
                             * {@inheritDoc}
3803
                             */
3804
                            @MaybeNull
3805
                            public Generic getComponentType() {
3806
                                TypeDescription componentType = typeDescription.getComponentType();
1✔
3807
                                return componentType == null
1✔
3808
                                        ? Generic.UNDEFINED
3809
                                        : new RawAnnotatedType(typePool, typePath + COMPONENT_TYPE_PATH, annotationTokens, componentType);
3810
                            }
3811

3812
                            /**
3813
                             * {@inheritDoc}
3814
                             */
3815
                            public AnnotationList getDeclaredAnnotations() {
3816
                                StringBuilder typePath = new StringBuilder(this.typePath);
1✔
3817
                                for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
1✔
3818
                                    typePath = typePath.append(INNER_CLASS_PATH);
1✔
3819
                                }
3820
                                return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath.toString()));
1✔
3821
                            }
3822

3823
                            /**
3824
                             * A generic type list representing raw types.
3825
                             */
3826
                            protected static class LazyRawAnnotatedTypeList extends TypeList.Generic.AbstractBase {
3827

3828
                                /**
3829
                                 * The type pool to use for locating types.
3830
                                 */
3831
                                private final TypePool typePool;
3832

3833
                                /**
3834
                                 * A mapping of the represented types' type annotation tokens by their indices.
3835
                                 */
3836
                                private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
3837

3838
                                /**
3839
                                 * A list of type descriptors that this list represents.
3840
                                 */
3841
                                private final List<String> descriptors;
3842

3843
                                /**
3844
                                 * Creates a generic type list only representing raw types.
3845
                                 *
3846
                                 * @param typePool         The type pool to use for locating types.
3847
                                 * @param annotationTokens A mapping of the represented types' type annotation tokens by their indices.
3848
                                 * @param descriptors      A list of type descriptors that this list represents.
3849
                                 */
3850
                                protected LazyRawAnnotatedTypeList(TypePool typePool,
3851
                                                                   Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3852
                                                                   List<String> descriptors) {
1✔
3853
                                    this.typePool = typePool;
1✔
3854
                                    this.annotationTokens = annotationTokens;
1✔
3855
                                    this.descriptors = descriptors;
1✔
3856
                                }
1✔
3857

3858
                                /**
3859
                                 * Creates generic type list only representing raw types.
3860
                                 *
3861
                                 * @param typePool         The type pool to use for locating types.
3862
                                 * @param annotationTokens A mapping of the represented types' type annotation tokens by their indices or
3863
                                 *                         {@code null} if no type annotations are defined for any type.
3864
                                 * @param descriptors      A list of type descriptors that this list represents.
3865
                                 * @return A generic type list representing the raw types this list represents.
3866
                                 */
3867
                                protected static TypeList.Generic of(TypePool typePool,
3868
                                                                     @MaybeNull Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3869
                                                                     List<String> descriptors) {
3870
                                    return new LazyRawAnnotatedTypeList(typePool,
1✔
3871
                                            annotationTokens == null
3872
                                                    ? Collections.<Integer, Map<String, List<AnnotationToken>>>emptyMap()
1✔
3873
                                                    : annotationTokens,
3874
                                            descriptors);
3875
                                }
3876

3877
                                /**
3878
                                 * {@inheritDoc}
3879
                                 */
3880
                                public Generic get(int index) {
3881
                                    return RawAnnotatedType.of(typePool, annotationTokens.get(index), descriptors.get(index));
1✔
3882
                                }
3883

3884
                                /**
3885
                                 * {@inheritDoc}
3886
                                 */
3887
                                public int size() {
3888
                                    return descriptors.size();
1✔
3889
                                }
3890

3891
                                /**
3892
                                 * {@inheritDoc}
3893
                                 */
3894
                                public TypeList asErasures() {
3895
                                    return new LazyTypeList(typePool, descriptors);
1✔
3896
                                }
3897

3898
                                /**
3899
                                 * {@inheritDoc}
3900
                                 */
3901
                                public TypeList.Generic asRawTypes() {
3902
                                    return this;
×
3903
                                }
3904

3905
                                /**
3906
                                 * {@inheritDoc}
3907
                                 */
3908
                                public int getStackSize() {
3909
                                    int stackSize = 0;
1✔
3910
                                    for (String descriptor : descriptors) {
1✔
3911
                                        stackSize += Type.getType(descriptor).getSize();
1✔
3912
                                    }
1✔
3913
                                    return stackSize;
1✔
3914
                                }
3915
                            }
3916
                        }
3917
                    }
3918

3919
                    /**
3920
                     * A resolution of a type's, method's or field's generic types if its generic signature is malformed.
3921
                     */
3922
                    enum Malformed implements ForType, ForField, ForMethod, ForRecordComponent {
1✔
3923

3924
                        /**
3925
                         * The singleton instance.
3926
                         */
3927
                        INSTANCE;
1✔
3928

3929
                        /**
3930
                         * {@inheritDoc}
3931
                         */
3932
                        public Generic resolveSuperClass(String superClassDescriptor,
3933
                                                         TypePool typePool,
3934
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3935
                                                         TypeDescription definingType) {
3936
                            return new TokenizedGenericType.Malformed(typePool, superClassDescriptor);
×
3937
                        }
3938

3939
                        /**
3940
                         * {@inheritDoc}
3941
                         */
3942
                        public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
3943
                                                                      TypePool typePool,
3944
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3945
                                                                      TypeDescription definingType) {
3946
                            return new TokenizedGenericType.Malformed.TokenList(typePool, interfaceTypeDescriptors);
1✔
3947
                        }
3948

3949
                        /**
3950
                         * {@inheritDoc}
3951
                         */
3952
                        public TypeList.Generic resolveTypeVariables(TypePool typePool,
3953
                                                                     TypeVariableSource typeVariableSource,
3954
                                                                     Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3955
                                                                     Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
3956
                            throw new GenericSignatureFormatError();
×
3957
                        }
3958

3959
                        /**
3960
                         * {@inheritDoc}
3961
                         */
3962
                        public Generic resolveFieldType(String fieldTypeDescriptor,
3963
                                                        TypePool typePool,
3964
                                                        Map<String, List<AnnotationToken>> annotationTokens,
3965
                                                        FieldDescription.InDefinedShape definingField) {
3966
                            return new TokenizedGenericType.Malformed(typePool, fieldTypeDescriptor);
1✔
3967
                        }
3968

3969
                        /**
3970
                         * {@inheritDoc}
3971
                         */
3972
                        public Generic resolveReturnType(String returnTypeDescriptor,
3973
                                                         TypePool typePool,
3974
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3975
                                                         MethodDescription.InDefinedShape definingMethod) {
3976
                            return new TokenizedGenericType.Malformed(typePool, returnTypeDescriptor);
1✔
3977
                        }
3978

3979
                        /**
3980
                         * {@inheritDoc}
3981
                         */
3982
                        public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
3983
                                                                      TypePool typePool,
3984
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3985
                                                                      MethodDescription.InDefinedShape definingMethod) {
3986
                            return new TokenizedGenericType.Malformed.TokenList(typePool, parameterTypeDescriptors);
×
3987
                        }
3988

3989
                        /**
3990
                         * {@inheritDoc}
3991
                         */
3992
                        public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
3993
                                                                      TypePool typePool,
3994
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3995
                                                                      MethodDescription.InDefinedShape definingMethod) {
3996
                            return new TokenizedGenericType.Malformed.TokenList(typePool, exceptionTypeDescriptors);
×
3997
                        }
3998

3999

4000
                        /**
4001
                         * {@inheritDoc}
4002
                         */
4003
                        public Generic resolveRecordType(String recordTypeDescriptor,
4004
                                                         TypePool typePool,
4005
                                                         Map<String, List<AnnotationToken>> annotationTokens,
4006
                                                         RecordComponentDescription.InDefinedShape definingRecordComponent) {
4007
                            return new TokenizedGenericType.Malformed(typePool, recordTypeDescriptor);
×
4008
                        }
4009
                    }
4010

4011
                    /**
4012
                     * A resolution of the generic types of a {@link TypeDescription}.
4013
                     */
4014
                    interface ForType extends Resolution {
4015

4016
                        /**
4017
                         * Resolves the generic super type of the represented type.
4018
                         *
4019
                         * @param superClassDescriptor The descriptor of the raw super type.
4020
                         * @param typePool             The type pool to be used for locating non-generic type descriptions.
4021
                         * @param annotationTokens     A mapping of the super type's type annotation tokens.
4022
                         * @param definingType         The type that defines this super type.
4023
                         * @return A description of this type's generic super type.
4024
                         */
4025
                        Generic resolveSuperClass(String superClassDescriptor,
4026
                                                  TypePool typePool,
4027
                                                  Map<String, List<AnnotationToken>> annotationTokens,
4028
                                                  TypeDescription definingType);
4029

4030
                        /**
4031
                         * Resolves the generic interface types of the represented type.
4032
                         *
4033
                         * @param interfaceTypeDescriptors The descriptor of the raw interface types.
4034
                         * @param typePool                 The type pool to be used for locating non-generic type descriptions.
4035
                         * @param annotationTokens         A mapping of the interface types' type annotation tokens by their indices.
4036
                         * @param definingType             The type that defines these interface type.
4037
                         * @return A description of this type's generic interface types.
4038
                         */
4039
                        TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
4040
                                                               TypePool typePool,
4041
                                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4042
                                                               TypeDescription definingType);
4043

4044
                        /**
4045
                         * An implementation of a tokenized resolution of generic types of a {@link TypeDescription}.
4046
                         */
4047
                        @HashCodeAndEqualsPlugin.Enhance
4048
                        class Tokenized implements ForType {
4049

4050
                            /**
4051
                             * The super type's generic type token.
4052
                             */
4053
                            private final GenericTypeToken superClassToken;
4054

4055
                            /**
4056
                             * The interface type's generic type tokens.
4057
                             */
4058
                            private final List<GenericTypeToken> interfaceTypeTokens;
4059

4060
                            /**
4061
                             * The type variables generic type tokens.
4062
                             */
4063
                            private final List<OfFormalTypeVariable> typeVariableTokens;
4064

4065
                            /**
4066
                             * Creates a new tokenized resolution of a {@link TypeDescription}'s generic signatures.
4067
                             *
4068
                             * @param superClassToken     The super class's generic type token.
4069
                             * @param interfaceTypeTokens The interface type's generic type tokens.
4070
                             * @param typeVariableTokens  The type variables generic type tokens.
4071
                             */
4072
                            protected Tokenized(GenericTypeToken superClassToken,
4073
                                                List<GenericTypeToken> interfaceTypeTokens,
4074
                                                List<OfFormalTypeVariable> typeVariableTokens) {
1✔
4075
                                this.superClassToken = superClassToken;
1✔
4076
                                this.interfaceTypeTokens = interfaceTypeTokens;
1✔
4077
                                this.typeVariableTokens = typeVariableTokens;
1✔
4078
                            }
1✔
4079

4080
                            /**
4081
                             * {@inheritDoc}
4082
                             */
4083
                            public Generic resolveSuperClass(String superClassDescriptor,
4084
                                                             TypePool typePool,
4085
                                                             Map<String, List<AnnotationToken>> annotationTokens,
4086
                                                             TypeDescription definingType) {
4087
                                return TokenizedGenericType.of(typePool,
1✔
4088
                                        superClassToken,
4089
                                        superClassDescriptor,
4090
                                        annotationTokens,
4091
                                        definingType);
4092
                            }
4093

4094
                            /**
4095
                             * {@inheritDoc}
4096
                             */
4097
                            public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
4098
                                                                          TypePool typePool,
4099
                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4100
                                                                          TypeDescription definingType) {
4101
                                return new TokenizedGenericType.TokenList(typePool, interfaceTypeTokens, annotationTokens, interfaceTypeDescriptors, definingType);
1✔
4102
                            }
4103

4104
                            /**
4105
                             * {@inheritDoc}
4106
                             */
4107
                            public TypeList.Generic resolveTypeVariables(TypePool typePool,
4108
                                                                         TypeVariableSource typeVariableSource,
4109
                                                                         Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4110
                                                                         Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
4111
                                return new TokenizedGenericType.TypeVariableList(typePool, typeVariableTokens, typeVariableSource, annotationTokens, boundAnnotationTokens);
1✔
4112
                            }
4113
                        }
4114
                    }
4115

4116
                    /**
4117
                     * A resolution of the generic type of a {@link FieldDescription}.
4118
                     */
4119
                    interface ForField {
4120

4121
                        /**
4122
                         * Resolves the field type of the represented field.
4123
                         *
4124
                         * @param fieldTypeDescriptor The descriptor of the raw field type.
4125
                         * @param typePool            The type pool to be used for locating non-generic type descriptions.
4126
                         * @param annotationTokens    A mapping of the represented types' type annotation tokens.
4127
                         * @param definingField       The field that defines this type.
4128
                         * @return A generic type representation of the field's type.
4129
                         */
4130
                        Generic resolveFieldType(String fieldTypeDescriptor,
4131
                                                 TypePool typePool,
4132
                                                 Map<String, List<AnnotationToken>> annotationTokens,
4133
                                                 FieldDescription.InDefinedShape definingField);
4134

4135
                        /**
4136
                         * An implementation of a tokenized resolution of the generic type of a {@link FieldDescription}.
4137
                         */
4138
                        @HashCodeAndEqualsPlugin.Enhance
4139
                        class Tokenized implements ForField {
4140

4141
                            /**
4142
                             * The token of the represented field's type.
4143
                             */
4144
                            private final GenericTypeToken fieldTypeToken;
4145

4146
                            /**
4147
                             * Creates a new tokenized resolution of a {@link FieldDescription}'s type.
4148
                             *
4149
                             * @param fieldTypeToken The token of the represented field's type.
4150
                             */
4151
                            protected Tokenized(GenericTypeToken fieldTypeToken) {
1✔
4152
                                this.fieldTypeToken = fieldTypeToken;
1✔
4153
                            }
1✔
4154

4155
                            /**
4156
                             * {@inheritDoc}
4157
                             */
4158
                            public Generic resolveFieldType(String fieldTypeDescriptor,
4159
                                                            TypePool typePool,
4160
                                                            Map<String, List<AnnotationToken>> annotationTokens,
4161
                                                            FieldDescription.InDefinedShape definingField) {
4162
                                return TokenizedGenericType.of(typePool,
1✔
4163
                                        fieldTypeToken,
4164
                                        fieldTypeDescriptor,
4165
                                        annotationTokens,
4166
                                        definingField.getDeclaringType());
1✔
4167
                            }
4168
                        }
4169
                    }
4170

4171
                    /**
4172
                     * A resolution of the generic types of a {@link MethodDescription}.
4173
                     */
4174
                    interface ForMethod extends Resolution {
4175

4176
                        /**
4177
                         * Resolves the return type of the represented method.
4178
                         *
4179
                         * @param returnTypeDescriptor The descriptor of the raw return type.
4180
                         * @param typePool             The type pool to be used for locating non-generic type descriptions.
4181
                         * @param annotationTokens     A mapping of the return type's type annotation tokens.
4182
                         * @param definingMethod       The method that defines this return type.
4183
                         * @return A description of this type's generic return type.
4184
                         */
4185
                        Generic resolveReturnType(String returnTypeDescriptor,
4186
                                                  TypePool typePool,
4187
                                                  Map<String, List<AnnotationToken>> annotationTokens,
4188
                                                  MethodDescription.InDefinedShape definingMethod);
4189

4190
                        /**
4191
                         * Resolves the generic parameter types of the represented method.
4192
                         *
4193
                         * @param parameterTypeDescriptors The descriptor of the raw parameter types.
4194
                         * @param typePool                 The type pool to be used for locating non-generic type descriptions.
4195
                         * @param annotationTokens         A mapping of the parameter types' type annotation tokens by their indices.
4196
                         * @param definingMethod           The method that defines these parameter types.
4197
                         * @return A description of this type's generic interface types.
4198
                         */
4199
                        TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
4200
                                                               TypePool typePool,
4201
                                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4202
                                                               MethodDescription.InDefinedShape definingMethod);
4203

4204
                        /**
4205
                         * Resolves the generic parameter types of the represented method.
4206
                         *
4207
                         * @param exceptionTypeDescriptors The descriptor of the raw exception types.
4208
                         * @param typePool                 The type pool to be used for locating non-generic type descriptions.
4209
                         * @param annotationTokens         A mapping of the exception types' type annotation tokens by their indices.
4210
                         * @param definingMethod           The method that defines these exception types.
4211
                         * @return A description of this type's generic interface types.
4212
                         */
4213
                        TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
4214
                                                               TypePool typePool,
4215
                                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4216
                                                               MethodDescription.InDefinedShape definingMethod);
4217

4218
                        /**
4219
                         * An implementation of a tokenized resolution of generic types of a {@link MethodDescription}.
4220
                         */
4221
                        @HashCodeAndEqualsPlugin.Enhance
4222
                        class Tokenized implements ForMethod {
4223

4224
                            /**
4225
                             * A token describing the represented method's return type.
4226
                             */
4227
                            private final GenericTypeToken returnTypeToken;
4228

4229
                            /**
4230
                             * A token describing the represented method's parameter types.
4231
                             */
4232
                            private final List<GenericTypeToken> parameterTypeTokens;
4233

4234
                            /**
4235
                             * A token describing the represented method's exception types.
4236
                             */
4237
                            private final List<GenericTypeToken> exceptionTypeTokens;
4238

4239
                            /**
4240
                             * A token describing the represented method's type variables.
4241
                             */
4242
                            private final List<OfFormalTypeVariable> typeVariableTokens;
4243

4244
                            /**
4245
                             * Creates a new tokenized resolution of a {@link MethodDescription}'s generic signatures.
4246
                             *
4247
                             * @param returnTypeToken     A token describing the represented method's return type.
4248
                             * @param parameterTypeTokens A token describing the represented method's parameter types.
4249
                             * @param exceptionTypeTokens A token describing the represented method's exception types.
4250
                             * @param typeVariableTokens  A token describing the represented method's type variables.
4251
                             */
4252
                            protected Tokenized(GenericTypeToken returnTypeToken,
4253
                                                List<GenericTypeToken> parameterTypeTokens,
4254
                                                List<GenericTypeToken> exceptionTypeTokens,
4255
                                                List<OfFormalTypeVariable> typeVariableTokens) {
1✔
4256
                                this.returnTypeToken = returnTypeToken;
1✔
4257
                                this.parameterTypeTokens = parameterTypeTokens;
1✔
4258
                                this.exceptionTypeTokens = exceptionTypeTokens;
1✔
4259
                                this.typeVariableTokens = typeVariableTokens;
1✔
4260
                            }
1✔
4261

4262
                            /**
4263
                             * {@inheritDoc}
4264
                             */
4265
                            public Generic resolveReturnType(String returnTypeDescriptor,
4266
                                                             TypePool typePool,
4267
                                                             Map<String, List<AnnotationToken>> annotationTokens,
4268
                                                             MethodDescription.InDefinedShape definingMethod) {
4269
                                return TokenizedGenericType.of(typePool,
1✔
4270
                                        returnTypeToken,
4271
                                        returnTypeDescriptor,
4272
                                        annotationTokens,
4273
                                        definingMethod);
4274
                            }
4275

4276
                            /**
4277
                             * {@inheritDoc}
4278
                             */
4279
                            public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
4280
                                                                          TypePool typePool,
4281
                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4282
                                                                          MethodDescription.InDefinedShape definingMethod) {
4283
                                return new TokenizedGenericType.TokenList(typePool, parameterTypeTokens, annotationTokens, parameterTypeDescriptors, definingMethod);
1✔
4284
                            }
4285

4286
                            /**
4287
                             * {@inheritDoc}
4288
                             */
4289
                            public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
4290
                                                                          TypePool typePool,
4291
                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4292
                                                                          MethodDescription.InDefinedShape definingMethod) {
4293
                                // Generic signatures of methods are optional.
4294
                                return exceptionTypeTokens.isEmpty()
1✔
4295
                                        ? Raw.INSTANCE.resolveExceptionTypes(exceptionTypeDescriptors, typePool, annotationTokens, definingMethod)
1✔
4296
                                        : new TokenizedGenericType.TokenList(typePool, exceptionTypeTokens, annotationTokens, exceptionTypeDescriptors, definingMethod);
4297
                            }
4298

4299
                            /**
4300
                             * {@inheritDoc}
4301
                             */
4302
                            public TypeList.Generic resolveTypeVariables(TypePool typePool,
4303
                                                                         TypeVariableSource typeVariableSource,
4304
                                                                         Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4305
                                                                         Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
4306
                                return new TokenizedGenericType.TypeVariableList(typePool, typeVariableTokens, typeVariableSource, annotationTokens, boundAnnotationTokens);
1✔
4307
                            }
4308
                        }
4309
                    }
4310

4311
                    /**
4312
                     * A resolution of the generic type of a {@link RecordComponentDescription}.
4313
                     */
4314
                    interface ForRecordComponent {
4315

4316
                        /**
4317
                         * Resolves a record component's type.
4318
                         *
4319
                         * @param recordTypeDescriptor    The record component's descriptor.
4320
                         * @param typePool                The type pool to be used for locating non-generic type descriptions.
4321
                         * @param annotationTokens        A mapping of the represented types' type annotation tokens.
4322
                         * @param definingRecordComponent The defining record component.
4323
                         * @return A generic type representation of the record component's type.
4324
                         */
4325
                        Generic resolveRecordType(String recordTypeDescriptor,
4326
                                                  TypePool typePool,
4327
                                                  Map<String, List<AnnotationToken>> annotationTokens,
4328
                                                  RecordComponentDescription.InDefinedShape definingRecordComponent);
4329

4330
                        /**
4331
                         * An implementation of a tokenized resolution of the generic type of a {@link RecordComponentDescription}.
4332
                         */
4333
                        @HashCodeAndEqualsPlugin.Enhance
4334
                        class Tokenized implements ForRecordComponent {
4335

4336
                            /**
4337
                             * The token of the represented record component's type.
4338
                             */
4339
                            private final GenericTypeToken recordComponentTypeToken;
4340

4341
                            /**
4342
                             * Creates a new tokenized resolution of a {@link RecordComponentDescription}'s type.
4343
                             *
4344
                             * @param recordComponentTypeToken The token of the represented record component's type.
4345
                             */
4346
                            protected Tokenized(GenericTypeToken recordComponentTypeToken) {
×
4347
                                this.recordComponentTypeToken = recordComponentTypeToken;
×
4348
                            }
×
4349

4350
                            /**
4351
                             * {@inheritDoc}
4352
                             */
4353
                            public Generic resolveRecordType(String recordTypeDescriptor,
4354
                                                             TypePool typePool,
4355
                                                             Map<String, List<AnnotationToken>> annotationTokens,
4356
                                                             RecordComponentDescription.InDefinedShape definingRecordComponent) {
4357
                                return TokenizedGenericType.of(typePool,
×
4358
                                        recordComponentTypeToken,
4359
                                        recordTypeDescriptor,
4360
                                        annotationTokens,
4361
                                        definingRecordComponent.getDeclaringType());
×
4362
                            }
4363
                        }
4364
                    }
4365
                }
4366

4367
                /**
4368
                 * A generic type token that represents a non-generic type.
4369
                 */
4370
                @HashCodeAndEqualsPlugin.Enhance
4371
                class ForRawType implements GenericTypeToken {
4372

4373
                    /**
4374
                     * The name of the represented type.
4375
                     */
4376
                    private final String name;
4377

4378
                    /**
4379
                     * Creates a new type token that represents a non-generic type.
4380
                     *
4381
                     * @param name The name of the represented type.
4382
                     */
4383
                    protected ForRawType(String name) {
1✔
4384
                        this.name = name;
1✔
4385
                    }
1✔
4386

4387
                    /**
4388
                     * {@inheritDoc}
4389
                     */
4390
                    public Generic toGenericType(TypePool typePool,
4391
                                                 TypeVariableSource typeVariableSource,
4392
                                                 String typePath,
4393
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4394
                        return new Resolution.Raw.RawAnnotatedType(typePool,
1✔
4395
                                typePath,
4396
                                annotationTokens,
4397
                                typePool.describe(name).resolve());
1✔
4398
                    }
4399

4400
                    /**
4401
                     * {@inheritDoc}
4402
                     */
4403
                    public boolean isPrimaryBound(TypePool typePool) {
4404
                        return !typePool.describe(name).resolve().isInterface();
1✔
4405
                    }
4406

4407
                    /**
4408
                     * {@inheritDoc}
4409
                     */
4410
                    public String getTypePathPrefix() {
4411
                        throw new IllegalStateException("A non-generic type cannot be the owner of a nested type: " + this);
1✔
4412
                    }
4413
                }
4414

4415
                /**
4416
                 * A generic type token that represents a type variable.
4417
                 */
4418
                @HashCodeAndEqualsPlugin.Enhance
4419
                class ForTypeVariable implements GenericTypeToken {
4420

4421
                    /**
4422
                     * This type variable's nominal symbol.
4423
                     */
4424
                    private final String symbol;
4425

4426
                    /**
4427
                     * Creates a generic type token that represents a type variable.
4428
                     *
4429
                     * @param symbol This type variable's nominal symbol.
4430
                     */
4431
                    protected ForTypeVariable(String symbol) {
1✔
4432
                        this.symbol = symbol;
1✔
4433
                    }
1✔
4434

4435
                    /**
4436
                     * {@inheritDoc}
4437
                     */
4438
                    public Generic toGenericType(TypePool typePool,
4439
                                                 TypeVariableSource typeVariableSource,
4440
                                                 String typePath,
4441
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4442
                        Generic typeVariable = typeVariableSource.findVariable(symbol);
1✔
4443
                        return typeVariable == null
1✔
4444
                                ? new UnresolvedTypeVariable(typeVariableSource, typePool, symbol, annotationTokens.get(typePath))
1✔
4445
                                : new AnnotatedTypeVariable(typePool, annotationTokens.get(typePath), typeVariable);
1✔
4446
                    }
4447

4448
                    /**
4449
                     * {@inheritDoc}
4450
                     */
4451
                    public boolean isPrimaryBound(TypePool typePool) {
4452
                        return true;
1✔
4453
                    }
4454

4455
                    /**
4456
                     * {@inheritDoc}
4457
                     */
4458
                    public String getTypePathPrefix() {
4459
                        throw new IllegalStateException("A type variable cannot be the owner of a nested type: " + this);
1✔
4460
                    }
4461

4462
                    /**
4463
                     * An annotated representation of a formal type variable.
4464
                     */
4465
                    protected static class AnnotatedTypeVariable extends Generic.OfTypeVariable {
4466

4467
                        /**
4468
                         * The type pool to use.
4469
                         */
4470
                        private final TypePool typePool;
4471

4472
                        /**
4473
                         * The represented annotation tokens.
4474
                         */
4475
                        private final List<AnnotationToken> annotationTokens;
4476

4477
                        /**
4478
                         * The represented type variable.
4479
                         */
4480
                        private final Generic typeVariable;
4481

4482
                        /**
4483
                         * Creates a new annotated type variable.
4484
                         *
4485
                         * @param typePool         The type pool to use.
4486
                         * @param annotationTokens The represented annotation tokens.
4487
                         * @param typeVariable     The represented type variable.
4488
                         */
4489
                        protected AnnotatedTypeVariable(TypePool typePool, List<AnnotationToken> annotationTokens, Generic typeVariable) {
1✔
4490
                            this.typePool = typePool;
1✔
4491
                            this.annotationTokens = annotationTokens;
1✔
4492
                            this.typeVariable = typeVariable;
1✔
4493
                        }
1✔
4494

4495
                        /**
4496
                         * {@inheritDoc}
4497
                         */
4498
                        public TypeList.Generic getUpperBounds() {
4499
                            return typeVariable.getUpperBounds();
1✔
4500
                        }
4501

4502
                        /**
4503
                         * {@inheritDoc}
4504
                         */
4505
                        public TypeVariableSource getTypeVariableSource() {
4506
                            return typeVariable.getTypeVariableSource();
1✔
4507
                        }
4508

4509
                        /**
4510
                         * {@inheritDoc}
4511
                         */
4512
                        public String getSymbol() {
4513
                            return typeVariable.getSymbol();
1✔
4514
                        }
4515

4516
                        /**
4517
                         * {@inheritDoc}
4518
                         */
4519
                        public AnnotationList getDeclaredAnnotations() {
4520
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
1✔
4521
                        }
4522
                    }
4523

4524
                    /**
4525
                     * Represents a type variable that a type references but that does not exist. Such type variables are only emitted by wrongful
4526
                     * compilation either due to the isolated recompilation of outer classes or due to bugs in compilers.
4527
                     */
4528
                    protected static class UnresolvedTypeVariable extends Generic.OfTypeVariable {
4529

4530
                        /**
4531
                         * The undeclared type variable's source.
4532
                         */
4533
                        private final TypeVariableSource typeVariableSource;
4534

4535
                        /**
4536
                         * The type pool to use.
4537
                         */
4538
                        private final TypePool typePool;
4539

4540
                        /**
4541
                         * The type variable's symbol.
4542
                         */
4543
                        private final String symbol;
4544

4545
                        /**
4546
                         * The type variable's annotation tokens.
4547
                         */
4548
                        private final List<AnnotationToken> annotationTokens;
4549

4550
                        /**
4551
                         * Creates an unresolved type variable.
4552
                         *
4553
                         * @param typeVariableSource The undeclared type variable's source.
4554
                         * @param typePool           The type pool to use.
4555
                         * @param symbol             The type variable's symbol.
4556
                         * @param annotationTokens   The type variable's annotation tokens.
4557
                         */
4558
                        protected UnresolvedTypeVariable(TypeVariableSource typeVariableSource,
4559
                                                         TypePool typePool,
4560
                                                         String symbol,
4561
                                                         List<AnnotationToken> annotationTokens) {
×
4562
                            this.typeVariableSource = typeVariableSource;
×
4563
                            this.typePool = typePool;
×
4564
                            this.symbol = symbol;
×
4565
                            this.annotationTokens = annotationTokens;
×
4566
                        }
×
4567

4568
                        /**
4569
                         * {@inheritDoc}
4570
                         */
4571
                        public TypeList.Generic getUpperBounds() {
4572
                            throw new IllegalStateException("Cannot resolve bounds of unresolved type variable " + this + " by " + typeVariableSource);
×
4573
                        }
4574

4575
                        /**
4576
                         * {@inheritDoc}
4577
                         */
4578
                        public TypeVariableSource getTypeVariableSource() {
4579
                            return typeVariableSource;
×
4580
                        }
4581

4582
                        /**
4583
                         * {@inheritDoc}
4584
                         */
4585
                        public String getSymbol() {
4586
                            return symbol;
×
4587
                        }
4588

4589
                        /**
4590
                         * {@inheritDoc}
4591
                         */
4592
                        public AnnotationList getDeclaredAnnotations() {
4593
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
×
4594
                        }
4595
                    }
4596

4597
                    /**
4598
                     * A generic type token that represent a formal type variable, i.e. a type variable including its upper bounds.
4599
                     */
4600
                    @HashCodeAndEqualsPlugin.Enhance
4601
                    protected static class Formal implements GenericTypeToken.OfFormalTypeVariable {
4602

4603
                        /**
4604
                         * This type variable's nominal symbol.
4605
                         */
4606
                        private final String symbol;
4607

4608
                        /**
4609
                         * A list of tokens that represent this type variable's upper bounds.
4610
                         */
4611
                        private final List<GenericTypeToken> boundTypeTokens;
4612

4613
                        /**
4614
                         * Creates generic type token that represent a formal type variable.
4615
                         *
4616
                         * @param symbol          This type variable's nominal symbol.
4617
                         * @param boundTypeTokens A list of tokens that represent this type variable's upper bounds.
4618
                         */
4619
                        protected Formal(String symbol, List<GenericTypeToken> boundTypeTokens) {
1✔
4620
                            this.symbol = symbol;
1✔
4621
                            this.boundTypeTokens = boundTypeTokens;
1✔
4622
                        }
1✔
4623

4624
                        /**
4625
                         * {@inheritDoc}
4626
                         */
4627
                        public Generic toGenericType(TypePool typePool,
4628
                                                     TypeVariableSource typeVariableSource,
4629
                                                     @MaybeNull Map<String, List<AnnotationToken>> annotationTokens,
4630
                                                     @MaybeNull Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens) {
4631
                            return new LazyTypeVariable(typePool,
1✔
4632
                                    typeVariableSource,
4633
                                    annotationTokens == null
4634
                                            ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
4635
                                            : annotationTokens,
4636
                                    boundaryAnnotationTokens == null
4637
                                            ? Collections.<Integer, Map<String, List<AnnotationToken>>>emptyMap()
1✔
4638
                                            : boundaryAnnotationTokens,
4639
                                    symbol,
4640
                                    boundTypeTokens);
4641
                        }
4642

4643
                        /**
4644
                         * A type description that represents a type variable with bounds that are resolved lazily.
4645
                         */
4646
                        protected static class LazyTypeVariable extends Generic.OfTypeVariable {
4647

4648
                            /**
4649
                             * The type pool to use for locating type descriptions.
4650
                             */
4651
                            private final TypePool typePool;
4652

4653
                            /**
4654
                             * The type variable source to use for locating type variables.
4655
                             */
4656
                            private final TypeVariableSource typeVariableSource;
4657

4658
                            /**
4659
                             * The type variable's type annotation tokens.
4660
                             */
4661
                            private final Map<String, List<AnnotationToken>> annotationTokens;
4662

4663
                            /**
4664
                             * A mapping of the type variable bounds' type annotation tokens by their indices.
4665
                             */
4666
                            private final Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens;
4667

4668
                            /**
4669
                             * The type variable's symbol.
4670
                             */
4671
                            private final String symbol;
4672

4673
                            /**
4674
                             * Tokenized representations of the type variables bound types.
4675
                             */
4676
                            private final List<GenericTypeToken> boundTypeTokens;
4677

4678
                            /**
4679
                             * Creates a lazy type description of a type variables.
4680
                             *
4681
                             * @param typePool                 The type pool to use for locating type descriptions.
4682
                             * @param typeVariableSource       The type variable source to use for locating type variables.
4683
                             * @param annotationTokens         The type variable's type annotation tokens.
4684
                             * @param boundaryAnnotationTokens A mapping of the type variable bounds' type annotation tokens by their indices.
4685
                             * @param symbol                   The type variable's symbol.
4686
                             * @param boundTypeTokens          Tokenized representations of the type variables bound types.
4687
                             */
4688
                            protected LazyTypeVariable(TypePool typePool,
4689
                                                       TypeVariableSource typeVariableSource,
4690
                                                       Map<String, List<AnnotationToken>> annotationTokens,
4691
                                                       Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens,
4692
                                                       String symbol,
4693
                                                       List<GenericTypeToken> boundTypeTokens) {
1✔
4694
                                this.typePool = typePool;
1✔
4695
                                this.typeVariableSource = typeVariableSource;
1✔
4696
                                this.annotationTokens = annotationTokens;
1✔
4697
                                this.boundaryAnnotationTokens = boundaryAnnotationTokens;
1✔
4698
                                this.symbol = symbol;
1✔
4699
                                this.boundTypeTokens = boundTypeTokens;
1✔
4700
                            }
1✔
4701

4702
                            /**
4703
                             * {@inheritDoc}
4704
                             */
4705
                            public TypeList.Generic getUpperBounds() {
4706
                                return new LazyBoundTokenList(typePool, typeVariableSource, boundaryAnnotationTokens, boundTypeTokens);
1✔
4707
                            }
4708

4709
                            /**
4710
                             * {@inheritDoc}
4711
                             */
4712
                            public TypeVariableSource getTypeVariableSource() {
4713
                                return typeVariableSource;
1✔
4714
                            }
4715

4716
                            /**
4717
                             * {@inheritDoc}
4718
                             */
4719
                            public String getSymbol() {
4720
                                return symbol;
1✔
4721
                            }
4722

4723
                            /**
4724
                             * {@inheritDoc}
4725
                             */
4726
                            public AnnotationList getDeclaredAnnotations() {
4727
                                return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(EMPTY_TYPE_PATH));
1✔
4728
                            }
4729

4730
                            /**
4731
                             * A list representing a formal type variable's bounds.
4732
                             */
4733
                            protected static class LazyBoundTokenList extends TypeList.Generic.AbstractBase {
4734

4735
                                /**
4736
                                 * The type pool to use.
4737
                                 */
4738
                                private final TypePool typePool;
4739

4740
                                /**
4741
                                 * The type variable source for locating type variables.
4742
                                 */
4743
                                private final TypeVariableSource typeVariableSource;
4744

4745
                                /**
4746
                                 * A mapping of the bound type's type annotations by their bound index.
4747
                                 */
4748
                                private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
4749

4750
                                /**
4751
                                 * The bound types in their tokenized form.
4752
                                 */
4753
                                private final List<GenericTypeToken> boundTypeTokens;
4754

4755
                                /**
4756
                                 * Creates a new lazy bound token list for a type variable.
4757
                                 *
4758
                                 * @param typePool           The type pool to use.
4759
                                 * @param typeVariableSource The type variable source for locating type variables.
4760
                                 * @param annotationTokens   A mapping of the bound type's type annotations by their bound index.
4761
                                 * @param boundTypeTokens    The bound types in their tokenized form.
4762
                                 */
4763
                                protected LazyBoundTokenList(TypePool typePool,
4764
                                                             TypeVariableSource typeVariableSource,
4765
                                                             Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4766
                                                             List<GenericTypeToken> boundTypeTokens) {
1✔
4767
                                    this.typePool = typePool;
1✔
4768
                                    this.typeVariableSource = typeVariableSource;
1✔
4769
                                    this.annotationTokens = annotationTokens;
1✔
4770
                                    this.boundTypeTokens = boundTypeTokens;
1✔
4771
                                }
1✔
4772

4773
                                /**
4774
                                 * {@inheritDoc}
4775
                                 */
4776
                                public Generic get(int index) {
4777
                                    // Avoid resolution of interface bound type unless a type annotation can be possibly resolved.
4778
                                    Map<String, List<AnnotationToken>> annotationTokens = !this.annotationTokens.containsKey(index) && !this.annotationTokens.containsKey(index + 1)
1✔
4779
                                            ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
4780
                                            : this.annotationTokens.get(index + (boundTypeTokens.get(0).isPrimaryBound(typePool) ? 0 : 1));
1✔
4781
                                    return boundTypeTokens.get(index).toGenericType(typePool,
1✔
4782
                                            typeVariableSource,
4783
                                            EMPTY_TYPE_PATH,
4784
                                            annotationTokens == null
4785
                                                    ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
4786
                                                    : annotationTokens);
4787
                                }
4788

4789
                                /**
4790
                                 * {@inheritDoc}
4791
                                 */
4792
                                public int size() {
4793
                                    return boundTypeTokens.size();
1✔
4794
                                }
4795
                            }
4796
                        }
4797
                    }
4798
                }
4799

4800
                /**
4801
                 * A generic type token that represents a generic array.
4802
                 */
4803
                @HashCodeAndEqualsPlugin.Enhance
4804
                class ForGenericArray implements GenericTypeToken {
4805

4806
                    /**
4807
                     * The array's component type.
4808
                     */
4809
                    private final GenericTypeToken componentTypeToken;
4810

4811
                    /**
4812
                     * Creates a generic type token that represents a generic array.
4813
                     *
4814
                     * @param componentTypeToken The array's component type.
4815
                     */
4816
                    protected ForGenericArray(GenericTypeToken componentTypeToken) {
1✔
4817
                        this.componentTypeToken = componentTypeToken;
1✔
4818
                    }
1✔
4819

4820
                    /**
4821
                     * {@inheritDoc}
4822
                     */
4823
                    public Generic toGenericType(TypePool typePool,
4824
                                                 TypeVariableSource typeVariableSource,
4825
                                                 String typePath,
4826
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4827
                        return new LazyGenericArray(typePool, typeVariableSource, typePath, annotationTokens, componentTypeToken);
1✔
4828
                    }
4829

4830
                    /**
4831
                     * {@inheritDoc}
4832
                     */
4833
                    public boolean isPrimaryBound(TypePool typePool) {
4834
                        throw new IllegalStateException("A generic array type cannot be a type variable bound: " + this);
1✔
4835
                    }
4836

4837
                    /**
4838
                     * {@inheritDoc}
4839
                     */
4840
                    public String getTypePathPrefix() {
4841
                        throw new IllegalStateException("A generic array type cannot be the owner of a nested type: " + this);
1✔
4842
                    }
4843

4844
                    /**
4845
                     * A generic type representation of a generic array.
4846
                     */
4847
                    protected static class LazyGenericArray extends Generic.OfGenericArray {
4848

4849
                        /**
4850
                         * The type pool to use.
4851
                         */
4852
                        private final TypePool typePool;
4853

4854
                        /**
4855
                         * The type variable source for locating type variables.
4856
                         */
4857
                        private final TypeVariableSource typeVariableSource;
4858

4859
                        /**
4860
                         * This type's type path.
4861
                         */
4862
                        private final String typePath;
4863

4864
                        /**
4865
                         * This type's type annotations.
4866
                         */
4867
                        private final Map<String, List<AnnotationToken>> annotationTokens;
4868

4869
                        /**
4870
                         * A tokenized representation of this generic arrays's component type.
4871
                         */
4872
                        private final GenericTypeToken componentTypeToken;
4873

4874
                        /**
4875
                         * Creates a new lazy generic array.
4876
                         *
4877
                         * @param typePool           The type pool to use.
4878
                         * @param typeVariableSource The type variable source for locating type variables.
4879
                         * @param typePath           This type's type path.
4880
                         * @param annotationTokens   This type's type annotations.
4881
                         * @param componentTypeToken A tokenized representation of this generic arrays's component type.
4882
                         */
4883
                        protected LazyGenericArray(TypePool typePool,
4884
                                                   TypeVariableSource typeVariableSource,
4885
                                                   String typePath,
4886
                                                   Map<String, List<AnnotationToken>> annotationTokens,
4887
                                                   GenericTypeToken componentTypeToken) {
1✔
4888
                            this.typePool = typePool;
1✔
4889
                            this.typeVariableSource = typeVariableSource;
1✔
4890
                            this.typePath = typePath;
1✔
4891
                            this.annotationTokens = annotationTokens;
1✔
4892
                            this.componentTypeToken = componentTypeToken;
1✔
4893
                        }
1✔
4894

4895
                        /**
4896
                         * {@inheritDoc}
4897
                         */
4898
                        public Generic getComponentType() {
4899
                            return componentTypeToken.toGenericType(typePool, typeVariableSource, typePath + COMPONENT_TYPE_PATH, annotationTokens);
1✔
4900
                        }
4901

4902
                        /**
4903
                         * {@inheritDoc}
4904
                         */
4905
                        public AnnotationList getDeclaredAnnotations() {
4906
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
4907
                        }
4908
                    }
4909
                }
4910

4911
                /**
4912
                 * A generic type token for a wildcard that is bound below.
4913
                 */
4914
                @HashCodeAndEqualsPlugin.Enhance
4915
                class ForLowerBoundWildcard implements GenericTypeToken {
4916

4917
                    /**
4918
                     * A token that represents the wildcard's lower bound.
4919
                     */
4920
                    private final GenericTypeToken boundTypeToken;
4921

4922
                    /**
4923
                     * Creates a generic type token for a wildcard that is bound below.
4924
                     *
4925
                     * @param boundTypeToken A token that represents the wildcard's lower bound.
4926
                     */
4927
                    protected ForLowerBoundWildcard(GenericTypeToken boundTypeToken) {
1✔
4928
                        this.boundTypeToken = boundTypeToken;
1✔
4929
                    }
1✔
4930

4931
                    /**
4932
                     * {@inheritDoc}
4933
                     */
4934
                    public Generic toGenericType(TypePool typePool,
4935
                                                 TypeVariableSource typeVariableSource,
4936
                                                 String typePath,
4937
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4938
                        return new LazyLowerBoundWildcard(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
4939
                    }
4940

4941
                    /**
4942
                     * {@inheritDoc}
4943
                     */
4944
                    public boolean isPrimaryBound(TypePool typePool) {
4945
                        throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
1✔
4946
                    }
4947

4948
                    /**
4949
                     * {@inheritDoc}
4950
                     */
4951
                    public String getTypePathPrefix() {
4952
                        throw new IllegalStateException("A lower bound wildcard cannot be the owner of a nested type: " + this);
1✔
4953
                    }
4954

4955
                    /**
4956
                     * A generic type representation of a lower bound wildcard.
4957
                     */
4958
                    protected static class LazyLowerBoundWildcard extends Generic.OfWildcardType {
4959

4960
                        /**
4961
                         * The type pool to use.
4962
                         */
4963
                        private final TypePool typePool;
4964

4965
                        /**
4966
                         * The type variable source for locating type variables.
4967
                         */
4968
                        private final TypeVariableSource typeVariableSource;
4969

4970
                        /**
4971
                         * This type's type path.
4972
                         */
4973
                        private final String typePath;
4974

4975
                        /**
4976
                         * This type's type annotations.
4977
                         */
4978
                        private final Map<String, List<AnnotationToken>> annotationTokens;
4979

4980
                        /**
4981
                         * A tokenized representation of this wildcard's bound.
4982
                         */
4983
                        private final GenericTypeToken boundTypeToken;
4984

4985
                        /**
4986
                         * Creates a new lazy lower bound wildcard.
4987
                         *
4988
                         * @param typePool           The type pool to use.
4989
                         * @param typeVariableSource The type variable source for locating type variables.
4990
                         * @param typePath           This type's type path.
4991
                         * @param annotationTokens   This type's type annotations.
4992
                         * @param boundTypeToken     A tokenized representation of this wildcard's bound.
4993
                         */
4994
                        protected LazyLowerBoundWildcard(TypePool typePool,
4995
                                                         TypeVariableSource typeVariableSource,
4996
                                                         String typePath,
4997
                                                         Map<String, List<AnnotationToken>> annotationTokens,
4998
                                                         GenericTypeToken boundTypeToken) {
1✔
4999
                            this.typePool = typePool;
1✔
5000
                            this.typeVariableSource = typeVariableSource;
1✔
5001
                            this.typePath = typePath;
1✔
5002
                            this.annotationTokens = annotationTokens;
1✔
5003
                            this.boundTypeToken = boundTypeToken;
1✔
5004
                        }
1✔
5005

5006
                        /**
5007
                         * {@inheritDoc}
5008
                         */
5009
                        public TypeList.Generic getUpperBounds() {
5010
                            return new TypeList.Generic.Explicit(Generic.OfNonGenericType.ForLoadedType.of(Object.class));
1✔
5011
                        }
5012

5013
                        /**
5014
                         * {@inheritDoc}
5015
                         */
5016
                        public TypeList.Generic getLowerBounds() {
5017
                            return new LazyTokenList.ForWildcardBound(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
5018
                        }
5019

5020
                        /**
5021
                         * {@inheritDoc}
5022
                         */
5023
                        public AnnotationList getDeclaredAnnotations() {
5024
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
5025
                        }
5026
                    }
5027
                }
5028

5029
                /**
5030
                 * A generic type token for a wildcard that is bound above.
5031
                 */
5032
                @HashCodeAndEqualsPlugin.Enhance
5033
                class ForUpperBoundWildcard implements GenericTypeToken {
5034

5035
                    /**
5036
                     * A token that represents the wildcard's upper bound.
5037
                     */
5038
                    private final GenericTypeToken boundTypeToken;
5039

5040
                    /**
5041
                     * Creates a generic type token for a wildcard that is bound above.
5042
                     *
5043
                     * @param boundTypeToken A token that represents the wildcard's upper bound.
5044
                     */
5045
                    protected ForUpperBoundWildcard(GenericTypeToken boundTypeToken) {
1✔
5046
                        this.boundTypeToken = boundTypeToken;
1✔
5047
                    }
1✔
5048

5049
                    /**
5050
                     * {@inheritDoc}
5051
                     */
5052
                    public Generic toGenericType(TypePool typePool,
5053
                                                 TypeVariableSource typeVariableSource,
5054
                                                 String typePath,
5055
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
5056
                        return new LazyUpperBoundWildcard(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
5057
                    }
5058

5059
                    /**
5060
                     * {@inheritDoc}
5061
                     */
5062
                    public boolean isPrimaryBound(TypePool typePool) {
5063
                        throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
1✔
5064
                    }
5065

5066
                    /**
5067
                     * {@inheritDoc}
5068
                     */
5069
                    public String getTypePathPrefix() {
5070
                        throw new IllegalStateException("An upper bound wildcard cannot be the owner of a nested type: " + this);
1✔
5071
                    }
5072

5073
                    /**
5074
                     * A generic type representation of a tokenized wildcard with an upper bound.
5075
                     */
5076
                    protected static class LazyUpperBoundWildcard extends Generic.OfWildcardType {
5077

5078
                        /**
5079
                         * The type pool to use.
5080
                         */
5081
                        private final TypePool typePool;
5082

5083
                        /**
5084
                         * The type variable source for locating type variables.
5085
                         */
5086
                        private final TypeVariableSource typeVariableSource;
5087

5088
                        /**
5089
                         * This type's type path.
5090
                         */
5091
                        private final String typePath;
5092

5093
                        /**
5094
                         * This type's type annotations.
5095
                         */
5096
                        private final Map<String, List<AnnotationToken>> annotationTokens;
5097

5098
                        /**
5099
                         * A tokenized representation of this wildcard's bound.
5100
                         */
5101
                        private final GenericTypeToken boundTypeToken;
5102

5103
                        /**
5104
                         * Creates a new lazy upper bound wildcard.
5105
                         *
5106
                         * @param typePool           The type pool to use.
5107
                         * @param typeVariableSource The type variable source for locating type variables.
5108
                         * @param typePath           This type's type path.
5109
                         * @param annotationTokens   This type's type annotations.
5110
                         * @param boundTypeToken     A tokenized representation of this wildcard's bound.
5111
                         */
5112
                        protected LazyUpperBoundWildcard(TypePool typePool,
5113
                                                         TypeVariableSource typeVariableSource,
5114
                                                         String typePath,
5115
                                                         Map<String, List<AnnotationToken>> annotationTokens,
5116
                                                         GenericTypeToken boundTypeToken) {
1✔
5117
                            this.typePool = typePool;
1✔
5118
                            this.typeVariableSource = typeVariableSource;
1✔
5119
                            this.typePath = typePath;
1✔
5120
                            this.annotationTokens = annotationTokens;
1✔
5121
                            this.boundTypeToken = boundTypeToken;
1✔
5122
                        }
1✔
5123

5124
                        /**
5125
                         * {@inheritDoc}
5126
                         */
5127
                        public TypeList.Generic getUpperBounds() {
5128
                            return new LazyTokenList.ForWildcardBound(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
5129
                        }
5130

5131
                        /**
5132
                         * {@inheritDoc}
5133
                         */
5134
                        public TypeList.Generic getLowerBounds() {
5135
                            return new TypeList.Generic.Empty();
1✔
5136
                        }
5137

5138
                        /**
5139
                         * {@inheritDoc}
5140
                         */
5141
                        public AnnotationList getDeclaredAnnotations() {
5142
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
5143
                        }
5144
                    }
5145
                }
5146

5147
                /**
5148
                 * A generic type token that represents a parameterized type.
5149
                 */
5150
                @HashCodeAndEqualsPlugin.Enhance
5151
                class ForParameterizedType implements GenericTypeToken {
5152

5153
                    /**
5154
                     * The name of the parameterized type's erasure.
5155
                     */
5156
                    private final String name;
5157

5158
                    /**
5159
                     * A list of tokens that represent the parameters of the represented type.
5160
                     */
5161
                    private final List<GenericTypeToken> parameterTypeTokens;
5162

5163
                    /**
5164
                     * Creates a type token that represents a parameterized type.
5165
                     *
5166
                     * @param name                The name of the parameterized type's erasure.
5167
                     * @param parameterTypeTokens A list of tokens that represent the parameters of the represented type.
5168
                     */
5169
                    protected ForParameterizedType(String name, List<GenericTypeToken> parameterTypeTokens) {
1✔
5170
                        this.name = name;
1✔
5171
                        this.parameterTypeTokens = parameterTypeTokens;
1✔
5172
                    }
1✔
5173

5174
                    /**
5175
                     * {@inheritDoc}
5176
                     */
5177
                    public Generic toGenericType(TypePool typePool,
5178
                                                 TypeVariableSource typeVariableSource,
5179
                                                 String typePath,
5180
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
5181
                        return new LazyParameterizedType(typePool, typeVariableSource, typePath, annotationTokens, name, parameterTypeTokens);
1✔
5182
                    }
5183

5184
                    /**
5185
                     * {@inheritDoc}
5186
                     */
5187
                    public boolean isPrimaryBound(TypePool typePool) {
5188
                        return !typePool.describe(name).resolve().isInterface();
1✔
5189
                    }
5190

5191
                    /**
5192
                     * {@inheritDoc}
5193
                     */
5194
                    public String getTypePathPrefix() {
5195
                        return String.valueOf(INNER_CLASS_PATH);
1✔
5196
                    }
5197

5198
                    /**
5199
                     * A generic type token to describe a parameterized type description with a generic owner type.
5200
                     */
5201
                    @HashCodeAndEqualsPlugin.Enhance
5202
                    public static class Nested implements GenericTypeToken {
5203

5204
                        /**
5205
                         * The name of the parameterized type's erasure.
5206
                         */
5207
                        private final String name;
5208

5209
                        /**
5210
                         * A list of tokens that represent the parameters of the represented type.
5211
                         */
5212
                        private final List<GenericTypeToken> parameterTypeTokens;
5213

5214
                        /**
5215
                         * A token that describes the described parameterized type's owner type.
5216
                         */
5217
                        private final GenericTypeToken ownerTypeToken;
5218

5219
                        /**
5220
                         * Creates a type token that represents a parameterized type.
5221
                         *
5222
                         * @param name                The name of the parameterized type's erasure.
5223
                         * @param parameterTypeTokens A list of tokens that represent the parameters of the represented type.
5224
                         * @param ownerTypeToken      A token that describes the described parameterized type's owner type.
5225
                         */
5226
                        protected Nested(String name, List<GenericTypeToken> parameterTypeTokens, GenericTypeToken ownerTypeToken) {
1✔
5227
                            this.name = name;
1✔
5228
                            this.parameterTypeTokens = parameterTypeTokens;
1✔
5229
                            this.ownerTypeToken = ownerTypeToken;
1✔
5230
                        }
1✔
5231

5232
                        /**
5233
                         * {@inheritDoc}
5234
                         */
5235
                        public Generic toGenericType(TypePool typePool,
5236
                                                     TypeVariableSource typeVariableSource,
5237
                                                     String typePath,
5238
                                                     Map<String, List<AnnotationToken>> annotationTokens) {
5239
                            return new LazyParameterizedType(typePool, typeVariableSource, typePath, annotationTokens, name, parameterTypeTokens, ownerTypeToken);
1✔
5240
                        }
5241

5242
                        /**
5243
                         * {@inheritDoc}
5244
                         */
5245
                        public String getTypePathPrefix() {
5246
                            return ownerTypeToken.getTypePathPrefix() + INNER_CLASS_PATH;
×
5247
                        }
5248

5249
                        /**
5250
                         * {@inheritDoc}
5251
                         */
5252
                        public boolean isPrimaryBound(TypePool typePool) {
5253
                            return !typePool.describe(name).resolve().isInterface();
×
5254
                        }
5255

5256
                        /**
5257
                         * A lazy description of a parameterized type with an owner type.
5258
                         */
5259
                        protected static class LazyParameterizedType extends Generic.OfParameterizedType {
5260

5261
                            /**
5262
                             * The type pool that is used for locating a generic type.
5263
                             */
5264
                            private final TypePool typePool;
5265

5266
                            /**
5267
                             * The type variable source to use for resolving type variables.
5268
                             */
5269
                            private final TypeVariableSource typeVariableSource;
5270

5271
                            /**
5272
                             * This type's type path.
5273
                             */
5274
                            private final String typePath;
5275

5276
                            /**
5277
                             * A mapping of type annotations for this type.
5278
                             */
5279
                            private final Map<String, List<AnnotationToken>> annotationTokens;
5280

5281
                            /**
5282
                             * The binary name of this parameterized type's raw type.
5283
                             */
5284
                            private final String name;
5285

5286
                            /**
5287
                             * Tokens that represent this parameterized type's parameters.
5288
                             */
5289
                            private final List<GenericTypeToken> parameterTypeTokens;
5290

5291
                            /**
5292
                             * A token that represents this type's owner type.
5293
                             */
5294
                            private final GenericTypeToken ownerTypeToken;
5295

5296
                            /**
5297
                             * Creates a new lazy parameterized type.
5298
                             *
5299
                             * @param typePool            The type pool that is used for locating a generic type.
5300
                             * @param typeVariableSource  The type variable source to use for resolving type variables.
5301
                             * @param typePath            This type's type path.
5302
                             * @param annotationTokens    A mapping of type annotations for this type.
5303
                             * @param name                The binary name of this parameterized type's raw type.
5304
                             * @param parameterTypeTokens Tokens that represent this parameterized type's parameters.
5305
                             * @param ownerTypeToken      A token that represents this type's owner type.
5306
                             */
5307
                            protected LazyParameterizedType(TypePool typePool,
5308
                                                            TypeVariableSource typeVariableSource,
5309
                                                            String typePath,
5310
                                                            Map<String, List<AnnotationToken>> annotationTokens,
5311
                                                            String name,
5312
                                                            List<GenericTypeToken> parameterTypeTokens,
5313
                                                            GenericTypeToken ownerTypeToken) {
1✔
5314
                                this.typePool = typePool;
1✔
5315
                                this.typeVariableSource = typeVariableSource;
1✔
5316
                                this.typePath = typePath;
1✔
5317
                                this.annotationTokens = annotationTokens;
1✔
5318
                                this.name = name;
1✔
5319
                                this.parameterTypeTokens = parameterTypeTokens;
1✔
5320
                                this.ownerTypeToken = ownerTypeToken;
1✔
5321
                            }
1✔
5322

5323
                            /**
5324
                             * {@inheritDoc}
5325
                             */
5326
                            public TypeDescription asErasure() {
5327
                                return typePool.describe(name).resolve();
1✔
5328
                            }
5329

5330
                            /**
5331
                             * {@inheritDoc}
5332
                             */
5333
                            public TypeList.Generic getTypeArguments() {
5334
                                return new LazyTokenList(typePool, typeVariableSource, typePath + ownerTypeToken.getTypePathPrefix(), annotationTokens, parameterTypeTokens);
1✔
5335
                            }
5336

5337
                            /**
5338
                             * {@inheritDoc}
5339
                             */
5340
                            @MaybeNull
5341
                            public Generic getOwnerType() {
5342
                                return ownerTypeToken.toGenericType(typePool, typeVariableSource, typePath, annotationTokens);
1✔
5343
                            }
5344

5345
                            /**
5346
                             * {@inheritDoc}
5347
                             */
5348
                            public AnnotationList getDeclaredAnnotations() {
5349
                                return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath + ownerTypeToken.getTypePathPrefix()));
1✔
5350
                            }
5351
                        }
5352
                    }
5353

5354
                    /**
5355
                     * A generic type description that represents a parameterized type <b>without</b> an enclosing generic owner type.
5356
                     */
5357
                    protected static class LazyParameterizedType extends Generic.OfParameterizedType {
5358

5359
                        /**
5360
                         * The type pool that is used for locating a generic type.
5361
                         */
5362
                        private final TypePool typePool;
5363

5364
                        /**
5365
                         * The type variable source to use for resolving type variables.
5366
                         */
5367
                        private final TypeVariableSource typeVariableSource;
5368

5369
                        /**
5370
                         * This type's type path.
5371
                         */
5372
                        private final String typePath;
5373

5374
                        /**
5375
                         * A mapping of the represent type's annotation tokens.
5376
                         */
5377
                        private final Map<String, List<AnnotationToken>> annotationTokens;
5378

5379
                        /**
5380
                         * The binary name of the raw type.
5381
                         */
5382
                        private final String name;
5383

5384
                        /**
5385
                         * A list of type tokens representing this type's bounds.
5386
                         */
5387
                        private final List<GenericTypeToken> parameterTypeTokens;
5388

5389
                        /**
5390
                         * Creates a new description of a parameterized type.
5391
                         *
5392
                         * @param typePool            The type pool that is used for locating a generic type.
5393
                         * @param typeVariableSource  The type variable source to use for resolving type variables.
5394
                         * @param typePath            This type's type path.
5395
                         * @param annotationTokens    A mapping of the represent type's annotation tokens,
5396
                         * @param name                The binary name of the raw type.
5397
                         * @param parameterTypeTokens A list of type tokens representing this type's bounds.
5398
                         */
5399
                        protected LazyParameterizedType(TypePool typePool,
5400
                                                        TypeVariableSource typeVariableSource,
5401
                                                        String typePath,
5402
                                                        Map<String, List<AnnotationToken>> annotationTokens,
5403
                                                        String name,
5404
                                                        List<GenericTypeToken> parameterTypeTokens) {
1✔
5405
                            this.typePool = typePool;
1✔
5406
                            this.typeVariableSource = typeVariableSource;
1✔
5407
                            this.typePath = typePath;
1✔
5408
                            this.annotationTokens = annotationTokens;
1✔
5409
                            this.name = name;
1✔
5410
                            this.parameterTypeTokens = parameterTypeTokens;
1✔
5411
                        }
1✔
5412

5413
                        /**
5414
                         * {@inheritDoc}
5415
                         */
5416
                        public TypeDescription asErasure() {
5417
                            return typePool.describe(name).resolve();
1✔
5418
                        }
5419

5420
                        /**
5421
                         * {@inheritDoc}
5422
                         */
5423
                        public TypeList.Generic getTypeArguments() {
5424
                            return new LazyTokenList(typePool, typeVariableSource, typePath, annotationTokens, parameterTypeTokens);
1✔
5425
                        }
5426

5427
                        /**
5428
                         * {@inheritDoc}
5429
                         */
5430
                        @MaybeNull
5431
                        public Generic getOwnerType() {
5432
                            TypeDescription ownerType = typePool.describe(name).resolve().getEnclosingType();
1✔
5433
                            return ownerType == null
1✔
5434
                                    ? Generic.UNDEFINED
5435
                                    : ownerType.asGenericType();
1✔
5436
                        }
5437

5438
                        /**
5439
                         * {@inheritDoc}
5440
                         */
5441
                        public AnnotationList getDeclaredAnnotations() {
5442
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
5443
                        }
5444
                    }
5445
                }
5446

5447
                /**
5448
                 * A lazy list of type tokens.
5449
                 */
5450
                class LazyTokenList extends TypeList.Generic.AbstractBase {
5451

5452
                    /**
5453
                     * The type pool that is used for locating a generic type.
5454
                     */
5455
                    private final TypePool typePool;
5456

5457
                    /**
5458
                     * The type variable source to use for resolving type variables.
5459
                     */
5460
                    private final TypeVariableSource typeVariableSource;
5461

5462
                    /**
5463
                     * The represented types' type path to which an index step is added upon resolution.
5464
                     */
5465
                    private final String typePath;
5466

5467
                    /**
5468
                     * A mapping of the represent types' annotation tokens.
5469
                     */
5470
                    private final Map<String, List<AnnotationToken>> annotationTokens;
5471

5472
                    /**
5473
                     * A list of type tokens this list represents.
5474
                     */
5475
                    private final List<GenericTypeToken> genericTypeTokens;
5476

5477
                    /**
5478
                     * Creates a new type list that represents a list of tokenized types.
5479
                     *
5480
                     * @param typePool           The type pool that is used for locating a generic type.
5481
                     * @param typeVariableSource The type variable source to use for resolving type variables.
5482
                     * @param typePath           The represented types' type path to which an index step is added upon resolution.
5483
                     * @param annotationTokens   A mapping of the represent types' annotation tokens,
5484
                     * @param genericTypeTokens  A list of type tokens this list represents.
5485
                     */
5486
                    protected LazyTokenList(TypePool typePool,
5487
                                            TypeVariableSource typeVariableSource,
5488
                                            String typePath,
5489
                                            Map<String, List<AnnotationToken>> annotationTokens,
5490
                                            List<GenericTypeToken> genericTypeTokens) {
1✔
5491
                        this.typePool = typePool;
1✔
5492
                        this.typeVariableSource = typeVariableSource;
1✔
5493
                        this.typePath = typePath;
1✔
5494
                        this.annotationTokens = annotationTokens;
1✔
5495
                        this.genericTypeTokens = genericTypeTokens;
1✔
5496
                    }
1✔
5497

5498
                    /**
5499
                     * {@inheritDoc}
5500
                     */
5501
                    public Generic get(int index) {
5502
                        return genericTypeTokens.get(index).toGenericType(typePool, typeVariableSource, typePath + index + INDEXED_TYPE_DELIMITER, annotationTokens);
1✔
5503
                    }
5504

5505
                    /**
5506
                     * {@inheritDoc}
5507
                     */
5508
                    public int size() {
5509
                        return genericTypeTokens.size();
1✔
5510
                    }
5511

5512
                    /**
5513
                     * A generic type description representing a tokenized wildcard bound.
5514
                     */
5515
                    protected static class ForWildcardBound extends TypeList.Generic.AbstractBase {
5516

5517
                        /**
5518
                         * The type pool that is used for locating a generic type.
5519
                         */
5520
                        private final TypePool typePool;
5521

5522
                        /**
5523
                         * The type variable source to use for resolving type variables.
5524
                         */
5525
                        private final TypeVariableSource typeVariableSource;
5526

5527
                        /**
5528
                         * The represented types' type path to which a wildcard step is added upon resolution.
5529
                         */
5530
                        private final String typePath;
5531

5532
                        /**
5533
                         * A mapping of the represent types' annotation tokens.
5534
                         */
5535
                        private final Map<String, List<AnnotationToken>> annotationTokens;
5536

5537
                        /**
5538
                         * A token representing the wildcard's bound.
5539
                         */
5540
                        private final GenericTypeToken genericTypeToken;
5541

5542
                        /**
5543
                         * @param typePool           The type pool that is used for locating a generic type.
5544
                         * @param typeVariableSource The type variable source to use for resolving type variables.
5545
                         * @param typePath           The represented types' type path to which a wildcard step is added upon resolution.
5546
                         * @param annotationTokens   A mapping of the represent types' annotation tokens,
5547
                         * @param genericTypeToken   A token representing the wildcard's bound.
5548
                         */
5549
                        protected ForWildcardBound(TypePool typePool,
5550
                                                   TypeVariableSource typeVariableSource,
5551
                                                   String typePath,
5552
                                                   Map<String, List<AnnotationToken>> annotationTokens,
5553
                                                   GenericTypeToken genericTypeToken) {
1✔
5554
                            this.typePool = typePool;
1✔
5555
                            this.typeVariableSource = typeVariableSource;
1✔
5556
                            this.typePath = typePath;
1✔
5557
                            this.annotationTokens = annotationTokens;
1✔
5558
                            this.genericTypeToken = genericTypeToken;
1✔
5559
                        }
1✔
5560

5561
                        /**
5562
                         * {@inheritDoc}
5563
                         */
5564
                        public Generic get(int index) {
5565
                            if (index == 0) {
1✔
5566
                                return genericTypeToken.toGenericType(typePool, typeVariableSource, typePath + WILDCARD_TYPE_PATH, annotationTokens);
1✔
5567
                            } else {
5568
                                throw new IndexOutOfBoundsException("index = " + index);
×
5569
                            }
5570
                        }
5571

5572
                        /**
5573
                         * {@inheritDoc}
5574
                         */
5575
                        public int size() {
5576
                            return 1;
1✔
5577
                        }
5578
                    }
5579
                }
5580
            }
5581

5582
            /**
5583
             * A token for representing collected data on an annotation.
5584
             */
5585
            @HashCodeAndEqualsPlugin.Enhance
5586
            protected static class AnnotationToken {
5587

5588
                /**
5589
                 * The descriptor of the represented annotation.
5590
                 */
5591
                private final String descriptor;
5592

5593
                /**
5594
                 * A map of annotation value names to their value representations.
5595
                 */
5596
                private final Map<String, AnnotationValue<?, ?>> values;
5597

5598
                /**
5599
                 * Creates a new annotation token.
5600
                 *
5601
                 * @param descriptor The descriptor of the represented annotation.
5602
                 * @param values     A map of annotation value names to their value representations.
5603
                 */
5604
                protected AnnotationToken(String descriptor, Map<String, AnnotationValue<?, ?>> values) {
1✔
5605
                    this.descriptor = descriptor;
1✔
5606
                    this.values = values;
1✔
5607
                }
1✔
5608

5609
                /**
5610
                 * Returns the annotation type's binary name.
5611
                 *
5612
                 * @return The annotation type's binary name.
5613
                 */
5614
                protected String getBinaryName() {
5615
                    return descriptor.substring(1, descriptor.length() - 1).replace('/', '.');
1✔
5616
                }
5617

5618
                /**
5619
                 * Transforms this token into an annotation description.
5620
                 *
5621
                 * @param typePool The type pool to be used for looking up linked types.
5622
                 * @return An optional description of this annotation's token.
5623
                 */
5624
                private Resolution toAnnotationDescription(TypePool typePool) {
5625
                    TypePool.Resolution resolution = typePool.describe(getBinaryName());
1✔
5626
                    return resolution.isResolved()
1✔
5627
                            ? new Resolution.Simple(new LazyAnnotationDescription(typePool, resolution.resolve(), values))
1✔
5628
                            : new Resolution.Illegal(getBinaryName());
1✔
5629
                }
5630

5631
                /**
5632
                 * A resolution for an annotation tokens. Any annotation is suppressed if its type is not available.
5633
                 * This conforms to the handling of the Java reflection API.
5634
                 */
5635
                protected interface Resolution {
5636

5637
                    /**
5638
                     * Returns {@code true} if the represented annotation could be resolved.
5639
                     *
5640
                     * @return {@code true} if the represented annotation could be resolved.
5641
                     */
5642
                    boolean isResolved();
5643

5644
                    /**
5645
                     * Returns the resolved annotation. This method throws an exception if this instance is not resolved.
5646
                     *
5647
                     * @return The resolved annotation. This method throws an exception if this instance is not resolved.
5648
                     */
5649
                    AnnotationDescription resolve();
5650

5651
                    /**
5652
                     * A simple resolved annotation.
5653
                     */
5654
                    @HashCodeAndEqualsPlugin.Enhance
5655
                    class Simple implements Resolution {
5656

5657
                        /**
5658
                         * The represented annotation description.
5659
                         */
5660
                        private final AnnotationDescription annotationDescription;
5661

5662
                        /**
5663
                         * Creates a new simple resolution.
5664
                         *
5665
                         * @param annotationDescription The represented annotation description.
5666
                         */
5667
                        protected Simple(AnnotationDescription annotationDescription) {
1✔
5668
                            this.annotationDescription = annotationDescription;
1✔
5669
                        }
1✔
5670

5671
                        /**
5672
                         * {@inheritDoc}
5673
                         */
5674
                        public boolean isResolved() {
5675
                            return true;
1✔
5676
                        }
5677

5678
                        /**
5679
                         * {@inheritDoc}
5680
                         */
5681
                        public AnnotationDescription resolve() {
5682
                            return annotationDescription;
1✔
5683
                        }
5684
                    }
5685

5686
                    /**
5687
                     * An illegal resolution.
5688
                     */
5689
                    @HashCodeAndEqualsPlugin.Enhance
5690
                    class Illegal implements Resolution {
5691

5692
                        /**
5693
                         * The annotation's binary type name.
5694
                         */
5695
                        private final String annotationType;
5696

5697
                        /**
5698
                         * Creates a new illegal resolution.
5699
                         *
5700
                         * @param annotationType The annotation's binary type name.
5701
                         */
5702
                        public Illegal(String annotationType) {
1✔
5703
                            this.annotationType = annotationType;
1✔
5704
                        }
1✔
5705

5706
                        /**
5707
                         * {@inheritDoc}
5708
                         */
5709
                        public boolean isResolved() {
5710
                            return false;
1✔
5711
                        }
5712

5713
                        /**
5714
                         * {@inheritDoc}
5715
                         */
5716
                        public AnnotationDescription resolve() {
5717
                            throw new IllegalStateException("Annotation type is not available: " + annotationType);
1✔
5718
                        }
5719
                    }
5720
                }
5721
            }
5722

5723
            /**
5724
             * A token for representing collected data on a field.
5725
             */
5726
            @HashCodeAndEqualsPlugin.Enhance
5727
            protected static class FieldToken {
5728

5729
                /**
5730
                 * The name of the field.
5731
                 */
5732
                private final String name;
5733

5734
                /**
5735
                 * The modifiers of the represented field.
5736
                 */
5737
                private final int modifiers;
5738

5739
                /**
5740
                 * The descriptor of the field.
5741
                 */
5742
                private final String descriptor;
5743

5744
                /**
5745
                 * The field's generic signature as found in the class file or {@code null} if the field is not generic.
5746
                 */
5747
                @UnknownNull
5748
                private final String genericSignature;
5749

5750
                /**
5751
                 * The resolution of this field's generic type.
5752
                 */
5753
                private final GenericTypeToken.Resolution.ForField signatureResolution;
5754

5755
                /**
5756
                 * A mapping of the field type's type annotation tokens.
5757
                 */
5758
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
5759

5760
                /**
5761
                 * A list of annotation tokens representing the annotations of the represented field.
5762
                 */
5763
                private final List<AnnotationToken> annotationTokens;
5764

5765
                /**
5766
                 * Creates a new field token.
5767
                 *
5768
                 * @param name                 The name of the field.
5769
                 * @param modifiers            The modifiers of the represented field.
5770
                 * @param descriptor           The descriptor of the field.
5771
                 * @param genericSignature     The field's generic signature as found in the class file or {@code null} if the field is not generic.
5772
                 * @param typeAnnotationTokens A mapping of the field type's type annotation tokens.
5773
                 * @param annotationTokens     A list of annotation tokens representing the annotations of the represented field.
5774
                 */
5775
                protected FieldToken(String name,
5776
                                     int modifiers,
5777
                                     String descriptor,
5778
                                     @MaybeNull String genericSignature,
5779
                                     Map<String, List<AnnotationToken>> typeAnnotationTokens,
5780
                                     List<AnnotationToken> annotationTokens) {
1✔
5781
                    this.modifiers = modifiers & ~Opcodes.ACC_DEPRECATED;
1✔
5782
                    this.name = name;
1✔
5783
                    this.descriptor = descriptor;
1✔
5784
                    this.genericSignature = genericSignature;
1✔
5785
                    signatureResolution = RAW_TYPES
1✔
5786
                            ? GenericTypeToken.Resolution.Raw.INSTANCE
5787
                            : GenericTypeExtractor.ForSignature.OfField.extract(genericSignature);
1✔
5788
                    this.typeAnnotationTokens = typeAnnotationTokens;
1✔
5789
                    this.annotationTokens = annotationTokens;
1✔
5790
                }
1✔
5791

5792
                /**
5793
                 * Transforms this token into a lazy field description.
5794
                 *
5795
                 * @param lazyTypeDescription The lazy type description to attach this field description to.
5796
                 * @return A field description resembling this field token.
5797
                 */
5798
                private LazyFieldDescription toFieldDescription(LazyTypeDescription lazyTypeDescription) {
5799
                    return lazyTypeDescription.new LazyFieldDescription(name,
1✔
5800
                            modifiers,
5801
                            descriptor,
5802
                            genericSignature,
5803
                            signatureResolution,
5804
                            typeAnnotationTokens,
5805
                            annotationTokens);
5806
                }
5807
            }
5808

5809
            /**
5810
             * A token for representing collected data on a method.
5811
             */
5812
            @HashCodeAndEqualsPlugin.Enhance
5813
            protected static class MethodToken {
5814

5815
                /**
5816
                 * The internal name of the represented method.
5817
                 */
5818
                private final String name;
5819

5820
                /**
5821
                 * The modifiers of the represented method.
5822
                 */
5823
                private final int modifiers;
5824

5825
                /**
5826
                 * The descriptor of the represented method.
5827
                 */
5828
                private final String descriptor;
5829

5830
                /**
5831
                 * The methods's generic signature as found in the class file or {@code null} if the method is not generic.
5832
                 */
5833
                @UnknownNull
5834
                private final String genericSignature;
5835

5836
                /**
5837
                 * The generic type resolution of this method.
5838
                 */
5839
                private final GenericTypeToken.Resolution.ForMethod signatureResolution;
5840

5841
                /**
5842
                 * An array of internal names of the exceptions of the represented method or {@code null} if there
5843
                 * are no such exceptions.
5844
                 */
5845
                @MaybeNull
5846
                private final String[] exceptionName;
5847

5848
                /**
5849
                 * A mapping of the type variables' type annotation tokens by their indices.
5850
                 */
5851
                private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
5852

5853
                /**
5854
                 * A mapping of the type variables' type bounds' type annotation tokens by their indices and each variable's index.
5855
                 */
5856
                private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens;
5857

5858
                /**
5859
                 * A mapping of the return type's type variable tokens.
5860
                 */
5861
                private final Map<String, List<AnnotationToken>> returnTypeAnnotationTokens;
5862

5863
                /**
5864
                 * A mapping of the parameter types' type annotation tokens by their indices.
5865
                 */
5866
                private final Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens;
5867

5868
                /**
5869
                 * A mapping of the exception types' type annotation tokens by their indices.
5870
                 */
5871
                private final Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens;
5872

5873
                /**
5874
                 * A mapping of the receiver type's annotation tokens.
5875
                 */
5876
                private final Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens;
5877

5878
                /**
5879
                 * A list of annotation tokens that are present on the represented method.
5880
                 */
5881
                private final List<AnnotationToken> annotationTokens;
5882

5883
                /**
5884
                 * A map of parameter indices to tokens that represent their annotations.
5885
                 */
5886
                private final Map<Integer, List<AnnotationToken>> parameterAnnotationTokens;
5887

5888
                /**
5889
                 * A list of tokens describing meta data of the method's parameters.
5890
                 */
5891
                private final List<ParameterToken> parameterTokens;
5892

5893
                /**
5894
                 * The default value of this method or {@code null} if there is no such value.
5895
                 */
5896
                @UnknownNull
5897
                private final AnnotationValue<?, ?> defaultValue;
5898

5899
                /**
5900
                 * Creates a new method token.
5901
                 *
5902
                 * @param name                              The name of the method.
5903
                 * @param modifiers                         The modifiers of the represented method.
5904
                 * @param descriptor                        The descriptor of the represented method.
5905
                 * @param genericSignature                  The methods's generic signature as found in the class file or {@code null} if the method is not generic.
5906
                 * @param exceptionName                     An array of internal names of the exceptions of the represented method or {@code null} if
5907
                 *                                          there are no such exceptions.
5908
                 * @param typeVariableAnnotationTokens      A mapping of the type variables' type annotation tokens by their indices.
5909
                 * @param typeVariableBoundAnnotationTokens A mapping of the type variables' type bounds' type annotation tokens by their
5910
                 *                                          index and each variable's index.
5911
                 * @param returnTypeAnnotationTokens        A mapping of the return type's type variable tokens.
5912
                 * @param parameterTypeAnnotationTokens     A mapping of the parameter types' type annotation tokens by their indices.
5913
                 * @param exceptionTypeAnnotationTokens     A mapping of the exception types' type annotation tokens by their indices.
5914
                 * @param receiverTypeAnnotationTokens      A mapping of the receiver type's annotation tokens.
5915
                 * @param annotationTokens                  A list of annotation tokens that are present on the represented method.
5916
                 * @param parameterAnnotationTokens         A map of parameter indices to tokens that represent their annotations.
5917
                 * @param parameterTokens                   A list of tokens describing meta data of the method's parameters.
5918
                 * @param defaultValue                      The default value of this method or {@code null} if there is no such value.
5919
                 */
5920
                protected MethodToken(String name,
5921
                                      int modifiers,
5922
                                      String descriptor,
5923
                                      @MaybeNull String genericSignature,
5924
                                      @MaybeNull String[] exceptionName,
5925
                                      Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
5926
                                      Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens,
5927
                                      Map<String, List<AnnotationToken>> returnTypeAnnotationTokens,
5928
                                      Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens,
5929
                                      Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens,
5930
                                      Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens,
5931
                                      List<AnnotationToken> annotationTokens,
5932
                                      Map<Integer, List<AnnotationToken>> parameterAnnotationTokens,
5933
                                      List<ParameterToken> parameterTokens,
5934
                                      @MaybeNull AnnotationValue<?, ?> defaultValue) {
1✔
5935
                    this.modifiers = modifiers & ~Opcodes.ACC_DEPRECATED;
1✔
5936
                    this.name = name;
1✔
5937
                    this.descriptor = descriptor;
1✔
5938
                    this.genericSignature = genericSignature;
1✔
5939
                    signatureResolution = RAW_TYPES
1✔
5940
                            ? GenericTypeToken.Resolution.Raw.INSTANCE
5941
                            : GenericTypeExtractor.ForSignature.OfMethod.extract(genericSignature);
1✔
5942
                    this.exceptionName = exceptionName;
1✔
5943
                    this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
1✔
5944
                    this.typeVariableBoundAnnotationTokens = typeVariableBoundAnnotationTokens;
1✔
5945
                    this.returnTypeAnnotationTokens = returnTypeAnnotationTokens;
1✔
5946
                    this.parameterTypeAnnotationTokens = parameterTypeAnnotationTokens;
1✔
5947
                    this.exceptionTypeAnnotationTokens = exceptionTypeAnnotationTokens;
1✔
5948
                    this.receiverTypeAnnotationTokens = receiverTypeAnnotationTokens;
1✔
5949
                    this.annotationTokens = annotationTokens;
1✔
5950
                    this.parameterAnnotationTokens = parameterAnnotationTokens;
1✔
5951
                    this.parameterTokens = parameterTokens;
1✔
5952
                    this.defaultValue = defaultValue;
1✔
5953
                }
1✔
5954

5955
                /**
5956
                 * Transforms this method token to a method description that is attached to a lazy type description.
5957
                 *
5958
                 * @param lazyTypeDescription The lazy type description to attach this method description to.
5959
                 * @return A method description representing this method token.
5960
                 */
5961
                private MethodDescription.InDefinedShape toMethodDescription(LazyTypeDescription lazyTypeDescription) {
5962
                    return lazyTypeDescription.new LazyMethodDescription(name,
1✔
5963
                            modifiers,
5964
                            descriptor,
5965
                            genericSignature,
5966
                            signatureResolution,
5967
                            exceptionName,
5968
                            typeVariableAnnotationTokens,
5969
                            typeVariableBoundAnnotationTokens,
5970
                            returnTypeAnnotationTokens,
5971
                            parameterTypeAnnotationTokens,
5972
                            exceptionTypeAnnotationTokens,
5973
                            receiverTypeAnnotationTokens,
5974
                            annotationTokens,
5975
                            parameterAnnotationTokens,
5976
                            parameterTokens,
5977
                            defaultValue);
5978
                }
5979

5980
                /**
5981
                 * A token representing a method's parameter.
5982
                 */
5983
                @HashCodeAndEqualsPlugin.Enhance
5984
                protected static class ParameterToken {
5985

5986
                    /**
5987
                     * Donates an unknown name of a parameter.
5988
                     */
5989
                    @AlwaysNull
5990
                    protected static final String NO_NAME = null;
1✔
5991

5992
                    /**
5993
                     * Donates an unknown modifier of a parameter.
5994
                     */
5995
                    @AlwaysNull
5996
                    protected static final Integer NO_MODIFIERS = null;
1✔
5997

5998
                    /**
5999
                     * The name of the parameter or {@code null} if no explicit name for this parameter is known.
6000
                     */
6001
                    @MaybeNull
6002
                    @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
6003
                    private final String name;
6004

6005
                    /**
6006
                     * The modifiers of the parameter or {@code null} if no modifiers are known for this parameter.
6007
                     */
6008
                    @MaybeNull
6009
                    @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
6010
                    private final Integer modifiers;
6011

6012
                    /**
6013
                     * Creates a parameter token for a parameter without an explicit name and without specific modifiers.
6014
                     */
6015
                    protected ParameterToken() {
6016
                        this(NO_NAME);
1✔
6017
                    }
1✔
6018

6019
                    /**
6020
                     * Creates a parameter token for a parameter with an explicit name and without specific modifiers.
6021
                     *
6022
                     * @param name The name of the parameter.
6023
                     */
6024
                    protected ParameterToken(@MaybeNull String name) {
6025
                        this(name, NO_MODIFIERS);
1✔
6026
                    }
1✔
6027

6028
                    /**
6029
                     * Creates a parameter token for a parameter with an explicit name and with specific modifiers.
6030
                     *
6031
                     * @param name      The name of the parameter.
6032
                     * @param modifiers The modifiers of the parameter.
6033
                     */
6034
                    protected ParameterToken(@MaybeNull String name, @MaybeNull Integer modifiers) {
1✔
6035
                        this.name = name;
1✔
6036
                        this.modifiers = modifiers;
1✔
6037
                    }
1✔
6038

6039
                    /**
6040
                     * Returns the name of the parameter or {@code null} if there is no such name.
6041
                     *
6042
                     * @return The name of the parameter or {@code null} if there is no such name.
6043
                     */
6044
                    @MaybeNull
6045
                    protected String getName() {
6046
                        return name;
1✔
6047
                    }
6048

6049
                    /**
6050
                     * Returns the modifiers of the parameter or {@code null} if no modifiers are known.
6051
                     *
6052
                     * @return The modifiers of the parameter or {@code null} if no modifiers are known.
6053
                     */
6054
                    @MaybeNull
6055
                    protected Integer getModifiers() {
6056
                        return modifiers;
1✔
6057
                    }
6058
                }
6059
            }
6060

6061
            /**
6062
             * A token representing a record component.
6063
             */
6064
            @HashCodeAndEqualsPlugin.Enhance
6065
            protected static class RecordComponentToken {
6066

6067
                /**
6068
                 * The record component's name.
6069
                 */
6070
                private final String name;
6071

6072
                /**
6073
                 * The record component's descriptor.
6074
                 */
6075
                private final String descriptor;
6076

6077
                /**
6078
                 * The record component's generic signature or {@code null} if it is non-generic.
6079
                 */
6080
                @UnknownNull
6081
                private final String genericSignature;
6082

6083
                /**
6084
                 * The record component's signature resolution.
6085
                 */
6086
                private final GenericTypeToken.Resolution.ForRecordComponent signatureResolution;
6087

6088
                /**
6089
                 * A mapping of the record component's type annotations.
6090
                 */
6091
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
6092

6093
                /**
6094
                 * A list of the record component's annotations.
6095
                 */
6096
                private final List<AnnotationToken> annotationTokens;
6097

6098
                /**
6099
                 * Creates a new record component token.
6100
                 *
6101
                 * @param name                 The record component's name.
6102
                 * @param descriptor           The record component's descriptor.
6103
                 * @param genericSignature     The record component's generic signature or {@code null} if it is non-generic.
6104
                 * @param typeAnnotationTokens A mapping of the record component's type annotations.
6105
                 * @param annotationTokens     A list of the record component's annotations.
6106
                 */
6107
                protected RecordComponentToken(String name,
6108
                                               String descriptor,
6109
                                               @MaybeNull String genericSignature,
6110
                                               Map<String, List<AnnotationToken>> typeAnnotationTokens,
6111
                                               List<AnnotationToken> annotationTokens) {
×
6112
                    this.name = name;
×
6113
                    this.descriptor = descriptor;
×
6114
                    this.genericSignature = genericSignature;
×
6115
                    signatureResolution = RAW_TYPES
×
6116
                            ? GenericTypeToken.Resolution.Raw.INSTANCE
6117
                            : GenericTypeExtractor.ForSignature.OfRecordComponent.extract(genericSignature);
×
6118
                    this.typeAnnotationTokens = typeAnnotationTokens;
×
6119
                    this.annotationTokens = annotationTokens;
×
6120
                }
×
6121

6122
                /**
6123
                 * Transforms this record component token to a record component description that is attached to a lazy type description.
6124
                 *
6125
                 * @param lazyTypeDescription The lazy type description to attach this record component description to.
6126
                 * @return A record component description representing this record component token.
6127
                 */
6128
                private RecordComponentDescription.InDefinedShape toRecordComponentDescription(LazyTypeDescription lazyTypeDescription) {
6129
                    return lazyTypeDescription.new LazyRecordComponentDescription(name,
×
6130
                            descriptor,
6131
                            genericSignature,
6132
                            signatureResolution,
6133
                            typeAnnotationTokens,
6134
                            annotationTokens);
6135
                }
6136
            }
6137

6138
            /**
6139
             * A lazy description of an annotation that looks up types from a type pool when required.
6140
             */
6141
            private static class LazyAnnotationDescription extends AnnotationDescription.AbstractBase {
6142

6143
                /**
6144
                 * The type pool for looking up type references.
6145
                 */
6146
                protected final TypePool typePool;
6147

6148
                /**
6149
                 * The type of this annotation.
6150
                 */
6151
                private final TypeDescription annotationType;
6152

6153
                /**
6154
                 * A map of annotation values by their property name.
6155
                 */
6156
                protected final Map<String, AnnotationValue<?, ?>> values;
6157

6158
                /**
6159
                 * Creates a new lazy annotation description.
6160
                 *
6161
                 * @param typePool       The type pool to be used for looking up linked types.
6162
                 * @param annotationType The annotation's type.
6163
                 * @param values         A map of annotation value names to their value representations.
6164
                 */
6165
                private LazyAnnotationDescription(TypePool typePool, TypeDescription annotationType, Map<String, AnnotationValue<?, ?>> values) {
1✔
6166
                    this.typePool = typePool;
1✔
6167
                    this.annotationType = annotationType;
1✔
6168
                    this.values = values;
1✔
6169
                }
1✔
6170

6171
                /**
6172
                 * Represents a list of annotation tokens in form of a list of lazy type annotations. Any annotation with
6173
                 * a type that cannot be loaded from the type pool is ignored and not included in the list. If the provided
6174
                 * {@code tokens} are {@code null}, an empty list is returned.
6175
                 *
6176
                 * @param typePool The type pool to be used for looking up linked types.
6177
                 * @param tokens   The tokens to represent in the list.
6178
                 * @return A list of the loadable annotations.
6179
                 */
6180
                protected static AnnotationList asListOfNullable(TypePool typePool, @MaybeNull List<? extends AnnotationToken> tokens) {
6181
                    return tokens == null
1✔
6182
                            ? new AnnotationList.Empty()
6183
                            : asList(typePool, tokens);
1✔
6184
                }
6185

6186
                /**
6187
                 * Represents a list of annotation tokens in form of a list of lazy type annotations. Any annotation with
6188
                 * a type that cannot be loaded from the type pool is ignored and not included in the list.
6189
                 *
6190
                 * @param typePool The type pool to be used for looking up linked types.
6191
                 * @param tokens   The tokens to represent in the list.
6192
                 * @return A list of the represented annotations.
6193
                 */
6194
                protected static AnnotationList asList(TypePool typePool, List<? extends AnnotationToken> tokens) {
6195
                    List<AnnotationDescription> annotationDescriptions = new ArrayList<AnnotationDescription>(tokens.size());
1✔
6196
                    for (AnnotationToken token : tokens) {
1✔
6197
                        AnnotationToken.Resolution resolution = token.toAnnotationDescription(typePool);
1✔
6198
                        if (resolution.isResolved() && resolution.resolve().getAnnotationType().isAnnotation()) {
1✔
6199
                            annotationDescriptions.add(resolution.resolve());
1✔
6200
                        }
6201
                    }
1✔
6202
                    return new UnresolvedAnnotationList(annotationDescriptions, tokens);
1✔
6203
                }
6204

6205
                /**
6206
                 * {@inheritDoc}
6207
                 */
6208
                public AnnotationValue<?, ?> getValue(MethodDescription.InDefinedShape property) {
6209
                    if (!property.getDeclaringType().asErasure().equals(annotationType)) {
1✔
6210
                        throw new IllegalArgumentException(property + " is not declared by " + getAnnotationType());
1✔
6211
                    }
6212
                    AnnotationValue<?, ?> annotationValue = values.get(property.getName());
1✔
6213
                    if (annotationValue != null) {
1✔
6214
                        return annotationValue.filter(property);
1✔
6215
                    } else {
6216
                        annotationValue = getAnnotationType().getDeclaredMethods().filter(is(property)).getOnly().getDefaultValue();
1✔
6217
                    }
6218
                    return annotationValue == null
1✔
6219
                            ? new AnnotationValue.ForMissingValue<Void, Void>(annotationType, property.getName())
1✔
6220
                            : annotationValue;
6221
                }
6222

6223
                /**
6224
                 * {@inheritDoc}
6225
                 */
6226
                public TypeDescription getAnnotationType() {
6227
                    return annotationType;
1✔
6228
                }
6229

6230
                /**
6231
                 * {@inheritDoc}
6232
                 */
6233
                public <T extends Annotation> Loadable<T> prepare(Class<T> annotationType) {
6234
                    if (!this.annotationType.represents(annotationType)) {
1✔
6235
                        throw new IllegalArgumentException(annotationType + " does not represent " + this.annotationType);
1✔
6236
                    }
6237
                    return new Loadable<T>(typePool, annotationType, values);
1✔
6238
                }
6239

6240
                /**
6241
                 * A loadable version of a lazy annotation description.
6242
                 *
6243
                 * @param <S> The annotation type.
6244
                 */
6245
                private static class Loadable<S extends Annotation> extends LazyAnnotationDescription implements AnnotationDescription.Loadable<S> {
6246

6247
                    /**
6248
                     * The loaded annotation type.
6249
                     */
6250
                    private final Class<S> annotationType;
6251

6252
                    /**
6253
                     * Creates a new loadable version of a lazy annotation.
6254
                     *
6255
                     * @param typePool       The type pool to be used for looking up linked types.
6256
                     * @param annotationType The annotation's loaded type.
6257
                     * @param values         A map of annotation value names to their value representations.
6258
                     */
6259
                    private Loadable(TypePool typePool, Class<S> annotationType, Map<String, AnnotationValue<?, ?>> values) {
6260
                        super(typePool, ForLoadedType.of(annotationType), values);
1✔
6261
                        this.annotationType = annotationType;
1✔
6262
                    }
1✔
6263

6264
                    /**
6265
                     * {@inheritDoc}
6266
                     */
6267
                    public S load() {
6268
                        return AnnotationInvocationHandler.of(annotationType.getClassLoader(), annotationType, values);
1✔
6269
                    }
6270
                }
6271

6272
                /**
6273
                 * A list of annotations which allows for resolving the names of the annotations even if the annotations cannot be resolved.
6274
                 */
6275
                private static class UnresolvedAnnotationList extends AnnotationList.Explicit {
6276

6277
                    /**
6278
                     * The list of represented annotation tokens.
6279
                     */
6280
                    private final List<? extends AnnotationToken> tokens;
6281

6282
                    /**
6283
                     * Creates a list of unresolved annotations.
6284
                     *
6285
                     * @param annotationDescriptions The list of represented annotation descriptions.
6286
                     * @param tokens                 The list of represented annotation tokens.
6287
                     */
6288
                    private UnresolvedAnnotationList(List<? extends AnnotationDescription> annotationDescriptions, List<? extends AnnotationToken> tokens) {
6289
                        super(annotationDescriptions);
1✔
6290
                        this.tokens = tokens;
1✔
6291
                    }
1✔
6292

6293
                    @Override
6294
                    public List<String> asTypeNames() {
6295
                        List<String> typeNames = new ArrayList<String>(tokens.size());
×
6296
                        for (AnnotationToken token : tokens) {
×
6297
                            typeNames.add(token.getBinaryName());
×
6298
                        }
×
6299
                        return typeNames;
×
6300
                    }
6301
                }
6302
            }
6303

6304
            /**
6305
             * A proxy for a lazy annotation value.
6306
             *
6307
             * @param <U> The represented unloaded type.
6308
             * @param <V> The represented loaded type.
6309
             */
6310
            private abstract static class LazyAnnotationValue<U, V> extends AnnotationValue.AbstractBase<U, V> {
6311

6312
                /**
6313
                 * Resolves the actual annotation value.
6314
                 *
6315
                 * @return The actual annotation value.
6316
                 */
6317
                protected abstract AnnotationValue<U, V> doResolve();
6318

6319
                /**
6320
                 * {@inheritDoc}
6321
                 */
6322
                public State getState() {
6323
                    return doResolve().getState();
×
6324
                }
6325

6326
                /**
6327
                 * {@inheritDoc}
6328
                 */
6329
                public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
6330
                    return doResolve().filter(property, typeDefinition);
1✔
6331
                }
6332

6333
                /**
6334
                 * {@inheritDoc}
6335
                 */
6336
                public U resolve() {
6337
                    return doResolve().resolve();
1✔
6338
                }
6339

6340
                /**
6341
                 * {@inheritDoc}
6342
                 */
6343
                public Loaded<V> load(@MaybeNull ClassLoader classLoader) {
6344
                    return doResolve().load(classLoader);
1✔
6345
                }
6346

6347
                @Override
6348
                @CachedReturnPlugin.Enhance("hashCode")
6349
                public int hashCode() {
6350
                    return doResolve().hashCode();
1✔
6351
                }
6352

6353
                @Override
6354
                public boolean equals(@MaybeNull Object other) {
6355
                    return doResolve().equals(other);
×
6356
                }
6357

6358
                @Override
6359
                public String toString() {
6360
                    return doResolve().toString();
1✔
6361
                }
6362

6363
                /**
6364
                 * A proxy for a mismatched type for which the property is not yet know.
6365
                 *
6366
                 * @param <W> The represented unloaded type.
6367
                 * @param <X> The represented loaded type.
6368
                 */
6369
                @HashCodeAndEqualsPlugin.Enhance
6370
                private static class ForMismatchedType<W, X> extends AbstractBase<W, X> {
6371

6372
                    /**
6373
                     * The mismatched value.
6374
                     */
6375
                    private final String value;
6376

6377
                    /**
6378
                     * The mismatched array type.
6379
                     */
6380
                    private final Sort sort;
6381

6382
                    /**
6383
                     * Creates a new mismatched type proxy.
6384
                     *
6385
                     * @param value The mismatched value.
6386
                     * @param sort  The mismatched array type.
6387
                     */
6388
                    private ForMismatchedType(String value, Sort sort) {
×
6389
                        this.value = value;
×
6390
                        this.sort = sort;
×
6391
                    }
×
6392

6393
                    /**
6394
                     * {@inheritDoc}
6395
                     */
6396
                    public State getState() {
6397
                        return State.UNRESOLVED;
×
6398
                    }
6399

6400
                    /**
6401
                     * {@inheritDoc}
6402
                     */
6403
                    public Sort getSort() {
6404
                        return Sort.NONE;
×
6405
                    }
6406

6407
                    /**
6408
                     * {@inheritDoc}
6409
                     */
6410
                    public AnnotationValue<W, X> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
6411
                        return new ForMismatchedType<W, X>(property, property.getReturnType().isArray()
×
6412
                                ? RenderingDispatcher.CURRENT.toArrayErrorString(sort)
×
6413
                                : value);
6414
                    }
6415

6416
                    /**
6417
                     * {@inheritDoc}
6418
                     */
6419
                    public W resolve() {
6420
                        throw new IllegalStateException("Expected filtering of this unresolved property");
×
6421
                    }
6422

6423
                    /**
6424
                     * {@inheritDoc}
6425
                     */
6426
                    public Loaded<X> load(@MaybeNull ClassLoader classLoader) {
6427
                        throw new IllegalStateException("Expected filtering of this unresolved property");
×
6428
                    }
6429
                }
6430

6431
                /**
6432
                 * A lazy annotation value description for a type value.
6433
                 */
6434
                private static class ForTypeValue extends LazyAnnotationValue<TypeDescription, Class<?>> {
6435

6436
                    /**
6437
                     * The type pool to query for the type.
6438
                     */
6439
                    private final TypePool typePool;
6440

6441
                    /**
6442
                     * The type's binary name.
6443
                     */
6444
                    private final String typeName;
6445

6446
                    /**
6447
                     * Creates a new lazy description of an annotation type constant.
6448
                     *
6449
                     * @param typePool The type pool to query for the type.
6450
                     * @param typeName The type's binary name.
6451
                     */
6452
                    private ForTypeValue(TypePool typePool, String typeName) {
1✔
6453
                        this.typePool = typePool;
1✔
6454
                        this.typeName = typeName;
1✔
6455
                    }
1✔
6456

6457
                    /**
6458
                     * {@inheritDoc}
6459
                     */
6460
                    public Sort getSort() {
6461
                        return Sort.TYPE;
×
6462
                    }
6463

6464
                    @Override
6465
                    @CachedReturnPlugin.Enhance("resolved")
6466
                    @SuppressWarnings({"unchecked", "rawtypes"})
6467
                    protected AnnotationValue<TypeDescription, Class<?>> doResolve() {
6468
                        Resolution resolution = typePool.describe(typeName);
1✔
6469
                        return resolution.isResolved()
1✔
6470
                                ? new AnnotationValue.ForTypeDescription(resolution.resolve())
1✔
6471
                                : new AnnotationValue.ForMissingType<TypeDescription, Class<?>>(typeName);
6472
                    }
6473
                }
6474

6475
                /**
6476
                 * A lazy annotation value description for an annotation value.
6477
                 */
6478
                private static class ForAnnotationValue extends LazyAnnotationValue<AnnotationDescription, Annotation> {
6479

6480
                    /**
6481
                     * The type pool to use for resolving the annotation type.
6482
                     */
6483
                    private final TypePool typePool;
6484

6485
                    /**
6486
                     * The annotation token.
6487
                     */
6488
                    private final AnnotationToken annotationToken;
6489

6490
                    /**
6491
                     * Creates a new lazy annotation value.
6492
                     *
6493
                     * @param typePool        The type pool to use for resolving the annotation type.
6494
                     * @param annotationToken The annotation token.
6495
                     */
6496
                    private ForAnnotationValue(TypePool typePool, AnnotationToken annotationToken) {
1✔
6497
                        this.typePool = typePool;
1✔
6498
                        this.annotationToken = annotationToken;
1✔
6499
                    }
1✔
6500

6501
                    /**
6502
                     * {@inheritDoc}
6503
                     */
6504
                    public Sort getSort() {
6505
                        return Sort.ANNOTATION;
×
6506
                    }
6507

6508
                    @Override
6509
                    @CachedReturnPlugin.Enhance("resolved")
6510
                    protected AnnotationValue<AnnotationDescription, Annotation> doResolve() {
6511
                        AnnotationToken.Resolution resolution = annotationToken.toAnnotationDescription(typePool);
1✔
6512
                        if (!resolution.isResolved()) {
1✔
6513
                            return new AnnotationValue.ForMissingType<AnnotationDescription, Annotation>(annotationToken.getBinaryName());
×
6514
                        } else if (!resolution.resolve().getAnnotationType().isAnnotation()) {
1✔
6515
                            return new ForMismatchedType<AnnotationDescription, Annotation>(resolution.resolve().getAnnotationType().getName(), Sort.ANNOTATION);
×
6516
                        } else {
6517
                            return new AnnotationValue.ForAnnotationDescription<Annotation>(resolution.resolve());
1✔
6518
                        }
6519
                    }
6520
                }
6521

6522
                /**
6523
                 * A lazy annotation value description for an enumeration value.
6524
                 */
6525
                private static class ForEnumerationValue extends LazyAnnotationValue<EnumerationDescription, Enum<?>> {
6526

6527
                    /**
6528
                     * The type pool to use for looking up types.
6529
                     */
6530
                    private final TypePool typePool;
6531

6532
                    /**
6533
                     * The binary name of the enumeration type.
6534
                     */
6535
                    private final String typeName;
6536

6537
                    /**
6538
                     * The name of the enumeration.
6539
                     */
6540
                    private final String value;
6541

6542
                    /**
6543
                     * Creates a lazy annotation value description for an enumeration.
6544
                     *
6545
                     * @param typePool The type pool to use for looking up types.
6546
                     * @param typeName The binary name of the enumeration type.
6547
                     * @param value    The name of the enumeration.
6548
                     */
6549
                    private ForEnumerationValue(TypePool typePool, String typeName, String value) {
1✔
6550
                        this.typePool = typePool;
1✔
6551
                        this.typeName = typeName;
1✔
6552
                        this.value = value;
1✔
6553
                    }
1✔
6554

6555
                    /**
6556
                     * {@inheritDoc}
6557
                     */
6558
                    public Sort getSort() {
6559
                        return Sort.ENUMERATION;
×
6560
                    }
6561

6562
                    @Override
6563
                    @CachedReturnPlugin.Enhance("resolved")
6564
                    @SuppressWarnings({"unchecked", "rawtypes"})
6565
                    protected AnnotationValue<EnumerationDescription, Enum<?>> doResolve() {
6566
                        Resolution resolution = typePool.describe(typeName);
1✔
6567
                        if (!resolution.isResolved()) {
1✔
6568
                            return new AnnotationValue.ForMissingType<EnumerationDescription, Enum<?>>(typeName);
×
6569
                        } else if (!resolution.resolve().isEnum()) {
1✔
6570
                            return new ForMismatchedType<EnumerationDescription, Enum<?>>(typeName + "." + value, Sort.ENUMERATION);
×
6571
                        } else if (resolution.resolve().getDeclaredFields().filter(named(value)).isEmpty()) {
1✔
6572
                            return new AnnotationValue.ForEnumerationDescription.WithUnknownConstant(resolution.resolve(), value);
×
6573
                        } else {
6574
                            return new AnnotationValue.ForEnumerationDescription(new EnumerationDescription.Latent(resolution.resolve(), value));
1✔
6575
                        }
6576
                    }
6577
                }
6578

6579
                /**
6580
                 * A lazy projection of an annotation value that contains an array of values.
6581
                 */
6582
                private static class ForArray extends LazyAnnotationValue<Object, Object> {
6583

6584
                    /**
6585
                     * The type pool to use for looking up types.
6586
                     */
6587
                    private final TypePool typePool;
6588

6589
                    /**
6590
                     * A reference to the component type.
6591
                     */
6592
                    private final ComponentTypeReference componentTypeReference;
6593

6594
                    /**
6595
                     * A list of all values of this array value in their order.
6596
                     */
6597
                    private final List<AnnotationValue<?, ?>> values;
6598

6599
                    /**
6600
                     * Creates a lazy projection for a non-primitive array.
6601
                     *
6602
                     * @param typePool               The type pool to use for looking up types.
6603
                     * @param componentTypeReference A reference to the component type.
6604
                     * @param values                 A list of all values of this array value in their order.
6605
                     */
6606
                    private ForArray(TypePool typePool, ComponentTypeReference componentTypeReference, List<AnnotationValue<?, ?>> values) {
1✔
6607
                        this.typePool = typePool;
1✔
6608
                        this.componentTypeReference = componentTypeReference;
1✔
6609
                        this.values = values;
1✔
6610
                    }
1✔
6611

6612
                    /**
6613
                     * {@inheritDoc}
6614
                     */
6615
                    public Sort getSort() {
6616
                        return Sort.ARRAY;
×
6617
                    }
6618

6619
                    @Override
6620
                    @CachedReturnPlugin.Enhance("resolved")
6621
                    protected AnnotationValue<Object, Object> doResolve() {
6622
                        String typeName = componentTypeReference.resolve();
1✔
6623
                        if (typeName != null) {
1✔
6624
                            Resolution resolution = typePool.describe(typeName);
1✔
6625
                            if (!resolution.isResolved()) {
1✔
6626
                                return new ForMissingType<Object, Object>(typeName);
×
6627
                            } else if (resolution.resolve().isEnum()) {
1✔
6628
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(EnumerationDescription.class, resolution.resolve(), values);
1✔
6629
                            } else if (resolution.resolve().isAnnotation()) {
1✔
6630
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(AnnotationDescription.class, resolution.resolve(), values);
1✔
6631
                            } else if (resolution.resolve().represents(Class.class)) {
1✔
6632
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(TypeDescription.class, resolution.resolve(), values);
1✔
6633
                            } else if (resolution.resolve().represents(String.class)) {
1✔
6634
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(String.class, resolution.resolve(), values);
1✔
6635
                            } else if (resolution.resolve().represents(boolean.class)) {
1✔
6636
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(boolean.class, resolution.resolve(), values);
1✔
6637
                            } else if (resolution.resolve().represents(byte.class)) {
1✔
6638
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(byte.class, resolution.resolve(), values);
1✔
6639
                            } else if (resolution.resolve().represents(short.class)) {
1✔
6640
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(short.class, resolution.resolve(), values);
1✔
6641
                            } else if (resolution.resolve().represents(char.class)) {
1✔
6642
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(char.class, resolution.resolve(), values);
1✔
6643
                            } else if (resolution.resolve().represents(int.class)) {
1✔
6644
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(int.class, resolution.resolve(), values);
1✔
6645
                            } else if (resolution.resolve().represents(long.class)) {
1✔
6646
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(long.class, resolution.resolve(), values);
1✔
6647
                            } else if (resolution.resolve().represents(float.class)) {
1✔
6648
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(float.class, resolution.resolve(), values);
1✔
6649
                            } else if (resolution.resolve().represents(double.class)) {
1✔
6650
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(double.class, resolution.resolve(), values);
1✔
6651
                            }
6652
                        }
6653
                        Sort sort = Sort.NONE;
×
6654
                        ListIterator<AnnotationValue<?, ?>> iterator = values.listIterator(values.size());
×
6655
                        while (iterator.hasPrevious() && !sort.isDefined()) {
×
6656
                            sort = iterator.previous().getSort();
×
6657
                        }
6658
                        return new ForMismatchedType<Object, Object>(RenderingDispatcher.CURRENT.toArrayErrorString(sort), sort);
1✔
6659
                    }
6660
                }
6661
            }
6662

6663
            /**
6664
             * An implementation of a {@link PackageDescription} that only
6665
             * loads its annotations on requirement.
6666
             */
6667
            private static class LazyPackageDescription extends PackageDescription.AbstractBase {
6668

6669
                /**
6670
                 * The type pool to use for look-ups.
6671
                 */
6672
                private final TypePool typePool;
6673

6674
                /**
6675
                 * The name of the package.
6676
                 */
6677
                private final String name;
6678

6679
                /**
6680
                 * Creates a new lazy package description.
6681
                 *
6682
                 * @param typePool The type pool to use for look-ups.
6683
                 * @param name     The name of the package.
6684
                 */
6685
                private LazyPackageDescription(TypePool typePool, String name) {
1✔
6686
                    this.typePool = typePool;
1✔
6687
                    this.name = name;
1✔
6688
                }
1✔
6689

6690
                /**
6691
                 * {@inheritDoc}
6692
                 */
6693
                public AnnotationList getDeclaredAnnotations() {
6694
                    Resolution resolution = typePool.describe(name + "." + PackageDescription.PACKAGE_CLASS_NAME);
1✔
6695
                    return resolution.isResolved()
1✔
6696
                            ? resolution.resolve().getDeclaredAnnotations()
1✔
6697
                            : new AnnotationList.Empty();
6698
                }
6699

6700
                /**
6701
                 * {@inheritDoc}
6702
                 */
6703
                public String getName() {
6704
                    return name;
1✔
6705
                }
6706
            }
6707

6708
            /**
6709
             * A list that is constructing {@link LazyTypeDescription}s.
6710
             */
6711
            protected static class LazyTypeList extends TypeList.AbstractBase {
6712

6713
                /**
6714
                 * The type pool to use for locating types.
6715
                 */
6716
                private final TypePool typePool;
6717

6718
                /**
6719
                 * A list of type descriptors that this list represents.
6720
                 */
6721
                private final List<String> descriptors;
6722

6723
                /**
6724
                 * Creates a list of lazy type descriptions.
6725
                 *
6726
                 * @param typePool    The type pool to use for locating types.
6727
                 * @param descriptors A list of type descriptors that this list represents.
6728
                 */
6729
                protected LazyTypeList(TypePool typePool, List<String> descriptors) {
1✔
6730
                    this.typePool = typePool;
1✔
6731
                    this.descriptors = descriptors;
1✔
6732
                }
1✔
6733

6734
                /**
6735
                 * {@inheritDoc}
6736
                 */
6737
                public TypeDescription get(int index) {
6738
                    return TokenizedGenericType.toErasure(typePool, descriptors.get(index));
1✔
6739
                }
6740

6741
                /**
6742
                 * {@inheritDoc}
6743
                 */
6744
                public int size() {
6745
                    return descriptors.size();
1✔
6746
                }
6747

6748
                /**
6749
                 * {@inheritDoc}
6750
                 */
6751
                @MaybeNull
6752
                public String[] toInternalNames() {
6753
                    String[] internalName = new String[descriptors.size()];
1✔
6754
                    int index = 0;
1✔
6755
                    for (String descriptor : descriptors) {
1✔
6756
                        internalName[index++] = Type.getType(descriptor).getInternalName();
1✔
6757
                    }
1✔
6758
                    return internalName.length == 0
1✔
6759
                            ? NO_INTERFACES
6760
                            : internalName;
6761
                }
6762

6763
                /**
6764
                 * {@inheritDoc}
6765
                 */
6766
                public int getStackSize() {
6767
                    int stackSize = 0;
1✔
6768
                    for (String descriptor : descriptors) {
1✔
6769
                        stackSize += Type.getType(descriptor).getSize();
1✔
6770
                    }
1✔
6771
                    return stackSize;
1✔
6772
                }
6773
            }
6774

6775
            /**
6776
             * A lazy list that represents all nest members of the represented type.
6777
             */
6778
            protected static class LazyNestMemberList extends TypeList.AbstractBase {
6779

6780
                /**
6781
                 * The type for which the nest members are represented.
6782
                 */
6783
                private final TypeDescription typeDescription;
6784

6785
                /**
6786
                 * The type pool to use for looking up types.
6787
                 */
6788
                private final TypePool typePool;
6789

6790
                /**
6791
                 * The binary names of all nest members of this nest mate group excluding the represented type.
6792
                 */
6793
                private final List<String> nestMembers;
6794

6795
                /**
6796
                 * Creates a new lazy type list of all nest members of this group.
6797
                 *
6798
                 * @param typeDescription The type for which the nest members are represented.
6799
                 * @param typePool        The type pool to use for looking up types.
6800
                 * @param nestMembers     The binary names of all nest members of this nest mate group excluding the represented type.
6801
                 */
6802
                protected LazyNestMemberList(TypeDescription typeDescription, TypePool typePool, List<String> nestMembers) {
1✔
6803
                    this.typeDescription = typeDescription;
1✔
6804
                    this.typePool = typePool;
1✔
6805
                    this.nestMembers = nestMembers;
1✔
6806
                }
1✔
6807

6808
                /**
6809
                 * {@inheritDoc}
6810
                 */
6811
                public TypeDescription get(int index) {
6812
                    return index == 0
1✔
6813
                            ? typeDescription
6814
                            : typePool.describe(nestMembers.get(index - 1)).resolve();
×
6815
                }
6816

6817
                /**
6818
                 * {@inheritDoc}
6819
                 */
6820
                public int size() {
6821
                    return nestMembers.size() + 1;
1✔
6822
                }
6823

6824
                /**
6825
                 * {@inheritDoc}
6826
                 */
6827
                public String[] toInternalNames() {
6828
                    String[] internalName = new String[nestMembers.size() + 1];
×
6829
                    internalName[0] = typeDescription.getInternalName();
×
6830
                    int index = 1;
×
6831
                    for (String name : nestMembers) {
×
6832
                        internalName[index++] = name.replace('.', '/');
×
6833
                    }
×
6834
                    return internalName;
×
6835
                }
6836

6837
                /**
6838
                 * {@inheritDoc}
6839
                 */
6840
                public int getStackSize() {
6841
                    return nestMembers.size() + 1;
×
6842
                }
6843
            }
6844

6845
            /**
6846
             * A representation of a generic type that is described by a {@link GenericTypeToken}.
6847
             */
6848
            protected static class TokenizedGenericType extends Generic.LazyProjection.WithEagerNavigation {
6849

6850
                /**
6851
                 * The type pool to use for locating referenced types.
6852
                 */
6853
                private final TypePool typePool;
6854

6855
                /**
6856
                 * The token that describes the represented generic type.
6857
                 */
6858
                private final GenericTypeToken genericTypeToken;
6859

6860
                /**
6861
                 * A descriptor of the generic type's raw type.
6862
                 */
6863
                private final String rawTypeDescriptor;
6864

6865
                /**
6866
                 * The tokenized type's type annotation tokens.
6867
                 */
6868
                private final Map<String, List<AnnotationToken>> annotationTokens;
6869

6870
                /**
6871
                 * The closest type variable source of this generic type's declaration context.
6872
                 */
6873
                private final TypeVariableSource typeVariableSource;
6874

6875
                /**
6876
                 * Creates a new tokenized generic type.
6877
                 *
6878
                 * @param typePool           The type pool to use for locating referenced types.
6879
                 * @param genericTypeToken   The token that describes the represented generic type.
6880
                 * @param rawTypeDescriptor  A descriptor of the generic type's erasure.
6881
                 * @param annotationTokens   The tokenized type's type annotation tokens.
6882
                 * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6883
                 */
6884
                protected TokenizedGenericType(TypePool typePool,
6885
                                               GenericTypeToken genericTypeToken,
6886
                                               String rawTypeDescriptor,
6887
                                               Map<String, List<AnnotationToken>> annotationTokens,
6888
                                               TypeVariableSource typeVariableSource) {
1✔
6889
                    this.typePool = typePool;
1✔
6890
                    this.genericTypeToken = genericTypeToken;
1✔
6891
                    this.rawTypeDescriptor = rawTypeDescriptor;
1✔
6892
                    this.annotationTokens = annotationTokens;
1✔
6893
                    this.typeVariableSource = typeVariableSource;
1✔
6894
                }
1✔
6895

6896
                /**
6897
                 * Creates a new generic type description for a tokenized generic type.
6898
                 *
6899
                 * @param typePool           The type pool to use for locating referenced types.
6900
                 * @param genericTypeToken   The token that describes the represented generic type.
6901
                 * @param rawTypeDescriptor  A descriptor of the generic type's erasure.
6902
                 * @param annotationTokens   The tokenized type's type annotation tokens or {@code null} if no such annotations are defined.
6903
                 * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6904
                 * @return A suitable generic type.
6905
                 */
6906
                protected static Generic of(TypePool typePool,
6907
                                            GenericTypeToken genericTypeToken,
6908
                                            String rawTypeDescriptor,
6909
                                            @MaybeNull Map<String, List<AnnotationToken>> annotationTokens,
6910
                                            TypeVariableSource typeVariableSource) {
6911
                    return new TokenizedGenericType(typePool,
1✔
6912
                            genericTypeToken,
6913
                            rawTypeDescriptor,
6914
                            annotationTokens == null
6915
                                    ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
6916
                                    : annotationTokens,
6917
                            typeVariableSource);
6918
                }
6919

6920
                /**
6921
                 * Creates a type description from a descriptor by looking up the corresponding type.
6922
                 *
6923
                 * @param typePool   The type pool to use for locating a type.
6924
                 * @param descriptor The descriptor to interpret.
6925
                 * @return A description of the type represented by the descriptor.
6926
                 */
6927
                protected static TypeDescription toErasure(TypePool typePool, String descriptor) {
6928
                    Type type = Type.getType(descriptor);
1✔
6929
                    return typePool.describe(type.getSort() == Type.ARRAY
1✔
6930
                            ? type.getInternalName().replace('/', '.')
1✔
6931
                            : type.getClassName()).resolve();
1✔
6932
                }
6933

6934
                @Override
6935
                @CachedReturnPlugin.Enhance("resolved")
6936
                protected Generic resolve() {
6937
                    return genericTypeToken.toGenericType(typePool, typeVariableSource, GenericTypeToken.EMPTY_TYPE_PATH, annotationTokens);
1✔
6938
                }
6939

6940
                /**
6941
                 * {@inheritDoc}
6942
                 */
6943
                @CachedReturnPlugin.Enhance("erasure")
6944
                public TypeDescription asErasure() {
6945
                    return toErasure(typePool, rawTypeDescriptor);
1✔
6946
                }
6947

6948
                /**
6949
                 * {@inheritDoc}
6950
                 */
6951
                public AnnotationList getDeclaredAnnotations() {
6952
                    return resolve().getDeclaredAnnotations();
1✔
6953
                }
6954

6955
                /**
6956
                 * A tokenized list of generic types.
6957
                 */
6958
                protected static class TokenList extends TypeList.Generic.AbstractBase {
6959

6960
                    /**
6961
                     * The type pool to use for locating types.
6962
                     */
6963
                    private final TypePool typePool;
6964

6965
                    /**
6966
                     * Type tokens that describe the represented generic types.
6967
                     */
6968
                    private final List<GenericTypeToken> genericTypeTokens;
6969

6970
                    /**
6971
                     * A list of the generic types' erasures.
6972
                     */
6973
                    private final List<String> rawTypeDescriptors;
6974

6975
                    /**
6976
                     * The closest type variable source of this generic type's declaration context.
6977
                     */
6978
                    private final TypeVariableSource typeVariableSource;
6979

6980
                    /**
6981
                     * A mapping of each type's type annotation tokens by its index.
6982
                     */
6983
                    private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
6984

6985
                    /**
6986
                     * Creates a list of tokenized generic types.
6987
                     *
6988
                     * @param typePool           The type pool to use for locating type descriptions.
6989
                     * @param genericTypeTokens  A list of tokens describing the represented generic types.
6990
                     * @param annotationTokens   A mapping of each type's type annotation tokens by its index.
6991
                     * @param rawTypeDescriptors A list of the generic types' erasures.
6992
                     * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6993
                     */
6994
                    private TokenList(TypePool typePool,
6995
                                      List<GenericTypeToken> genericTypeTokens,
6996
                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
6997
                                      List<String> rawTypeDescriptors,
6998
                                      TypeVariableSource typeVariableSource) {
1✔
6999
                        this.typePool = typePool;
1✔
7000
                        this.genericTypeTokens = genericTypeTokens;
1✔
7001
                        this.annotationTokens = annotationTokens;
1✔
7002
                        this.rawTypeDescriptors = rawTypeDescriptors;
1✔
7003
                        this.typeVariableSource = typeVariableSource;
1✔
7004
                    }
1✔
7005

7006
                    /**
7007
                     * {@inheritDoc}
7008
                     */
7009
                    public Generic get(int index) {
7010
                        return rawTypeDescriptors.size() == genericTypeTokens.size()
1✔
7011
                                ? TokenizedGenericType.of(typePool, genericTypeTokens.get(index), rawTypeDescriptors.get(index), annotationTokens.get(index), typeVariableSource)
1✔
7012
                                : TokenizedGenericType.toErasure(typePool, rawTypeDescriptors.get(index)).asGenericType();
1✔
7013
                    }
7014

7015
                    /**
7016
                     * {@inheritDoc}
7017
                     */
7018
                    public int size() {
7019
                        return rawTypeDescriptors.size();
1✔
7020
                    }
7021

7022
                    /**
7023
                     * {@inheritDoc}
7024
                     */
7025
                    public TypeList asErasures() {
7026
                        return new LazyTypeList(typePool, rawTypeDescriptors);
1✔
7027
                    }
7028
                }
7029

7030
                /**
7031
                 * A list of tokenized type variables.
7032
                 */
7033
                protected static class TypeVariableList extends TypeList.Generic.AbstractBase {
7034

7035
                    /**
7036
                     * The type pool to use for locating types.
7037
                     */
7038
                    private final TypePool typePool;
7039

7040
                    /**
7041
                     * Type tokens that describe the represented type variables.
7042
                     */
7043
                    private final List<GenericTypeToken.OfFormalTypeVariable> typeVariables;
7044

7045
                    /**
7046
                     * The type variable source of the represented type variables.
7047
                     */
7048
                    private final TypeVariableSource typeVariableSource;
7049

7050
                    /**
7051
                     * A mapping of the type variables' type annotation tokens by their indices.
7052
                     */
7053
                    private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
7054

7055
                    /**
7056
                     * A mapping of the type variables' bound types' annotation tokens by their indices and each type variable's index..
7057
                     */
7058
                    private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens;
7059

7060
                    /**
7061
                     * Creates a list of type variables.
7062
                     *
7063
                     * @param typePool              The type pool to use for locating types.
7064
                     * @param typeVariables         Type tokens that describe the represented generic types.
7065
                     * @param typeVariableSource    The type variable source of the represented type variables.
7066
                     * @param annotationTokens      A mapping of the type variables' type annotation tokens by their indices.
7067
                     * @param boundAnnotationTokens A mapping of the type variables' bound types' annotation tokens by their indices
7068
                     *                              and each type variable's index.
7069
                     */
7070
                    protected TypeVariableList(TypePool typePool,
7071
                                               List<GenericTypeToken.OfFormalTypeVariable> typeVariables,
7072
                                               TypeVariableSource typeVariableSource,
7073
                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
7074
                                               Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
1✔
7075
                        this.typePool = typePool;
1✔
7076
                        this.typeVariables = typeVariables;
1✔
7077
                        this.typeVariableSource = typeVariableSource;
1✔
7078
                        this.annotationTokens = annotationTokens;
1✔
7079
                        this.boundAnnotationTokens = boundAnnotationTokens;
1✔
7080
                    }
1✔
7081

7082
                    /**
7083
                     * {@inheritDoc}
7084
                     */
7085
                    public Generic get(int index) {
7086
                        return typeVariables.get(index).toGenericType(typePool, typeVariableSource, annotationTokens.get(index), boundAnnotationTokens.get(index));
1✔
7087
                    }
7088

7089
                    /**
7090
                     * {@inheritDoc}
7091
                     */
7092
                    public int size() {
7093
                        return typeVariables.size();
1✔
7094
                    }
7095
                }
7096

7097
                /**
7098
                 * A lazy description of a non-well-defined described generic type.
7099
                 */
7100
                protected static class Malformed extends LazyProjection.WithEagerNavigation {
7101

7102
                    /**
7103
                     * The type pool to use for locating types.
7104
                     */
7105
                    private final TypePool typePool;
7106

7107
                    /**
7108
                     * The descriptor of the type erasure.
7109
                     */
7110
                    private final String rawTypeDescriptor;
7111

7112
                    /**
7113
                     * Creates a lazy description of a non-well-defined described generic type.
7114
                     *
7115
                     * @param typePool          The type pool to use for locating types.
7116
                     * @param rawTypeDescriptor The descriptor of the type erasure.
7117
                     */
7118
                    protected Malformed(TypePool typePool, String rawTypeDescriptor) {
1✔
7119
                        this.typePool = typePool;
1✔
7120
                        this.rawTypeDescriptor = rawTypeDescriptor;
1✔
7121
                    }
1✔
7122

7123
                    @Override
7124
                    protected Generic resolve() {
7125
                        throw new GenericSignatureFormatError();
1✔
7126
                    }
7127

7128
                    /**
7129
                     * {@inheritDoc}
7130
                     */
7131
                    public TypeDescription asErasure() {
7132
                        return toErasure(typePool, rawTypeDescriptor);
×
7133
                    }
7134

7135
                    /**
7136
                     * {@inheritDoc}
7137
                     */
7138
                    public AnnotationList getDeclaredAnnotations() {
7139
                        throw new GenericSignatureFormatError();
×
7140
                    }
7141

7142
                    /**
7143
                     * A tokenized list of non-well-defined generic types.
7144
                     */
7145
                    protected static class TokenList extends TypeList.Generic.AbstractBase {
7146

7147
                        /**
7148
                         * The type pool to use for locating types.
7149
                         */
7150
                        private final TypePool typePool;
7151

7152
                        /**
7153
                         * A list of descriptors of the list's types' erasures.
7154
                         */
7155
                        private final List<String> rawTypeDescriptors;
7156

7157
                        /**
7158
                         * Creates a new tokenized list of generic types.
7159
                         *
7160
                         * @param typePool           The type pool to use for locating types.
7161
                         * @param rawTypeDescriptors A list of descriptors of the list's types' erasures.
7162
                         */
7163
                        protected TokenList(TypePool typePool, List<String> rawTypeDescriptors) {
1✔
7164
                            this.typePool = typePool;
1✔
7165
                            this.rawTypeDescriptors = rawTypeDescriptors;
1✔
7166
                        }
1✔
7167

7168
                        /**
7169
                         * {@inheritDoc}
7170
                         */
7171
                        public Generic get(int index) {
7172
                            return new Malformed(typePool, rawTypeDescriptors.get(index));
1✔
7173
                        }
7174

7175
                        /**
7176
                         * {@inheritDoc}
7177
                         */
7178
                        public int size() {
7179
                            return rawTypeDescriptors.size();
1✔
7180
                        }
7181

7182
                        /**
7183
                         * {@inheritDoc}
7184
                         */
7185
                        public TypeList asErasures() {
7186
                            return new LazyTypeList(typePool, rawTypeDescriptors);
×
7187
                        }
7188
                    }
7189

7190
                }
7191
            }
7192

7193
            /**
7194
             * A lazy field description that only resolved type references when required.
7195
             */
7196
            private class LazyFieldDescription extends FieldDescription.InDefinedShape.AbstractBase {
7197

7198
                /**
7199
                 * The name of the field.
7200
                 */
7201
                private final String name;
7202

7203
                /**
7204
                 * The modifiers of the field.
7205
                 */
7206
                private final int modifiers;
7207

7208
                /**
7209
                 * The descriptor of this field's type.
7210
                 */
7211
                private final String descriptor;
7212

7213
                /**
7214
                 * The field's generic signature as found in the class file or {@code null} if the field is not generic.
7215
                 */
7216
                @MaybeNull
7217
                private final String genericSignature;
7218

7219
                /**
7220
                 * A resolution of this field's generic type.
7221
                 */
7222
                private final GenericTypeToken.Resolution.ForField signatureResolution;
7223

7224
                /**
7225
                 * A mapping of the field type's type annotation tokens.
7226
                 */
7227
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
7228

7229
                /**
7230
                 * A list of annotation descriptions of this field.
7231
                 */
7232
                private final List<AnnotationToken> annotationTokens;
7233

7234
                /**
7235
                 * Creates a new lazy field description.
7236
                 *
7237
                 * @param name                 The name of the field.
7238
                 * @param modifiers            The modifiers of the field.
7239
                 * @param descriptor           The descriptor of this field's type.
7240
                 * @param genericSignature     The field's generic signature as found in the class file or {@code null} if the field is not generic.
7241
                 * @param signatureResolution  A resolution of this field's generic type.
7242
                 * @param typeAnnotationTokens A mapping of the field type's type annotation tokens.
7243
                 * @param annotationTokens     A list of annotation descriptions of this field.
7244
                 */
7245
                private LazyFieldDescription(String name,
7246
                                             int modifiers,
7247
                                             String descriptor,
7248
                                             @MaybeNull String genericSignature,
7249
                                             GenericTypeToken.Resolution.ForField signatureResolution,
7250
                                             Map<String, List<AnnotationToken>> typeAnnotationTokens,
7251
                                             List<AnnotationToken> annotationTokens) {
1✔
7252
                    this.modifiers = modifiers;
1✔
7253
                    this.name = name;
1✔
7254
                    this.descriptor = descriptor;
1✔
7255
                    this.genericSignature = genericSignature;
1✔
7256
                    this.signatureResolution = signatureResolution;
1✔
7257
                    this.typeAnnotationTokens = typeAnnotationTokens;
1✔
7258
                    this.annotationTokens = annotationTokens;
1✔
7259
                }
1✔
7260

7261
                /**
7262
                 * {@inheritDoc}
7263
                 */
7264
                public Generic getType() {
7265
                    return signatureResolution.resolveFieldType(descriptor, typePool, typeAnnotationTokens, this);
1✔
7266
                }
7267

7268
                /**
7269
                 * {@inheritDoc}
7270
                 */
7271
                public AnnotationList getDeclaredAnnotations() {
7272
                    return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
1✔
7273
                }
7274

7275
                /**
7276
                 * {@inheritDoc}
7277
                 */
7278
                public String getName() {
7279
                    return name;
1✔
7280
                }
7281

7282
                /**
7283
                 * {@inheritDoc}
7284
                 */
7285
                @Nonnull
7286
                public TypeDescription getDeclaringType() {
7287
                    return LazyTypeDescription.this;
1✔
7288
                }
7289

7290
                /**
7291
                 * {@inheritDoc}
7292
                 */
7293
                public int getModifiers() {
7294
                    return modifiers;
1✔
7295
                }
7296

7297
                /**
7298
                 * {@inheritDoc}
7299
                 */
7300
                @MaybeNull
7301
                public String getGenericSignature() {
7302
                    return genericSignature;
×
7303
                }
7304
            }
7305

7306
            /**
7307
             * A lazy representation of a method that resolves references to types only on demand.
7308
             */
7309
            private class LazyMethodDescription extends MethodDescription.InDefinedShape.AbstractBase {
7310

7311
                /**
7312
                 * The internal name of this method.
7313
                 */
7314
                private final String internalName;
7315

7316
                /**
7317
                 * The modifiers of this method.
7318
                 */
7319
                private final int modifiers;
7320

7321
                /**
7322
                 * The descriptor of the return type.
7323
                 */
7324
                private final String returnTypeDescriptor;
7325

7326
                /**
7327
                 * The method's generic signature as found in the class file or {@code null} if the method is not generic.
7328
                 */
7329
                @MaybeNull
7330
                private final String genericSignature;
7331

7332
                /**
7333
                 * The generic type token of this method.
7334
                 */
7335
                private final GenericTypeToken.Resolution.ForMethod signatureResolution;
7336

7337
                /**
7338
                 * A list of type descriptions of this method's parameters.
7339
                 */
7340
                private final List<String> parameterTypeDescriptors;
7341

7342
                /**
7343
                 * A list of type descriptions of this method's exception types.
7344
                 */
7345
                private final List<String> exceptionTypeDescriptors;
7346

7347
                /**
7348
                 * A mapping of the type variables' type annotation tokens by their indices.
7349
                 */
7350
                private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
7351

7352
                /**
7353
                 * A mapping of the type variables' type bounds' type annotation tokens by their indices and each variable's index.
7354
                 */
7355
                private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens;
7356

7357
                /**
7358
                 * A mapping of the return type's type variable tokens.
7359
                 */
7360
                private final Map<String, List<AnnotationToken>> returnTypeAnnotationTokens;
7361

7362
                /**
7363
                 * A mapping of the parameter types' type annotation tokens by their indices.
7364
                 */
7365
                private final Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens;
7366

7367
                /**
7368
                 * A mapping of the exception types' type annotation tokens by their indices.
7369
                 */
7370
                private final Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens;
7371

7372
                /**
7373
                 * A mapping of the receiver type's type annotation tokens.
7374
                 */
7375
                private final Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens;
7376

7377
                /**
7378
                 * The annotation tokens representing the method's annotations.
7379
                 */
7380
                private final List<AnnotationToken> annotationTokens;
7381

7382
                /**
7383
                 * The annotation tokens representing the parameter's annotation. Every index can
7384
                 * contain {@code null} if a parameter does not define any annotations.
7385
                 */
7386
                private final Map<Integer, List<AnnotationToken>> parameterAnnotationTokens;
7387

7388
                /**
7389
                 * An array of parameter names which may be {@code null} if no explicit name is known for a parameter.
7390
                 */
7391
                private final String[] parameterNames;
7392

7393
                /**
7394
                 * An array of parameter modifiers which may be {@code null} if no modifiers is known.
7395
                 */
7396
                private final Integer[] parameterModifiers;
7397

7398
                /**
7399
                 * The default value of this method or {@code null} if no such value exists.
7400
                 */
7401
                @MaybeNull
7402
                private final AnnotationValue<?, ?> defaultValue;
7403

7404
                /**
7405
                 * Creates a new lazy method description.
7406
                 *
7407
                 * @param internalName                      The internal name of this method.
7408
                 * @param modifiers                         The modifiers of the represented method.
7409
                 * @param descriptor                        The method descriptor of this method.
7410
                 * @param genericSignature                  The method's generic signature as found in the class file or {@code null} if the method is not generic.
7411
                 * @param signatureResolution               The generic type token of this method.
7412
                 * @param exceptionTypeInternalName         The internal names of the exceptions that are declared by this
7413
                 *                                          method or {@code null} if no exceptions are declared by this
7414
                 *                                          method.
7415
                 * @param typeVariableAnnotationTokens      A mapping of the type variables' type annotation tokens by their indices.
7416
                 * @param typeVariableBoundAnnotationTokens A mapping of the type variables' type bounds' type annotation tokens by their
7417
                 *                                          index and each variable's index.
7418
                 * @param returnTypeAnnotationTokens        A mapping of the return type's type variable tokens.
7419
                 * @param parameterTypeAnnotationTokens     A mapping of the parameter types' type annotation tokens by their indices.
7420
                 * @param exceptionTypeAnnotationTokens     A mapping of the exception types' type annotation tokens by their indices.
7421
                 * @param receiverTypeAnnotationTokens      A mapping of the receiver type's type annotation tokens.
7422
                 * @param annotationTokens                  The annotation tokens representing the method's annotations.
7423
                 * @param parameterAnnotationTokens         The annotation tokens representing the parameter's annotation. Every
7424
                 *                                          index can contain {@code null} if a parameter does not define any annotations.
7425
                 * @param parameterTokens                   A list of parameter tokens which might be empty or even out of sync
7426
                 *                                          with the actual parameters if the debugging information found in a
7427
                 *                                          class was corrupt.
7428
                 * @param defaultValue                      The default value of this method or {@code null} if there is no
7429
                 */
7430
                private LazyMethodDescription(String internalName,
7431
                                              int modifiers,
7432
                                              String descriptor,
7433
                                              @MaybeNull String genericSignature,
7434
                                              GenericTypeToken.Resolution.ForMethod signatureResolution,
7435
                                              @MaybeNull String[] exceptionTypeInternalName,
7436
                                              Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
7437
                                              Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens,
7438
                                              Map<String, List<AnnotationToken>> returnTypeAnnotationTokens,
7439
                                              Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens,
7440
                                              Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens,
7441
                                              Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens,
7442
                                              List<AnnotationToken> annotationTokens,
7443
                                              Map<Integer, List<AnnotationToken>> parameterAnnotationTokens,
7444
                                              List<MethodToken.ParameterToken> parameterTokens,
7445
                                              @MaybeNull AnnotationValue<?, ?> defaultValue) {
1✔
7446
                    this.modifiers = modifiers;
1✔
7447
                    this.internalName = internalName;
1✔
7448
                    Type methodType = Type.getMethodType(descriptor);
1✔
7449
                    Type returnType = methodType.getReturnType();
1✔
7450
                    Type[] parameterType = methodType.getArgumentTypes();
1✔
7451
                    returnTypeDescriptor = returnType.getDescriptor();
1✔
7452
                    parameterTypeDescriptors = new ArrayList<String>(parameterType.length);
1✔
7453
                    for (Type type : parameterType) {
1✔
7454
                        parameterTypeDescriptors.add(type.getDescriptor());
1✔
7455
                    }
7456
                    this.genericSignature = genericSignature;
1✔
7457
                    this.signatureResolution = signatureResolution;
1✔
7458
                    if (exceptionTypeInternalName == null) {
1✔
7459
                        exceptionTypeDescriptors = Collections.emptyList();
1✔
7460
                    } else {
7461
                        exceptionTypeDescriptors = new ArrayList<String>(exceptionTypeInternalName.length);
1✔
7462
                        for (String anExceptionTypeInternalName : exceptionTypeInternalName) {
1✔
7463
                            exceptionTypeDescriptors.add(Type.getObjectType(anExceptionTypeInternalName).getDescriptor());
1✔
7464
                        }
7465
                    }
7466
                    this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
1✔
7467
                    this.typeVariableBoundAnnotationTokens = typeVariableBoundAnnotationTokens;
1✔
7468
                    this.returnTypeAnnotationTokens = returnTypeAnnotationTokens;
1✔
7469
                    this.parameterTypeAnnotationTokens = parameterTypeAnnotationTokens;
1✔
7470
                    this.exceptionTypeAnnotationTokens = exceptionTypeAnnotationTokens;
1✔
7471
                    this.receiverTypeAnnotationTokens = receiverTypeAnnotationTokens;
1✔
7472
                    this.annotationTokens = annotationTokens;
1✔
7473
                    this.parameterAnnotationTokens = parameterAnnotationTokens;
1✔
7474
                    parameterNames = new String[parameterType.length];
1✔
7475
                    parameterModifiers = new Integer[parameterType.length];
1✔
7476
                    if (parameterTokens.size() == parameterType.length) {
1✔
7477
                        int index = 0;
1✔
7478
                        for (MethodToken.ParameterToken parameterToken : parameterTokens) {
1✔
7479
                            parameterNames[index] = parameterToken.getName();
1✔
7480
                            parameterModifiers[index] = parameterToken.getModifiers();
1✔
7481
                            index++;
1✔
7482
                        }
1✔
7483
                    }
7484
                    this.defaultValue = defaultValue;
1✔
7485
                }
1✔
7486

7487
                /**
7488
                 * {@inheritDoc}
7489
                 */
7490
                public Generic getReturnType() {
7491
                    return signatureResolution.resolveReturnType(returnTypeDescriptor, typePool, returnTypeAnnotationTokens, this);
1✔
7492
                }
7493

7494
                /**
7495
                 * {@inheritDoc}
7496
                 */
7497
                public TypeList.Generic getExceptionTypes() {
7498
                    return signatureResolution.resolveExceptionTypes(exceptionTypeDescriptors, typePool, exceptionTypeAnnotationTokens, this);
1✔
7499
                }
7500

7501
                /**
7502
                 * {@inheritDoc}
7503
                 */
7504
                public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
7505
                    return new LazyParameterList();
1✔
7506
                }
7507

7508
                /**
7509
                 * {@inheritDoc}
7510
                 */
7511
                public AnnotationList getDeclaredAnnotations() {
7512
                    return LazyAnnotationDescription.asList(typePool, annotationTokens);
1✔
7513
                }
7514

7515
                /**
7516
                 * {@inheritDoc}
7517
                 */
7518
                public String getInternalName() {
7519
                    return internalName;
1✔
7520
                }
7521

7522
                /**
7523
                 * {@inheritDoc}
7524
                 */
7525
                @Nonnull
7526
                public TypeDescription getDeclaringType() {
7527
                    return LazyTypeDescription.this;
1✔
7528
                }
7529

7530
                /**
7531
                 * {@inheritDoc}
7532
                 */
7533
                public int getModifiers() {
7534
                    return modifiers;
1✔
7535
                }
7536

7537
                /**
7538
                 * {@inheritDoc}
7539
                 */
7540
                public TypeList.Generic getTypeVariables() {
7541
                    return signatureResolution.resolveTypeVariables(typePool, this, typeVariableAnnotationTokens, typeVariableBoundAnnotationTokens);
1✔
7542
                }
7543

7544
                /**
7545
                 * {@inheritDoc}
7546
                 */
7547
                @MaybeNull
7548
                public AnnotationValue<?, ?> getDefaultValue() {
7549
                    return defaultValue;
1✔
7550
                }
7551

7552
                /**
7553
                 * {@inheritDoc}
7554
                 */
7555
                @MaybeNull
7556
                public Generic getReceiverType() {
7557
                    if (isStatic()) {
1✔
7558
                        return Generic.UNDEFINED;
1✔
7559
                    } else if (isConstructor()) {
1✔
7560
                        TypeDescription declaringType = getDeclaringType(), enclosingDeclaringType = declaringType.getEnclosingType();
1✔
7561
                        if (enclosingDeclaringType == null) {
1✔
7562
                            return declaringType.isGenerified()
1✔
7563
                                    ? new LazyParameterizedReceiverType(declaringType)
7564
                                    : new LazyNonGenericReceiverType(declaringType);
7565
                        } else {
7566
                            return !declaringType.isStatic() && declaringType.isGenerified()
1✔
7567
                                    ? new LazyParameterizedReceiverType(enclosingDeclaringType)
7568
                                    : new LazyNonGenericReceiverType(enclosingDeclaringType);
7569
                        }
7570
                    } else {
7571
                        return LazyTypeDescription.this.isGenerified()
1✔
7572
                                ? new LazyParameterizedReceiverType()
7573
                                : new LazyNonGenericReceiverType();
7574
                    }
7575
                }
7576

7577
                /**
7578
                 * {@inheritDoc}
7579
                 */
7580
                @MaybeNull
7581
                public String getGenericSignature() {
7582
                    return genericSignature;
1✔
7583
                }
7584

7585
                /**
7586
                 * A lazy list of parameter descriptions for the enclosing method description.
7587
                 */
7588
                private class LazyParameterList extends ParameterList.AbstractBase<ParameterDescription.InDefinedShape> {
1✔
7589

7590
                    /**
7591
                     * {@inheritDoc}
7592
                     */
7593
                    public ParameterDescription.InDefinedShape get(int index) {
7594
                        return new LazyParameterDescription(index);
1✔
7595
                    }
7596

7597
                    /**
7598
                     * {@inheritDoc}
7599
                     */
7600
                    public boolean hasExplicitMetaData() {
7601
                        for (int i = 0; i < size(); i++) {
×
7602
                            if (parameterNames[i] == null || parameterModifiers[i] == null) {
×
7603
                                return false;
×
7604
                            }
7605
                        }
7606
                        return true;
×
7607
                    }
7608

7609
                    /**
7610
                     * {@inheritDoc}
7611
                     */
7612
                    public int size() {
7613
                        return parameterTypeDescriptors.size();
1✔
7614
                    }
7615

7616
                    /**
7617
                     * {@inheritDoc}
7618
                     */
7619
                    public TypeList.Generic asTypeList() {
7620
                        return signatureResolution.resolveParameterTypes(parameterTypeDescriptors, typePool, parameterTypeAnnotationTokens, LazyMethodDescription.this);
1✔
7621
                    }
7622
                }
7623

7624
                /**
7625
                 * A lazy description of a parameters of the enclosing method.
7626
                 */
7627
                private class LazyParameterDescription extends ParameterDescription.InDefinedShape.AbstractBase {
7628

7629
                    /**
7630
                     * The index of the described parameter.
7631
                     */
7632
                    private final int index;
7633

7634
                    /**
7635
                     * Creates a new description for a given parameter of the enclosing method.
7636
                     *
7637
                     * @param index The index of the described parameter.
7638
                     */
7639
                    protected LazyParameterDescription(int index) {
1✔
7640
                        this.index = index;
1✔
7641
                    }
1✔
7642

7643
                    /**
7644
                     * {@inheritDoc}
7645
                     */
7646
                    public MethodDescription.InDefinedShape getDeclaringMethod() {
7647
                        return LazyMethodDescription.this;
1✔
7648
                    }
7649

7650
                    /**
7651
                     * {@inheritDoc}
7652
                     */
7653
                    public int getIndex() {
7654
                        return index;
1✔
7655
                    }
7656

7657
                    /**
7658
                     * {@inheritDoc}
7659
                     */
7660
                    public boolean isNamed() {
7661
                        return parameterNames[index] != null;
1✔
7662
                    }
7663

7664
                    /**
7665
                     * {@inheritDoc}
7666
                     */
7667
                    public boolean hasModifiers() {
7668
                        return parameterModifiers[index] != null;
1✔
7669
                    }
7670

7671
                    /**
7672
                     * {@inheritDoc}
7673
                     */
7674
                    public String getName() {
7675
                        return isNamed()
1✔
7676
                                ? parameterNames[index]
1✔
7677
                                : super.getName();
1✔
7678
                    }
7679

7680
                    /**
7681
                     * {@inheritDoc}
7682
                     */
7683
                    public int getModifiers() {
7684
                        return hasModifiers()
1✔
7685
                                ? parameterModifiers[index]
1✔
7686
                                : super.getModifiers();
1✔
7687
                    }
7688

7689
                    /**
7690
                     * {@inheritDoc}
7691
                     */
7692
                    public Generic getType() {
7693
                        return signatureResolution.resolveParameterTypes(parameterTypeDescriptors, typePool, parameterTypeAnnotationTokens, LazyMethodDescription.this).get(index);
1✔
7694
                    }
7695

7696
                    /**
7697
                     * {@inheritDoc}
7698
                     */
7699
                    public AnnotationList getDeclaredAnnotations() {
7700
                        return LazyAnnotationDescription.asListOfNullable(typePool, parameterAnnotationTokens.get(index));
1✔
7701
                    }
7702
                }
7703

7704
                /**
7705
                 * A lazy description of a parameterized receiver type.
7706
                 */
7707
                private class LazyParameterizedReceiverType extends Generic.OfParameterizedType {
7708

7709
                    /**
7710
                     * The erasure of the type to be represented as a parameterized receiver type.
7711
                     */
7712
                    private final TypeDescription typeDescription;
7713

7714
                    /**
7715
                     * Creates a new lazy parameterized receiver type of the method's declaring type.
7716
                     */
7717
                    protected LazyParameterizedReceiverType() {
7718
                        this(LazyTypeDescription.this);
1✔
7719
                    }
1✔
7720

7721
                    /**
7722
                     * Creates a new lazy parameterized receiver type of the supplied receiver type.
7723
                     *
7724
                     * @param typeDescription The erasure of the type to be represented as a parameterized receiver type.
7725
                     */
7726
                    protected LazyParameterizedReceiverType(TypeDescription typeDescription) {
1✔
7727
                        this.typeDescription = typeDescription;
1✔
7728
                    }
1✔
7729

7730
                    /**
7731
                     * {@inheritDoc}
7732
                     */
7733
                    public TypeList.Generic getTypeArguments() {
7734
                        return new TypeArgumentList(typeDescription.getTypeVariables());
1✔
7735
                    }
7736

7737
                    /**
7738
                     * {@inheritDoc}
7739
                     */
7740
                    @MaybeNull
7741
                    public Generic getOwnerType() {
7742
                        TypeDescription declaringType = typeDescription.getDeclaringType();
1✔
7743
                        if (declaringType == null) {
1✔
7744
                            return Generic.UNDEFINED;
×
7745
                        } else {
7746
                            return !typeDescription.isStatic() && declaringType.isGenerified()
1✔
7747
                                    ? new LazyParameterizedReceiverType(declaringType)
7748
                                    : new LazyNonGenericReceiverType(declaringType);
7749
                        }
7750
                    }
7751

7752
                    /**
7753
                     * {@inheritDoc}
7754
                     */
7755
                    public AnnotationList getDeclaredAnnotations() {
7756
                        return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(getTypePath()));
1✔
7757
                    }
7758

7759
                    /**
7760
                     * Returns the type path for this type.
7761
                     *
7762
                     * @return This type's type path.
7763
                     */
7764
                    private String getTypePath() {
7765
                        StringBuilder typePath = new StringBuilder();
1✔
7766
                        for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
1✔
7767
                            typePath = typePath.append(GenericTypeToken.INNER_CLASS_PATH);
1✔
7768
                        }
7769
                        return typePath.toString();
1✔
7770
                    }
7771

7772
                    /**
7773
                     * {@inheritDoc}
7774
                     */
7775
                    public TypeDescription asErasure() {
7776
                        return typeDescription;
1✔
7777
                    }
7778

7779
                    /**
7780
                     * A list of generic types representing the receiver type's type arguments.
7781
                     */
7782
                    protected class TypeArgumentList extends TypeList.Generic.AbstractBase {
7783

7784
                        /**
7785
                         * The type variables of the represented receiver type.
7786
                         */
7787
                        private final List<? extends Generic> typeVariables;
7788

7789
                        /**
7790
                         * Creates a new type argument list.
7791
                         *
7792
                         * @param typeVariables The type variables of the represented receiver type.
7793
                         */
7794
                        protected TypeArgumentList(List<? extends Generic> typeVariables) {
1✔
7795
                            this.typeVariables = typeVariables;
1✔
7796
                        }
1✔
7797

7798
                        /**
7799
                         * {@inheritDoc}
7800
                         */
7801
                        public Generic get(int index) {
7802
                            return new AnnotatedTypeVariable(typeVariables.get(index), index);
1✔
7803
                        }
7804

7805
                        /**
7806
                         * {@inheritDoc}
7807
                         */
7808
                        public int size() {
7809
                            return typeVariables.size();
1✔
7810
                        }
7811

7812
                        /**
7813
                         * Represents a type variable as a type argument with type annotations.
7814
                         */
7815
                        protected class AnnotatedTypeVariable extends OfTypeVariable {
7816

7817
                            /**
7818
                             * The type variable's description.
7819
                             */
7820
                            private final Generic typeVariable;
7821

7822
                            /**
7823
                             * The type variable's index.
7824
                             */
7825
                            private final int index;
7826

7827
                            /**
7828
                             * Creates a new description of an annotated type variable as a type argument.
7829
                             *
7830
                             * @param typeVariable The type variable's description.
7831
                             * @param index        The type variable's index.
7832
                             */
7833
                            protected AnnotatedTypeVariable(Generic typeVariable, int index) {
1✔
7834
                                this.typeVariable = typeVariable;
1✔
7835
                                this.index = index;
1✔
7836
                            }
1✔
7837

7838
                            /**
7839
                             * {@inheritDoc}
7840
                             */
7841
                            public TypeList.Generic getUpperBounds() {
7842
                                return typeVariable.getUpperBounds();
×
7843
                            }
7844

7845
                            /**
7846
                             * {@inheritDoc}
7847
                             */
7848
                            public TypeVariableSource getTypeVariableSource() {
7849
                                return typeVariable.getTypeVariableSource();
×
7850
                            }
7851

7852
                            /**
7853
                             * {@inheritDoc}
7854
                             */
7855
                            public String getSymbol() {
7856
                                return typeVariable.getSymbol();
1✔
7857
                            }
7858

7859
                            /**
7860
                             * {@inheritDoc}
7861
                             */
7862
                            public AnnotationList getDeclaredAnnotations() {
7863
                                return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(getTypePath()
1✔
7864
                                        + index
7865
                                        + GenericTypeToken.INDEXED_TYPE_DELIMITER));
7866
                            }
7867
                        }
7868
                    }
7869
                }
7870

7871
                /**
7872
                 * A lazy description of a non-generic receiver type.
7873
                 */
7874
                protected class LazyNonGenericReceiverType extends Generic.OfNonGenericType {
7875

7876
                    /**
7877
                     * The type description of the non-generic receiver type.
7878
                     */
7879
                    private final TypeDescription typeDescription;
7880

7881
                    /**
7882
                     * Creates a new non-generic receiver type of the method's declaring type.
7883
                     */
7884
                    protected LazyNonGenericReceiverType() {
7885
                        this(LazyTypeDescription.this);
1✔
7886
                    }
1✔
7887

7888
                    /**
7889
                     * Creates a new non-generic receiver type of the supplied type.
7890
                     *
7891
                     * @param typeDescription The type to represent as a non-generic receiver type.
7892
                     */
7893
                    protected LazyNonGenericReceiverType(TypeDescription typeDescription) {
1✔
7894
                        this.typeDescription = typeDescription;
1✔
7895
                    }
1✔
7896

7897
                    /**
7898
                     * {@inheritDoc}
7899
                     */
7900
                    @MaybeNull
7901
                    public Generic getOwnerType() {
7902
                        TypeDescription declaringType = typeDescription.getDeclaringType();
1✔
7903
                        return declaringType == null
1✔
7904
                                ? Generic.UNDEFINED
7905
                                : new LazyNonGenericReceiverType(declaringType);
7906
                    }
7907

7908
                    /**
7909
                     * {@inheritDoc}
7910
                     */
7911
                    @MaybeNull
7912
                    public Generic getComponentType() {
7913
                        return Generic.UNDEFINED;
×
7914
                    }
7915

7916
                    /**
7917
                     * {@inheritDoc}
7918
                     */
7919
                    public AnnotationList getDeclaredAnnotations() {
7920
                        StringBuilder typePath = new StringBuilder();
1✔
7921
                        for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
1✔
7922
                            typePath = typePath.append(GenericTypeToken.INNER_CLASS_PATH);
1✔
7923
                        }
7924
                        return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(typePath.toString()));
1✔
7925
                    }
7926

7927
                    /**
7928
                     * {@inheritDoc}
7929
                     */
7930
                    public TypeDescription asErasure() {
7931
                        return typeDescription;
1✔
7932
                    }
7933
                }
7934
            }
7935

7936
            /**
7937
             * A lazy description of a record component.
7938
             */
7939
            private class LazyRecordComponentDescription extends RecordComponentDescription.InDefinedShape.AbstractBase {
7940

7941
                /**
7942
                 * The record component's name.
7943
                 */
7944
                private final String name;
7945

7946
                /**
7947
                 * The record component's descriptor.
7948
                 */
7949
                private final String descriptor;
7950

7951
                /**
7952
                 * The record component's generic signature or {@code null} if the record component is non-generic.
7953
                 */
7954
                @MaybeNull
7955
                private final String genericSignature;
7956

7957
                /**
7958
                 * The record component's signature resolution.
7959
                 */
7960
                private final GenericTypeToken.Resolution.ForRecordComponent signatureResolution;
7961

7962
                /**
7963
                 * A mapping of the record component's type annotations.
7964
                 */
7965
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
7966

7967
                /**
7968
                 * A list of the record components annotations.
7969
                 */
7970
                private final List<AnnotationToken> annotationTokens;
7971

7972
                /**
7973
                 * Creates a new lazy description of a record component.
7974
                 *
7975
                 * @param name                 The record component's name.
7976
                 * @param descriptor           The record component's descriptor.
7977
                 * @param genericSignature     The record component's generic signature or {@code null} if the record component is non-generic.
7978
                 * @param signatureResolution  The record component's signature resolution.
7979
                 * @param typeAnnotationTokens A mapping of the record component's type annotations.
7980
                 * @param annotationTokens     A list of the record components annotations.
7981
                 */
7982
                private LazyRecordComponentDescription(String name,
7983
                                                       String descriptor,
7984
                                                       @MaybeNull String genericSignature,
7985
                                                       GenericTypeToken.Resolution.ForRecordComponent signatureResolution,
7986
                                                       Map<String, List<AnnotationToken>> typeAnnotationTokens,
7987
                                                       List<AnnotationToken> annotationTokens) {
×
7988
                    this.name = name;
×
7989
                    this.descriptor = descriptor;
×
7990
                    this.genericSignature = genericSignature;
×
7991
                    this.signatureResolution = signatureResolution;
×
7992
                    this.typeAnnotationTokens = typeAnnotationTokens;
×
7993
                    this.annotationTokens = annotationTokens;
×
7994
                }
×
7995

7996
                /**
7997
                 * {@inheritDoc}
7998
                 */
7999
                public Generic getType() {
8000
                    return signatureResolution.resolveRecordType(descriptor, typePool, typeAnnotationTokens, this);
×
8001
                }
8002

8003
                /**
8004
                 * {@inheritDoc}
8005
                 */
8006
                @Nonnull
8007
                public TypeDescription getDeclaringType() {
8008
                    return LazyTypeDescription.this;
×
8009
                }
8010

8011
                /**
8012
                 * {@inheritDoc}
8013
                 */
8014
                public String getActualName() {
8015
                    return name;
×
8016
                }
8017

8018
                /**
8019
                 * {@inheritDoc}
8020
                 */
8021
                public AnnotationList getDeclaredAnnotations() {
8022
                    return LazyAnnotationDescription.asList(typePool, annotationTokens);
×
8023
                }
8024

8025
                @Override
8026
                @MaybeNull
8027
                public String getGenericSignature() {
8028
                    return genericSignature;
×
8029
                }
8030
            }
8031
        }
8032

8033
        /**
8034
         * A type extractor reads a class file and collects data that is relevant to create a type description.
8035
         */
8036
        protected class TypeExtractor extends ClassVisitor {
8037

8038
            /**
8039
             * The index of a super class's type annotations.
8040
             */
8041
            private static final int SUPER_CLASS_INDEX = -1;
8042

8043
            /**
8044
             * A mask that cuts off pseudo flags beyond the second byte that are inserted by ASM.
8045
             */
8046
            private static final int REAL_MODIFIER_MASK = 0xFFFF;
8047

8048
            /**
8049
             * A mapping of the super types' type annotation tokens by their indices.
8050
             */
8051
            private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> superTypeAnnotationTokens;
8052

8053
            /**
8054
             * A mapping of the type variables' type annotation tokens by their indices.
8055
             */
8056
            private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> typeVariableAnnotationTokens;
8057

8058
            /**
8059
             * A mapping of the type variables' bounds' type annotation tokens by their indices and each variables index.
8060
             */
8061
            private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> typeVariableBoundsAnnotationTokens;
8062

8063
            /**
8064
             * A list of annotation tokens describing annotations that are found on the visited type.
8065
             */
8066
            private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8067

8068
            /**
8069
             * A list of field tokens describing fields that are found on the visited type.
8070
             */
8071
            private final List<LazyTypeDescription.FieldToken> fieldTokens;
8072

8073
            /**
8074
             * A list of method tokens describing annotations that are found on the visited type.
8075
             */
8076
            private final List<LazyTypeDescription.MethodToken> methodTokens;
8077

8078
            /**
8079
             * A list of record component tokens that are found on the visited type.
8080
             */
8081
            private final List<LazyTypeDescription.RecordComponentToken> recordComponentTokens;
8082

8083
            /**
8084
             * The actual modifiers found for this type.
8085
             */
8086
            private int actualModifiers;
8087

8088
            /**
8089
             * The modifiers found for this type.
8090
             */
8091
            private int modifiers;
8092

8093
            /**
8094
             * The internal name found for this type.
8095
             */
8096
            @MaybeNull
8097
            private String internalName;
8098

8099
            /**
8100
             * The internal name of the super type found for this type or {@code null} if no such type exists.
8101
             */
8102
            @MaybeNull
8103
            private String superClassName;
8104

8105
            /**
8106
             * The generic signature of the type or {@code null} if it is not generic.
8107
             */
8108
            @MaybeNull
8109
            private String genericSignature;
8110

8111
            /**
8112
             * A list of internal names of interfaces implemented by this type or {@code null} if no interfaces
8113
             * are implemented.
8114
             */
8115
            @MaybeNull
8116
            private String[] interfaceName;
8117

8118
            /**
8119
             * {@code true} if this type was found to represent an anonymous type.
8120
             */
8121
            private boolean anonymousType;
8122

8123
            /**
8124
             * The nest host that was found in the class file or {@code null} if no nest host was specified.
8125
             */
8126
            @MaybeNull
8127
            private String nestHost;
8128

8129
            /**
8130
             * A list of nest members that were found in the class file.
8131
             */
8132
            private final List<String> nestMembers;
8133

8134
            /**
8135
             * The declaration context found for this type.
8136
             */
8137
            private LazyTypeDescription.TypeContainment typeContainment;
8138

8139
            /**
8140
             * The binary name of this type's declaring type or {@code null} if no such type exists.
8141
             */
8142
            @MaybeNull
8143
            private String declaringTypeName;
8144

8145
            /**
8146
             * A list of descriptors representing the types that are declared by the parsed type.
8147
             */
8148
            private final List<String> declaredTypes;
8149

8150
            /**
8151
             * A list of internal names of permitted subclasses.
8152
             */
8153
            private final List<String> permittedSubclasses;
8154

8155
            /**
8156
             * The discovered class file version or {@code null} if no version was yet discovered.
8157
             */
8158
            @MaybeNull
8159
            private ClassFileVersion classFileVersion;
8160

8161
            /**
8162
             * Creates a new type extractor.
8163
             */
8164
            protected TypeExtractor() {
1✔
8165
                super(OpenedClassReader.ASM_API);
1✔
8166
                superTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8167
                typeVariableAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8168
                typeVariableBoundsAnnotationTokens = new HashMap<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>>();
1✔
8169
                annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
8170
                fieldTokens = new ArrayList<LazyTypeDescription.FieldToken>();
1✔
8171
                methodTokens = new ArrayList<LazyTypeDescription.MethodToken>();
1✔
8172
                recordComponentTokens = new ArrayList<LazyTypeDescription.RecordComponentToken>();
1✔
8173
                anonymousType = false;
1✔
8174
                typeContainment = LazyTypeDescription.TypeContainment.SelfContained.INSTANCE;
1✔
8175
                nestMembers = new ArrayList<String>();
1✔
8176
                declaredTypes = new ArrayList<String>();
1✔
8177
                permittedSubclasses = new ArrayList<String>();
1✔
8178
            }
1✔
8179

8180
            @Override
8181
            @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "The array is not modified by class contract.")
8182
            public void visit(int classFileVersion,
8183
                              int modifiers,
8184
                              String internalName,
8185
                              @MaybeNull String genericSignature,
8186
                              @MaybeNull String superClassName,
8187
                              @MaybeNull String[] interfaceName) {
8188
                this.modifiers = modifiers & REAL_MODIFIER_MASK;
1✔
8189
                actualModifiers = modifiers;
1✔
8190
                this.internalName = internalName;
1✔
8191
                this.genericSignature = genericSignature;
1✔
8192
                this.superClassName = superClassName;
1✔
8193
                this.interfaceName = interfaceName;
1✔
8194
                this.classFileVersion = ClassFileVersion.ofMinorMajor(classFileVersion);
1✔
8195
            }
1✔
8196

8197
            @Override
8198
            public void visitOuterClass(@MaybeNull String typeName, @MaybeNull String methodName, String methodDescriptor) {
8199
                if (methodName != null && !methodName.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) {
1✔
8200
                    typeContainment = new LazyTypeDescription.TypeContainment.WithinMethod(typeName, methodName, methodDescriptor);
1✔
8201
                } else if (typeName != null) {
1✔
8202
                    typeContainment = new LazyTypeDescription.TypeContainment.WithinType(typeName, true);
1✔
8203
                }
8204
            }
1✔
8205

8206
            @Override
8207
            public void visitInnerClass(String internalName, @MaybeNull String outerName, @MaybeNull String innerName, int modifiers) {
8208
                if (internalName.equals(this.internalName)) {
1✔
8209
                    if (outerName != null) {
1✔
8210
                        declaringTypeName = outerName;
1✔
8211
                        if (typeContainment.isSelfContained()) {
1✔
8212
                            typeContainment = new LazyTypeDescription.TypeContainment.WithinType(outerName, false);
1✔
8213
                        }
8214
                    }
8215
                    if (innerName == null && !typeContainment.isSelfContained()) { // Some compilers define this property inconsistently.
1✔
8216
                        anonymousType = true;
1✔
8217
                    }
8218
                    this.modifiers = modifiers & REAL_MODIFIER_MASK;
1✔
8219
                } else if (outerName != null && innerName != null && outerName.equals(this.internalName)) {
1✔
8220
                    declaredTypes.add("L" + internalName + ";");
1✔
8221
                }
8222
            }
1✔
8223

8224
            @Override
8225
            public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, @MaybeNull TypePath typePath, String descriptor, boolean visible) {
8226
                AnnotationRegistrant annotationRegistrant;
8227
                TypeReference typeReference = new TypeReference(rawTypeReference);
1✔
8228
                switch (typeReference.getSort()) {
1✔
8229
                    case TypeReference.CLASS_EXTENDS:
8230
                        annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex(descriptor,
1✔
8231
                                typePath,
8232
                                typeReference.getSuperTypeIndex(),
1✔
8233
                                superTypeAnnotationTokens);
8234
                        break;
1✔
8235
                    case TypeReference.CLASS_TYPE_PARAMETER:
8236
                        annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex(descriptor,
1✔
8237
                                typePath,
8238
                                typeReference.getTypeParameterIndex(),
1✔
8239
                                typeVariableAnnotationTokens);
8240
                        break;
1✔
8241
                    case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
8242
                        annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex.DoubleIndexed(descriptor,
1✔
8243
                                typePath,
8244
                                typeReference.getTypeParameterBoundIndex(),
1✔
8245
                                typeReference.getTypeParameterIndex(),
1✔
8246
                                typeVariableBoundsAnnotationTokens);
8247
                        break;
1✔
8248
                    default:
8249
                        throw new IllegalArgumentException("Unexpected type reference: " + typeReference.getSort());
×
8250
                }
8251
                return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8252
            }
8253

8254
            @Override
8255
            public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8256
                return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8257
            }
8258

8259
            @Override
8260
            public FieldVisitor visitField(int modifiers, String internalName, String descriptor, @MaybeNull String genericSignature, @MaybeNull Object value) {
8261
                return new FieldExtractor(modifiers & REAL_MODIFIER_MASK, internalName, descriptor, genericSignature);
1✔
8262
            }
8263

8264
            @Override
8265
            @MaybeNull
8266
            public MethodVisitor visitMethod(int modifiers, String internalName, String descriptor, @MaybeNull String genericSignature, @MaybeNull String[] exceptionName) {
8267
                return internalName.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)
1✔
8268
                        ? IGNORE_METHOD
1✔
8269
                        : new MethodExtractor(modifiers & REAL_MODIFIER_MASK, internalName, descriptor, genericSignature, exceptionName);
8270
            }
8271

8272
            @Override
8273
            public void visitNestHost(String nestHost) {
8274
                this.nestHost = nestHost;
×
8275
            }
×
8276

8277
            @Override
8278
            public void visitNestMember(String nestMember) {
8279
                nestMembers.add(nestMember);
×
8280
            }
×
8281

8282
            @Override
8283
            public RecordComponentVisitor visitRecordComponent(String name, String descriptor, @MaybeNull String signature) {
8284
                return new RecordComponentExtractor(name, descriptor, signature);
×
8285
            }
8286

8287
            @Override
8288
            public void visitPermittedSubclass(String permittedSubclass) {
8289
                permittedSubclasses.add(permittedSubclass);
×
8290
            }
×
8291

8292
            /**
8293
             * Creates a type description from all data that is currently collected. This method should only be invoked
8294
             * after a class file was parsed fully.
8295
             *
8296
             * @return A type description reflecting the data that was collected by this instance.
8297
             */
8298
            protected TypeDescription toTypeDescription() {
8299
                if (internalName == null || classFileVersion == null) {
1✔
8300
                    throw new IllegalStateException("Internal name or class file version were not set");
×
8301
                }
8302
                Map<String, List<LazyTypeDescription.AnnotationToken>> superClassAnnotationTokens = superTypeAnnotationTokens.remove(SUPER_CLASS_INDEX);
1✔
8303
                return new LazyTypeDescription(Default.this,
1✔
8304
                        actualModifiers,
8305
                        modifiers,
8306
                        internalName,
8307
                        superClassName,
8308
                        interfaceName,
8309
                        genericSignature,
8310
                        typeContainment,
8311
                        declaringTypeName,
8312
                        declaredTypes,
8313
                        anonymousType,
8314
                        nestHost,
8315
                        nestMembers,
8316
                        superClassAnnotationTokens == null
8317
                                ? Collections.<String, List<LazyTypeDescription.AnnotationToken>>emptyMap()
1✔
8318
                                : superClassAnnotationTokens,
8319
                        superTypeAnnotationTokens,
8320
                        typeVariableAnnotationTokens,
8321
                        typeVariableBoundsAnnotationTokens,
8322
                        annotationTokens,
8323
                        fieldTokens,
8324
                        methodTokens,
8325
                        recordComponentTokens,
8326
                        permittedSubclasses,
8327
                        classFileVersion);
8328
            }
8329

8330
            /**
8331
             * An annotation extractor reads an annotation found in a class field an collects data that
8332
             * is relevant to creating a related annotation description.
8333
             */
8334
            protected class AnnotationExtractor extends AnnotationVisitor {
8335

8336
                /**
8337
                 * The annotation registrant to register found annotation values on.
8338
                 */
8339
                private final AnnotationRegistrant annotationRegistrant;
8340

8341
                /**
8342
                 * A locator for the component type of any found annotation value.
8343
                 */
8344
                private final ComponentTypeLocator componentTypeLocator;
8345

8346
                /**
8347
                 * Creates a new annotation extractor for a byte code element without an index.
8348
                 *
8349
                 * @param descriptor           The annotation descriptor.
8350
                 * @param annotationTokens     The collection for storing any discovered annotation tokens.
8351
                 * @param componentTypeLocator The component type locator to use.
8352
                 */
8353
                protected AnnotationExtractor(String descriptor, List<LazyTypeDescription.AnnotationToken> annotationTokens, ComponentTypeLocator componentTypeLocator) {
8354
                    this(new AnnotationRegistrant.ForByteCodeElement(descriptor, annotationTokens), componentTypeLocator);
1✔
8355
                }
1✔
8356

8357
                /**
8358
                 * Creates a new annotation extractor for a byte code element with an index.
8359
                 *
8360
                 * @param descriptor           The annotation descriptor.
8361
                 * @param index                The index of the element for which the annotations are collected.
8362
                 * @param annotationTokens     The collection for storing any discovered annotation tokens.
8363
                 * @param componentTypeLocator The component type locator to use.
8364
                 */
8365
                protected AnnotationExtractor(String descriptor,
8366
                                              int index,
8367
                                              Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens,
8368
                                              ComponentTypeLocator componentTypeLocator) {
8369
                    this(new AnnotationRegistrant.ForByteCodeElement.WithIndex(descriptor, index, annotationTokens), componentTypeLocator);
1✔
8370
                }
1✔
8371

8372
                /**
8373
                 * Creates a new annotation extractor.
8374
                 *
8375
                 * @param annotationRegistrant The annotation registrant to register found annotation values on.
8376
                 * @param componentTypeLocator A locator for the component type of any found annotation value.
8377
                 */
8378
                protected AnnotationExtractor(AnnotationRegistrant annotationRegistrant, ComponentTypeLocator componentTypeLocator) {
1✔
8379
                    super(OpenedClassReader.ASM_API);
1✔
8380
                    this.annotationRegistrant = annotationRegistrant;
1✔
8381
                    this.componentTypeLocator = componentTypeLocator;
1✔
8382
                }
1✔
8383

8384
                @Override
8385
                public void visit(String name, Object value) {
8386
                    if (value instanceof Type) {
1✔
8387
                        Type type = (Type) value;
1✔
8388
                        annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForTypeValue(Default.this, type.getSort() == Type.ARRAY
1✔
8389
                                ? type.getInternalName().replace('/', '.')
1✔
8390
                                : type.getClassName()));
1✔
8391
                    } else {
1✔
8392
                        annotationRegistrant.register(name, AnnotationValue.ForConstant.of(value));
1✔
8393
                    }
8394
                }
1✔
8395

8396
                @Override
8397
                public void visitEnum(String name, String descriptor, String value) {
8398
                    annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForEnumerationValue(Default.this,
1✔
8399
                            descriptor.substring(1, descriptor.length() - 1).replace('/', '.'),
1✔
8400
                            value));
8401
                }
1✔
8402

8403
                @Override
8404
                public AnnotationVisitor visitAnnotation(String name, String descriptor) {
8405
                    return new AnnotationExtractor(new AnnotationLookup(descriptor, name), new ComponentTypeLocator.ForAnnotationProperty(TypePool.Default.this, descriptor));
1✔
8406
                }
8407

8408
                @Override
8409
                public AnnotationVisitor visitArray(String name) {
8410
                    return new AnnotationExtractor(new ArrayLookup(name, componentTypeLocator.bind(name)), ComponentTypeLocator.Illegal.INSTANCE);
1✔
8411
                }
8412

8413
                @Override
8414
                public void visitEnd() {
8415
                    annotationRegistrant.onComplete();
1✔
8416
                }
1✔
8417

8418
                /**
8419
                 * An annotation registrant for registering values of an array.
8420
                 */
8421
                protected class ArrayLookup implements AnnotationRegistrant {
8422

8423
                    /**
8424
                     * The name of the annotation property the collected array is representing.
8425
                     */
8426
                    private final String name;
8427

8428
                    /**
8429
                     * A lazy reference to resolve the component type of the collected array.
8430
                     */
8431
                    private final ComponentTypeReference componentTypeReference;
8432

8433
                    /**
8434
                     * A list of all annotation values that are found on this array.
8435
                     */
8436
                    private final List<AnnotationValue<?, ?>> values;
8437

8438
                    /**
8439
                     * Creates a new annotation registrant for an array lookup.
8440
                     *
8441
                     * @param name                   The name of the annotation property the collected array is representing.
8442
                     * @param componentTypeReference A lazy reference to resolve the component type of the collected array.
8443
                     */
8444
                    private ArrayLookup(String name, ComponentTypeReference componentTypeReference) {
1✔
8445
                        this.name = name;
1✔
8446
                        this.componentTypeReference = componentTypeReference;
1✔
8447
                        values = new ArrayList<AnnotationValue<?, ?>>();
1✔
8448
                    }
1✔
8449

8450
                    /**
8451
                     * {@inheritDoc}
8452
                     */
8453
                    public void register(String ignored, AnnotationValue<?, ?> annotationValue) {
8454
                        values.add(annotationValue);
1✔
8455
                    }
1✔
8456

8457
                    /**
8458
                     * {@inheritDoc}
8459
                     */
8460
                    public void onComplete() {
8461
                        annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForArray(Default.this,
1✔
8462
                                componentTypeReference,
8463
                                values));
8464
                    }
1✔
8465
                }
8466

8467
                /**
8468
                 * An annotation registrant for registering the values on an array that is itself an annotation property.
8469
                 */
8470
                protected class AnnotationLookup implements AnnotationRegistrant {
8471

8472
                    /**
8473
                     * The descriptor of the original annotation for which the annotation values are looked up.
8474
                     */
8475
                    private final String descriptor;
8476

8477
                    /**
8478
                     * The name of the original annotation for which the annotation values are looked up.
8479
                     */
8480
                    private final String name;
8481

8482
                    /**
8483
                     * This annotation's values mapped by their attribute name.
8484
                     */
8485
                    private final Map<String, AnnotationValue<?, ?>> values;
8486

8487
                    /**
8488
                     * Creates a new annotation registrant for a recursive annotation lookup.
8489
                     *
8490
                     * @param descriptor The descriptor of the original annotation for which the annotation values are looked up.
8491
                     * @param name       The name of the original annotation for which the annotation values are looked up.
8492
                     */
8493
                    protected AnnotationLookup(String descriptor, String name) {
1✔
8494
                        this.descriptor = descriptor;
1✔
8495
                        this.name = name;
1✔
8496
                        values = new HashMap<String, AnnotationValue<?, ?>>();
1✔
8497
                    }
1✔
8498

8499
                    /**
8500
                     * {@inheritDoc}
8501
                     */
8502
                    public void register(String name, AnnotationValue<?, ?> annotationValue) {
8503
                        values.put(name, annotationValue);
1✔
8504
                    }
1✔
8505

8506
                    /**
8507
                     * {@inheritDoc}
8508
                     */
8509
                    public void onComplete() {
8510
                        annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForAnnotationValue(Default.this,
1✔
8511
                                new LazyTypeDescription.AnnotationToken(descriptor, values)));
8512
                    }
1✔
8513
                }
8514
            }
8515

8516
            /**
8517
             * A field extractor reads a field within a class file and collects data that is relevant
8518
             * to creating a related field description.
8519
             */
8520
            protected class FieldExtractor extends FieldVisitor {
8521

8522
                /**
8523
                 * The modifiers found on the field.
8524
                 */
8525
                private final int modifiers;
8526

8527
                /**
8528
                 * The name of the field.
8529
                 */
8530
                private final String internalName;
8531

8532
                /**
8533
                 * The descriptor of the field type.
8534
                 */
8535
                private final String descriptor;
8536

8537
                /**
8538
                 * The generic signature of the field or {@code null} if it is not generic.
8539
                 */
8540
                @MaybeNull
8541
                private final String genericSignature;
8542

8543
                /**
8544
                 * A mapping of the field type's type annotations.
8545
                 */
8546
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> typeAnnotationTokens;
8547

8548
                /**
8549
                 * A list of annotation tokens found for this field.
8550
                 */
8551
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8552

8553
                /**
8554
                 * Creates a new field extractor.
8555
                 *
8556
                 * @param modifiers        The modifiers found for this field.
8557
                 * @param internalName     The name of the field.
8558
                 * @param descriptor       The descriptor of the field type.
8559
                 * @param genericSignature The generic signature of the field or {@code null} if it is not generic.
8560
                 */
8561
                protected FieldExtractor(int modifiers,
8562
                                         String internalName,
8563
                                         String descriptor,
8564
                                         @MaybeNull String genericSignature) {
1✔
8565
                    super(OpenedClassReader.ASM_API);
1✔
8566
                    this.modifiers = modifiers;
1✔
8567
                    this.internalName = internalName;
1✔
8568
                    this.descriptor = descriptor;
1✔
8569
                    this.genericSignature = genericSignature;
1✔
8570
                    typeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
8571
                    annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
8572
                }
1✔
8573

8574
                @Override
8575
                @MaybeNull
8576
                public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, @MaybeNull TypePath typePath, String descriptor, boolean visible) {
8577
                    AnnotationRegistrant annotationRegistrant;
8578
                    TypeReference typeReference = new TypeReference(rawTypeReference);
1✔
8579
                    switch (typeReference.getSort()) {
1✔
8580
                        case TypeReference.FIELD:
8581
                            annotationRegistrant = new AnnotationRegistrant.ForTypeVariable(descriptor, typePath, typeAnnotationTokens);
1✔
8582
                            break;
1✔
8583
                        default:
8584
                            throw new IllegalStateException("Unexpected type reference on field: " + typeReference.getSort());
×
8585
                    }
8586
                    return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8587
                }
8588

8589
                @Override
8590
                public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8591
                    return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8592
                }
8593

8594
                @Override
8595
                public void visitEnd() {
8596
                    fieldTokens.add(new LazyTypeDescription.FieldToken(internalName,
1✔
8597
                            modifiers,
8598
                            descriptor,
8599
                            genericSignature,
8600
                            typeAnnotationTokens,
8601
                            annotationTokens));
8602
                }
1✔
8603
            }
8604

8605
            /**
8606
             * A method extractor reads a method within a class file and collects data that is relevant
8607
             * to creating a related method description.
8608
             */
8609
            protected class MethodExtractor extends MethodVisitor implements AnnotationRegistrant {
8610

8611
                /**
8612
                 * The modifiers found for this method.
8613
                 */
8614
                private final int modifiers;
8615

8616
                /**
8617
                 * The internal name found for this method.
8618
                 */
8619
                private final String internalName;
8620

8621
                /**
8622
                 * The descriptor found for this method.
8623
                 */
8624
                private final String descriptor;
8625

8626
                /**
8627
                 * The generic signature of the method or {@code null} if it is not generic.
8628
                 */
8629
                @MaybeNull
8630
                private final String genericSignature;
8631

8632
                /**
8633
                 * An array of internal names of the exceptions of the found method
8634
                 * or {@code null} if there are no such exceptions.
8635
                 */
8636
                @MaybeNull
8637
                private final String[] exceptionName;
8638

8639
                /**
8640
                 * A mapping of the method's type variables' type annotations by their indices.
8641
                 */
8642
                private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> typeVariableAnnotationTokens;
8643

8644
                /**
8645
                 * A mapping of the method's type variables' bounds' type annotations by their indices and each variable's index.
8646
                 */
8647
                private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> typeVariableBoundAnnotationTokens;
8648

8649
                /**
8650
                 * A mapping of the method's return type's type annotations.
8651
                 */
8652
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> returnTypeAnnotationTokens;
8653

8654
                /**
8655
                 * A mapping of the parameters' type annotations by their indices.
8656
                 */
8657
                private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> parameterTypeAnnotationTokens;
8658

8659
                /**
8660
                 * A mapping of the exception types' type annotations by their indices.
8661
                 */
8662
                private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> exceptionTypeAnnotationTokens;
8663

8664
                /**
8665
                 * A mapping of the receiver type's type annotations.
8666
                 */
8667
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> receiverTypeAnnotationTokens;
8668

8669
                /**
8670
                 * A list of annotation tokens declared on the found method.
8671
                 */
8672
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8673

8674
                /**
8675
                 * A mapping of parameter indices to annotation tokens found for the parameters at these indices.
8676
                 */
8677
                private final Map<Integer, List<LazyTypeDescription.AnnotationToken>> parameterAnnotationTokens;
8678

8679
                /**
8680
                 * A list of tokens representing meta information of a parameter as it is available for method's
8681
                 * that are compiled in the Java 8 version format.
8682
                 */
8683
                private final List<LazyTypeDescription.MethodToken.ParameterToken> parameterTokens;
8684

8685
                /**
8686
                 * A bag of parameter meta information representing debugging information which allows to extract
8687
                 * a method's parameter names.
8688
                 */
8689
                private final ParameterBag legacyParameterBag;
8690

8691
                /**
8692
                 * The first label that is found in the method's body, if any, denoting the start of the method.
8693
                 * This label can be used to identify names of local variables that describe the method's parameters.
8694
                 */
8695
                @MaybeNull
8696
                private Label firstLabel;
8697

8698
                /**
8699
                 * A shift index for visible parameters that indicates a deviation of the actual parameter index.
8700
                 */
8701
                private int visibleParameterShift;
8702

8703
                /**
8704
                 * A shift index for invisible parameters that indicates a deviation of the actual parameter index.
8705
                 */
8706
                private int invisibleParameterShift;
8707

8708
                /**
8709
                 * The default value of the found method or {@code null} if no such value exists.
8710
                 */
8711
                @MaybeNull
8712
                private AnnotationValue<?, ?> defaultValue;
8713

8714
                /**
8715
                 * Creates a method extractor.
8716
                 *
8717
                 * @param modifiers        The modifiers found for this method.
8718
                 * @param internalName     The internal name found for this method.
8719
                 * @param descriptor       The descriptor found for this method.
8720
                 * @param genericSignature The generic signature of the method or {@code null} if it is not generic.
8721
                 * @param exceptionName    An array of internal names of the exceptions of the found method
8722
                 *                         or {@code null} if there are no such exceptions.
8723
                 */
8724
                protected MethodExtractor(int modifiers,
8725
                                          String internalName,
8726
                                          String descriptor,
8727
                                          @MaybeNull String genericSignature,
8728
                                          @MaybeNull String[] exceptionName) {
1✔
8729
                    super(OpenedClassReader.ASM_API);
1✔
8730
                    this.modifiers = modifiers;
1✔
8731
                    this.internalName = internalName;
1✔
8732
                    this.descriptor = descriptor;
1✔
8733
                    this.genericSignature = genericSignature;
1✔
8734
                    this.exceptionName = exceptionName;
1✔
8735
                    typeVariableAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8736
                    typeVariableBoundAnnotationTokens = new HashMap<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>>();
1✔
8737
                    returnTypeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
8738
                    parameterTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8739
                    exceptionTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8740
                    receiverTypeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
8741
                    annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
8742
                    parameterAnnotationTokens = new HashMap<Integer, List<LazyTypeDescription.AnnotationToken>>();
1✔
8743
                    parameterTokens = new ArrayList<LazyTypeDescription.MethodToken.ParameterToken>();
1✔
8744
                    legacyParameterBag = new ParameterBag(Type.getMethodType(descriptor).getArgumentTypes());
1✔
8745
                }
1✔
8746

8747
                @Override
8748
                @MaybeNull
8749
                public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
8750
                    AnnotationRegistrant annotationRegistrant;
8751
                    TypeReference typeReference = new TypeReference(rawTypeReference);
1✔
8752
                    switch (typeReference.getSort()) {
1✔
8753
                        case TypeReference.METHOD_TYPE_PARAMETER:
8754
                            annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
1✔
8755
                                    typePath,
8756
                                    typeReference.getTypeParameterIndex(),
1✔
8757
                                    typeVariableAnnotationTokens);
8758
                            break;
1✔
8759
                        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
8760
                            annotationRegistrant = new ForTypeVariable.WithIndex.DoubleIndexed(descriptor,
1✔
8761
                                    typePath,
8762
                                    typeReference.getTypeParameterBoundIndex(),
1✔
8763
                                    typeReference.getTypeParameterIndex(),
1✔
8764
                                    typeVariableBoundAnnotationTokens);
8765
                            break;
1✔
8766
                        case TypeReference.METHOD_RETURN:
8767
                            annotationRegistrant = new ForTypeVariable(descriptor,
1✔
8768
                                    typePath,
8769
                                    returnTypeAnnotationTokens);
8770
                            break;
1✔
8771
                        case TypeReference.METHOD_FORMAL_PARAMETER:
8772
                            annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
1✔
8773
                                    typePath,
8774
                                    typeReference.getFormalParameterIndex(),
1✔
8775
                                    parameterTypeAnnotationTokens);
8776
                            break;
1✔
8777
                        case TypeReference.THROWS:
8778
                            annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
1✔
8779
                                    typePath,
8780
                                    typeReference.getExceptionIndex(),
1✔
8781
                                    exceptionTypeAnnotationTokens);
8782
                            break;
1✔
8783
                        case TypeReference.METHOD_RECEIVER:
8784
                            annotationRegistrant = new ForTypeVariable(descriptor,
1✔
8785
                                    typePath,
8786
                                    receiverTypeAnnotationTokens);
8787
                            break;
1✔
8788
                        case TypeReference.FIELD: // Emitted by mistake by javac for records in Java 14.
8789
                            return null;
×
8790
                        default:
8791
                            throw new IllegalStateException("Unexpected type reference on method: " + typeReference.getSort());
×
8792
                    }
8793
                    return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8794
                }
8795

8796
                @Override
8797
                public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8798
                    return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8799
                }
8800

8801
                @Override
8802
                public void visitAnnotableParameterCount(int count, boolean visible) {
8803
                    if (visible) {
1✔
8804
                        visibleParameterShift = Type.getMethodType(descriptor).getArgumentTypes().length - count;
1✔
8805
                    } else {
8806
                        invisibleParameterShift = Type.getMethodType(descriptor).getArgumentTypes().length - count;
×
8807
                    }
8808
                }
1✔
8809

8810
                @Override
8811
                public AnnotationVisitor visitParameterAnnotation(int index, String descriptor, boolean visible) {
8812
                    return new AnnotationExtractor(descriptor,
1✔
8813
                            index + (visible ? visibleParameterShift : invisibleParameterShift),
8814
                            parameterAnnotationTokens,
8815
                            new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8816
                }
8817

8818
                @Override
8819
                public void visitLabel(Label label) {
8820
                    if (readerMode.isExtended() && firstLabel == null) {
1✔
8821
                        firstLabel = label;
1✔
8822
                    }
8823
                }
1✔
8824

8825
                @Override
8826
                public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int offset) {
8827
                    if (readerMode.isExtended() && start == firstLabel) {
1✔
8828
                        legacyParameterBag.register(offset, name);
1✔
8829
                    }
8830
                }
1✔
8831

8832
                @Override
8833
                public void visitParameter(String name, int modifiers) {
8834
                    parameterTokens.add(new LazyTypeDescription.MethodToken.ParameterToken(name, modifiers));
1✔
8835
                }
1✔
8836

8837
                @Override
8838
                public AnnotationVisitor visitAnnotationDefault() {
8839
                    return new AnnotationExtractor(this, new ComponentTypeLocator.ForArrayType(descriptor));
1✔
8840
                }
8841

8842
                /**
8843
                 * {@inheritDoc}
8844
                 */
8845
                public void register(String ignored, AnnotationValue<?, ?> annotationValue) {
8846
                    defaultValue = annotationValue;
1✔
8847
                }
1✔
8848

8849
                /**
8850
                 * {@inheritDoc}
8851
                 */
8852
                public void onComplete() {
8853
                    /* do nothing, as the register method is called at most once for default values */
8854
                }
1✔
8855

8856
                @Override
8857
                public void visitEnd() {
8858
                    methodTokens.add(new LazyTypeDescription.MethodToken(internalName,
1✔
8859
                            modifiers,
8860
                            descriptor,
8861
                            genericSignature,
8862
                            exceptionName,
8863
                            typeVariableAnnotationTokens,
8864
                            typeVariableBoundAnnotationTokens,
8865
                            returnTypeAnnotationTokens,
8866
                            parameterTypeAnnotationTokens,
8867
                            exceptionTypeAnnotationTokens,
8868
                            receiverTypeAnnotationTokens,
8869
                            annotationTokens,
8870
                            parameterAnnotationTokens,
8871
                            parameterTokens.isEmpty()
1✔
8872
                                    ? legacyParameterBag.resolve((modifiers & Opcodes.ACC_STATIC) != 0)
1✔
8873
                                    : parameterTokens,
8874
                            defaultValue));
8875
                }
1✔
8876
            }
8877

8878
            /**
8879
             * A record component extractor reads a record component's information within a class file.
8880
             */
8881
            protected class RecordComponentExtractor extends RecordComponentVisitor {
8882

8883
                /**
8884
                 * The record component's name.
8885
                 */
8886
                private final String name;
8887

8888
                /**
8889
                 * The record component's descriptor.
8890
                 */
8891
                private final String descriptor;
8892

8893
                /**
8894
                 * The record component's generic signature.
8895
                 */
8896
                @MaybeNull
8897
                private final String genericSignature;
8898

8899
                /**
8900
                 * A mapping of the record component's type annotations.
8901
                 */
8902
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> typeAnnotationTokens;
8903

8904
                /**
8905
                 * A list of the record component's annotations.
8906
                 */
8907
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8908

8909
                /**
8910
                 * Creates a new record component extractor.
8911
                 *
8912
                 * @param name             The record component's name.
8913
                 * @param descriptor       The record component's descriptor.
8914
                 * @param genericSignature The record component's generic signature.
8915
                 */
8916
                protected RecordComponentExtractor(String name, String descriptor, @MaybeNull String genericSignature) {
×
8917
                    super(OpenedClassReader.ASM_API);
×
8918
                    this.name = name;
×
8919
                    this.descriptor = descriptor;
×
8920
                    this.genericSignature = genericSignature;
×
8921
                    typeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
×
8922
                    annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
×
8923
                }
×
8924

8925
                @Override
8926
                public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
8927
                    AnnotationRegistrant annotationRegistrant;
8928
                    TypeReference typeReference = new TypeReference(rawTypeReference);
×
8929
                    switch (typeReference.getSort()) {
×
8930
                        case TypeReference.FIELD:
8931
                            annotationRegistrant = new AnnotationRegistrant.ForTypeVariable(descriptor, typePath, typeAnnotationTokens);
×
8932
                            break;
×
8933
                        default:
8934
                            throw new IllegalStateException("Unexpected type reference on record component: " + typeReference.getSort());
×
8935
                    }
8936
                    return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
×
8937
                }
8938

8939
                @Override
8940
                public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8941
                    return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
×
8942
                }
8943

8944
                @Override
8945
                public void visitEnd() {
8946
                    recordComponentTokens.add(new LazyTypeDescription.RecordComponentToken(name,
×
8947
                            descriptor,
8948
                            genericSignature,
8949
                            typeAnnotationTokens,
8950
                            annotationTokens));
8951
                }
×
8952
            }
8953
        }
8954
    }
8955

8956
    /**
8957
     * 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.
8958
     */
8959
    @HashCodeAndEqualsPlugin.Enhance
8960
    class LazyFacade extends AbstractBase {
8961

8962
        /**
8963
         * The type pool to delegate to.
8964
         */
8965
        private final TypePool typePool;
8966

8967
        /**
8968
         * Creates a lazy facade for a type pool.
8969
         *
8970
         * @param typePool The type pool to delegate to.
8971
         */
8972
        public LazyFacade(TypePool typePool) {
8973
            super(CacheProvider.NoOp.INSTANCE);
1✔
8974
            this.typePool = typePool;
1✔
8975
        }
1✔
8976

8977
        @Override
8978
        protected Resolution doDescribe(String name) {
8979
            return new LazyResolution(typePool, name);
1✔
8980
        }
8981

8982
        /**
8983
         * {@inheritDoc}
8984
         */
8985
        public void clear() {
8986
            typePool.clear();
1✔
8987
        }
1✔
8988

8989
        /**
8990
         * The lazy resolution for a lazy facade for a type pool.
8991
         */
8992
        @HashCodeAndEqualsPlugin.Enhance
8993
        protected static class LazyResolution implements Resolution {
8994

8995
            /**
8996
             * The type pool to delegate to.
8997
             */
8998
            private final TypePool typePool;
8999

9000
            /**
9001
             * The name of the type that is represented by this resolution.
9002
             */
9003
            private final String name;
9004

9005
            /**
9006
             * Creates a lazy resolution for a lazy facade for a type pool.
9007
             *
9008
             * @param typePool The type pool to delegate to.
9009
             * @param name     The name of the type that is represented by this resolution.
9010
             */
9011
            protected LazyResolution(TypePool typePool, String name) {
1✔
9012
                this.typePool = typePool;
1✔
9013
                this.name = name;
1✔
9014
            }
1✔
9015

9016
            /**
9017
             * {@inheritDoc}
9018
             */
9019
            public boolean isResolved() {
9020
                return typePool.describe(name).isResolved();
1✔
9021
            }
9022

9023
            /**
9024
             * {@inheritDoc}
9025
             */
9026
            public TypeDescription resolve() {
9027
                return new LazyTypeDescription(typePool, name);
1✔
9028
            }
9029
        }
9030

9031
        /**
9032
         * A description of a type that delegates to another type pool once a property that is not the name is resolved.
9033
         */
9034
        protected static class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType.WithDelegation {
9035

9036
            /**
9037
             * The type pool to delegate to.
9038
             */
9039
            private final TypePool typePool;
9040

9041
            /**
9042
             * The name of the type that is represented by this resolution.
9043
             */
9044
            private final String name;
9045

9046
            /**
9047
             * Creates a new lazy type resolution.
9048
             *
9049
             * @param typePool The type pool to delegate to.
9050
             * @param name     The name of the type.
9051
             */
9052
            protected LazyTypeDescription(TypePool typePool, String name) {
1✔
9053
                this.typePool = typePool;
1✔
9054
                this.name = name;
1✔
9055
            }
1✔
9056

9057
            /**
9058
             * {@inheritDoc}
9059
             */
9060
            public String getName() {
9061
                return name;
1✔
9062
            }
9063

9064
            @Override
9065
            @CachedReturnPlugin.Enhance("delegate")
9066
            protected TypeDescription delegate() {
9067
                return typePool.describe(name).resolve();
1✔
9068
            }
9069
        }
9070
    }
9071

9072
    /**
9073
     * A type pool that attempts to load a class.
9074
     */
9075
    @HashCodeAndEqualsPlugin.Enhance
9076
    class ClassLoading extends AbstractBase.Hierarchical {
9077

9078
        /**
9079
         * The class loader to query.
9080
         */
9081
        @MaybeNull
9082
        @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
9083
        private final ClassLoader classLoader;
9084

9085
        /**
9086
         * Creates a class loadings type pool.
9087
         *
9088
         * @param cacheProvider The cache provider to use.
9089
         * @param parent        The parent type pool.
9090
         * @param classLoader   The class loader to use for locating files.
9091
         */
9092
        public ClassLoading(CacheProvider cacheProvider, TypePool parent, @MaybeNull ClassLoader classLoader) {
9093
            super(cacheProvider, parent);
1✔
9094
            this.classLoader = classLoader;
1✔
9095
        }
1✔
9096

9097
        /**
9098
         * Returns a type pool that attempts type descriptions by loadings types from the given class loader.
9099
         *
9100
         * @param classLoader The class loader to use.
9101
         * @return An class loading type pool.
9102
         */
9103
        public static TypePool of(@MaybeNull ClassLoader classLoader) {
9104
            return of(classLoader, Empty.INSTANCE);
1✔
9105
        }
9106

9107
        /**
9108
         * Returns a type pool that attempts type descriptions by loadings types from the given class loader.
9109
         *
9110
         * @param classLoader The class loader to use.
9111
         * @param parent      The parent type pool to use.
9112
         * @return An class loading type pool.
9113
         */
9114
        public static TypePool of(@MaybeNull ClassLoader classLoader, TypePool parent) {
9115
            return new ClassLoading(new CacheProvider.Simple(), parent, classLoader);
1✔
9116
        }
9117

9118
        /**
9119
         * Returns a type pool that attempts type descriptions by loadings types from the system class loader.
9120
         *
9121
         * @return An class loading type pool for the system class loader.
9122
         */
9123
        public static TypePool ofSystemLoader() {
9124
            return of(ClassLoader.getSystemClassLoader());
1✔
9125
        }
9126

9127
        /**
9128
         * Returns a type pool that attempts type descriptions by loadings types from the platform class loader.
9129
         * If the current VM is Java 8 or older, the extension class loader is represented instead.
9130
         *
9131
         * @return An class loading type pool for the system class loader.
9132
         */
9133
        public static TypePool ofPlatformLoader() {
9134
            return of(ClassLoader.getSystemClassLoader().getParent());
1✔
9135
        }
9136

9137
        /**
9138
         * Returns a type pool that attempts type descriptions by loadings types from the bootstrap class loader.
9139
         *
9140
         * @return An class loading type pool for the bootstrap class loader.
9141
         */
9142
        public static TypePool ofBootLoader() {
9143
            return of(ClassLoadingStrategy.BOOTSTRAP_LOADER);
1✔
9144
        }
9145

9146
        @Override
9147
        protected Resolution doDescribe(String name) {
9148
            try {
9149
                return new Resolution.Simple(TypeDescription.ForLoadedType.of(Class.forName(name, false, classLoader)));
1✔
9150
            } catch (ClassNotFoundException ignored) {
1✔
9151
                return new Resolution.Illegal(name);
1✔
9152
            }
9153
        }
9154
    }
9155

9156
    /**
9157
     * A type pool that supplies explicitly known type descriptions.
9158
     */
9159
    @HashCodeAndEqualsPlugin.Enhance
9160
    class Explicit extends AbstractBase.Hierarchical {
9161

9162
        /**
9163
         * A mapping from type names to type descriptions of that name.
9164
         */
9165
        private final Map<String, TypeDescription> types;
9166

9167
        /**
9168
         * Creates a new explicit type pool without a parent.
9169
         *
9170
         * @param types A mapping from type names to type descriptions of that name.
9171
         */
9172
        public Explicit(Map<String, TypeDescription> types) {
9173
            this(Empty.INSTANCE, types);
×
9174
        }
×
9175

9176
        /**
9177
         * Creates a new explicit type pool.
9178
         *
9179
         * @param parent The parent type pool.
9180
         * @param types  A mapping from type names to type descriptions of that name.
9181
         */
9182
        public Explicit(TypePool parent, Map<String, TypeDescription> types) {
9183
            super(CacheProvider.NoOp.INSTANCE, parent);
1✔
9184
            this.types = types;
1✔
9185
        }
1✔
9186

9187
        /**
9188
         * Wraps another type pool for an instrumented type and its auxiliary types.
9189
         *
9190
         * @param instrumentedType The instrumented type.
9191
         * @param auxiliaryTypes   The auxiliary types.
9192
         * @param typePool         The type pool to wrap.
9193
         * @return A type pool that also represents the instrumented type and its auxiliary types.
9194
         */
9195
        public static TypePool wrap(TypeDescription instrumentedType, List<? extends DynamicType> auxiliaryTypes, TypePool typePool) {
9196
            Map<String, TypeDescription> typeDescriptions = new HashMap<String, TypeDescription>();
1✔
9197
            typeDescriptions.put(instrumentedType.getName(), instrumentedType);
1✔
9198
            for (DynamicType auxiliaryType : auxiliaryTypes) {
1✔
9199
                for (TypeDescription typeDescription : auxiliaryType.getAllTypes().keySet()) {
1✔
9200
                    typeDescriptions.put(typeDescription.getName(), typeDescription);
1✔
9201
                }
1✔
9202
            }
1✔
9203
            return new Explicit(typePool, typeDescriptions);
1✔
9204
        }
9205

9206
        @Override
9207
        protected Resolution doDescribe(String name) {
9208
            TypeDescription typeDescription = types.get(name);
1✔
9209
            return typeDescription == null
1✔
9210
                    ? new Resolution.Illegal(name)
9211
                    : new Resolution.Simple(typeDescription);
9212
        }
9213
    }
9214
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc