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

raphw / byte-buddy / #641

19 Aug 2024 10:38PM CUT coverage: 85.389% (-0.06%) from 85.448%
#641

push

raphw
Disable validation for minor breakage of protected API.

28759 of 33680 relevant lines covered (85.39%)

0.85 hits per line

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

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

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

80
import static net.bytebuddy.matcher.ElementMatchers.hasDescriptor;
81
import static net.bytebuddy.matcher.ElementMatchers.hasMethodName;
82
import static net.bytebuddy.matcher.ElementMatchers.is;
83
import static net.bytebuddy.matcher.ElementMatchers.named;
84

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

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

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

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

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

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

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

132
            /**
133
             * The represented type description.
134
             */
135
            private final TypeDescription typeDescription;
136

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

263
        /**
264
         * Clears this cache.
265
         */
266
        void clear();
267

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

273
            /**
274
             * The singleton instance.
275
             */
276
            INSTANCE;
1✔
277

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

498
        /**
499
         * The singleton instance.
500
         */
501
        INSTANCE;
1✔
502

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

659
            /**
660
             * The parent type pool.
661
             */
662
            private final TypePool parent;
663

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

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

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

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

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

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

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

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

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

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

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

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

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

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

784
        /**
785
         * The class reader factory to use.
786
         */
787
        protected final AsmClassReader.Factory classReaderFactory;
788

789
        /**
790
         * Creates a new default type pool without a parent pool.
791
         *
792
         * @param cacheProvider    The cache provider to be used.
793
         * @param classFileLocator The class file locator to be used.
794
         * @param readerMode       The reader mode to apply by this default type pool.
795
         */
796
        public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode) {
797
            this(cacheProvider, classFileLocator, readerMode, Empty.INSTANCE);
1✔
798
        }
1✔
799

800
        /**
801
         * Creates a new default type pool.
802
         *
803
         * @param cacheProvider    The cache provider to be used.
804
         * @param classFileLocator The class file locator to be used.
805
         * @param readerMode       The reader mode to apply by this default type pool.
806
         * @param parentPool       The parent type pool.
807
         */
808
        public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, TypePool parentPool) {
809
            this(cacheProvider, classFileLocator, readerMode, AsmClassReader.Factory.Default.INSTANCE, parentPool);
1✔
810
        }
1✔
811

812
        /**
813
         * Creates a new default type pool that uses an explicit class reader factory.
814
         *
815
         * @param cacheProvider      The cache provider to be used.
816
         * @param classFileLocator   The class file locator to be used.
817
         * @param readerMode         The reader mode to apply by this default type pool.
818
         * @param classReaderFactory The class reader factory to use.
819
         */
820
        public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, AsmClassReader.Factory classReaderFactory) {
821
            this(cacheProvider, classFileLocator, readerMode, classReaderFactory, Empty.INSTANCE);
×
822
        }
×
823

824

825
        /**
826
         * Creates a new default type pool.
827
         *
828
         * @param cacheProvider      The cache provider to be used.
829
         * @param classFileLocator   The class file locator to be used.
830
         * @param readerMode         The reader mode to apply by this default type pool.
831
         * @param classReaderFactory The class reader factory to use.
832
         * @param parentPool         The parent type pool.
833
         */
834
        public Default(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, AsmClassReader.Factory classReaderFactory, TypePool parentPool) {
835
            super(cacheProvider, parentPool);
1✔
836
            this.classFileLocator = classFileLocator;
1✔
837
            this.readerMode = readerMode;
1✔
838
            this.classReaderFactory = classReaderFactory;
1✔
839
        }
1✔
840

841
        /**
842
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the system class
843
         * loader. The returned instance is configured to use a fast reading mode and a simple cache.
844
         *
845
         * @return A type pool that reads its data from the system class loader.
846
         */
847
        public static TypePool ofSystemLoader() {
848
            return of(ClassFileLocator.ForClassLoader.ofSystemLoader());
1✔
849
        }
850

851
        /**
852
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the plaform class
853
         * loader. The returned instance is configured to use a fast reading mode and a simple cache. If the current
854
         * VM is of version 8 or older, the extension class loader is represented instead.
855
         *
856
         * @return A type pool that reads its data from the platform class path.
857
         */
858
        public static TypePool ofPlatformLoader() {
859
            return of(ClassFileLocator.ForClassLoader.ofPlatformLoader());
×
860
        }
861

862
        /**
863
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the boot class
864
         * loader. The returned instance is configured to use a fast reading mode and a simple cache.
865
         *
866
         * @return A type pool that reads its data from the boot class loader.
867
         */
868
        public static TypePool ofBootLoader() {
869
            return of(ClassFileLocator.ForClassLoader.ofBootLoader());
×
870
        }
871

872
        /**
873
         * Returns a type pool for the provided class loader.
874
         *
875
         * @param classLoader The class loader for which this class pool is representing types.
876
         * @return An appropriate type pool.
877
         */
878
        public static TypePool of(@MaybeNull ClassLoader classLoader) {
879
            return of(ClassFileLocator.ForClassLoader.of(classLoader));
1✔
880
        }
881

882
        /**
883
         * Creates a default {@link net.bytebuddy.pool.TypePool} that looks up data by querying the supplied class
884
         * file locator. The returned instance is configured to use a fast reading mode and a simple cache.
885
         *
886
         * @param classFileLocator The class file locator to use.
887
         * @return A type pool that reads its data from the system class path.
888
         */
889
        public static TypePool of(ClassFileLocator classFileLocator) {
890
            return new Default(new CacheProvider.Simple(), classFileLocator, ReaderMode.FAST);
1✔
891
        }
892

893
        @Override
894
        protected Resolution doDescribe(String name) {
895
            try {
896
                ClassFileLocator.Resolution resolution = classFileLocator.locate(name);
1✔
897
                return resolution.isResolved()
1✔
898
                        ? new Resolution.Simple(parse(resolution.resolve()))
1✔
899
                        : new Resolution.Illegal(name);
900
            } catch (IOException exception) {
×
901
                throw new IllegalStateException("Error while reading class file", exception);
×
902
            }
903
        }
904

905
        /**
906
         * Parses a binary representation and transforms it into a type description.
907
         *
908
         * @param binaryRepresentation The binary data to be parsed.
909
         * @return A type description of the binary data.
910
         */
911
        private TypeDescription parse(byte[] binaryRepresentation) {
912
            AsmClassReader classReader = classReaderFactory.make(binaryRepresentation);
1✔
913
            TypeExtractor typeExtractor = new TypeExtractor();
1✔
914
            classReader.accept(typeExtractor, readerMode.getFlags());
1✔
915
            return typeExtractor.toTypeDescription();
1✔
916
        }
917

918
        /**
919
         * Determines the granularity of the class file parsing that is conducted by a {@link net.bytebuddy.pool.TypePool.Default}.
920
         */
921
        public enum ReaderMode {
1✔
922

923
            /**
924
             * The extended reader mode parses the code segment of each method in order to detect parameter names
925
             * that are only stored in a method's debugging information but are not explicitly included.
926
             */
927
            EXTENDED(ClassReader.SKIP_FRAMES),
1✔
928

929
            /**
930
             * The fast reader mode skips the code segment of each method and cannot detect parameter names that are
931
             * only contained within the debugging information. This mode still detects explicitly included method
932
             * parameter names.
933
             */
934
            FAST(ClassReader.SKIP_CODE);
1✔
935

936
            /**
937
             * The flags to provide to a {@link ClassReader} for parsing a file.
938
             */
939
            private final int flags;
940

941
            /**
942
             * Creates a new reader mode constant.
943
             *
944
             * @param flags The flags to provide to a {@link ClassReader} for parsing a file.
945
             */
946
            ReaderMode(int flags) {
1✔
947
                this.flags = flags;
1✔
948
            }
1✔
949

950
            /**
951
             * Returns the flags to provide to a {@link ClassReader} for parsing a file.
952
             *
953
             * @return The flags to provide to a {@link ClassReader} for parsing a file.
954
             */
955
            protected int getFlags() {
956
                return flags;
1✔
957
            }
958

959
            /**
960
             * Determines if this reader mode represents extended reading.
961
             *
962
             * @return {@code true} if this reader mode represents extended reading.
963
             */
964
            public boolean isExtended() {
965
                return this == EXTENDED;
1✔
966
            }
967
        }
968

969
        /**
970
         * <p>
971
         * A variant of {@link TypePool.Default} that resolves type descriptions lazily. A lazy resolution respects this type
972
         * pool's {@link CacheProvider} but requeries this cache pool for every access of a property of a {@link TypeDescription}.
973
         * </p>
974
         * <p>
975
         * {@link Resolution}s of this type pool are only fully resolved if a property that is not the type's name is required.
976
         * </p>
977
         */
978
        public static class WithLazyResolution extends Default {
979

980
            /**
981
             * Creates a new default type pool with lazy resolution and without a parent pool.
982
             *
983
             * @param cacheProvider    The cache provider to be used.
984
             * @param classFileLocator The class file locator to be used.
985
             * @param readerMode       The reader mode to apply by this default type pool.
986
             */
987
            public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode) {
988
                super(cacheProvider, classFileLocator, readerMode);
1✔
989
            }
1✔
990

991
            /**
992
             * Creates a new default type pool with lazy resolution.
993
             *
994
             * @param cacheProvider    The cache provider to be used.
995
             * @param classFileLocator The class file locator to be used.
996
             * @param readerMode       The reader mode to apply by this default type pool.
997
             * @param parentPool       The parent type pool.
998
             */
999
            public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, TypePool parentPool) {
1000
                super(cacheProvider, classFileLocator, readerMode, parentPool);
1✔
1001
            }
1✔
1002

1003
            /**
1004
             * Creates a new default type pool that uses an explicit class reader factory with lazy resolution.
1005
             *
1006
             * @param cacheProvider      The cache provider to be used.
1007
             * @param classFileLocator   The class file locator to be used.
1008
             * @param readerMode         The reader mode to apply by this default type pool.
1009
             * @param classReaderFactory The class reader factory to use.
1010
             */
1011
            public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, AsmClassReader.Factory classReaderFactory) {
1012
                super(cacheProvider, classFileLocator, readerMode, classReaderFactory);
×
1013
            }
×
1014

1015
            /**
1016
             * Creates a new default type pool that uses an explicit class reader factory with lazy resolution.
1017
             *
1018
             * @param cacheProvider      The cache provider to be used.
1019
             * @param classFileLocator   The class file locator to be used.
1020
             * @param readerMode         The reader mode to apply by this default type pool.
1021
             * @param classReaderFactory The class reader factory to use.
1022
             * @param parentPool         The parent type pool.
1023
             */
1024
            public WithLazyResolution(CacheProvider cacheProvider, ClassFileLocator classFileLocator, ReaderMode readerMode, AsmClassReader.Factory classReaderFactory, TypePool parentPool) {
1025
                super(cacheProvider, classFileLocator, readerMode, classReaderFactory, parentPool);
×
1026
            }
×
1027

1028
            /**
1029
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the system class
1030
             * loader. The returned instance is configured to use a fast reading mode and a simple cache.
1031
             *
1032
             * @return A type pool that reads its data from the system class loader.
1033
             */
1034
            public static TypePool ofSystemLoader() {
1035
                return of(ClassFileLocator.ForClassLoader.ofSystemLoader());
×
1036
            }
1037

1038
            /**
1039
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the platform class
1040
             * 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,
1041
             * the type pool represents the extension class loader.
1042
             *
1043
             * @return A type pool that reads its data from the boot class loader.
1044
             */
1045
            public static TypePool ofPlatformLoader() {
1046
                return of(ClassFileLocator.ForClassLoader.ofPlatformLoader());
×
1047
            }
1048

1049
            /**
1050
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the boot class
1051
             * loader. The returned instance is configured to use a fast reading mode and a simple cache.
1052
             *
1053
             * @return A type pool that reads its data from the boot class loader.
1054
             */
1055
            public static TypePool ofBootLoader() {
1056
                return of(ClassFileLocator.ForClassLoader.ofBootLoader());
×
1057
            }
1058

1059
            /**
1060
             * Returns a default {@link TypePool} with lazy resolution for the provided class loader.
1061
             *
1062
             * @param classLoader The class loader for which this class pool is representing types.
1063
             * @return An appropriate type pool.
1064
             */
1065
            public static TypePool of(@MaybeNull ClassLoader classLoader) {
1066
                return of(ClassFileLocator.ForClassLoader.of(classLoader));
×
1067
            }
1068

1069
            /**
1070
             * Creates a default {@link net.bytebuddy.pool.TypePool} with lazy resolution that looks up data by querying the supplied class
1071
             * file locator. The returned instance is configured to use a fast reading mode and a simple cache.
1072
             *
1073
             * @param classFileLocator The class file locator to use.
1074
             * @return A type pool that reads its data from the system class path.
1075
             */
1076
            public static TypePool of(ClassFileLocator classFileLocator) {
1077
                return new WithLazyResolution(new CacheProvider.Simple(), classFileLocator, ReaderMode.FAST);
1✔
1078
            }
1079

1080
            @Override
1081
            protected Resolution doDescribe(String name) {
1082
                return new LazyResolution(name);
1✔
1083
            }
1084

1085
            /**
1086
             * {@inheritDoc}
1087
             */
1088
            protected Resolution doCache(String name, Resolution resolution) {
1089
                return resolution;
1✔
1090
            }
1091

1092
            /**
1093
             * Non-lazily resolves a type name.
1094
             *
1095
             * @param name The name of the type to resolve.
1096
             * @return The resolution for the type of this name.
1097
             */
1098
            protected Resolution doResolve(String name) {
1099
                Resolution resolution = cacheProvider.find(name);
1✔
1100
                if (resolution == null) {
1✔
1101
                    resolution = cacheProvider.register(name, WithLazyResolution.super.doDescribe(name));
1✔
1102
                }
1103
                return resolution;
1✔
1104
            }
1105

1106
            /**
1107
             * A lazy resolution of a type that the enclosing type pool attempts to resolve.
1108
             */
1109
            @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
1110
            protected class LazyResolution implements Resolution {
1111

1112
                /**
1113
                 * The type's name.
1114
                 */
1115
                private final String name;
1116

1117
                /**
1118
                 * Creates a new lazy resolution.
1119
                 *
1120
                 * @param name The type's name.
1121
                 */
1122
                protected LazyResolution(String name) {
1✔
1123
                    this.name = name;
1✔
1124
                }
1✔
1125

1126
                /**
1127
                 * {@inheritDoc}
1128
                 */
1129
                public boolean isResolved() {
1130
                    return doResolve(name).isResolved();
1✔
1131
                }
1132

1133
                /**
1134
                 * {@inheritDoc}
1135
                 */
1136
                public TypeDescription resolve() {
1137
                    return new LazyTypeDescription(name);
1✔
1138
                }
1139
            }
1140

1141
            /**
1142
             * A lazy type description that resolves any property that is not the name only when requested.
1143
             */
1144
            protected class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType.WithDelegation {
1145

1146
                /**
1147
                 * The type's name.
1148
                 */
1149
                private final String name;
1150

1151
                /**
1152
                 * Creates a new lazy type description.
1153
                 *
1154
                 * @param name The type's name.
1155
                 */
1156
                protected LazyTypeDescription(String name) {
1✔
1157
                    this.name = name;
1✔
1158
                }
1✔
1159

1160
                /**
1161
                 * {@inheritDoc}
1162
                 */
1163
                public String getName() {
1164
                    return name;
1✔
1165
                }
1166

1167
                @Override
1168
                @CachedReturnPlugin.Enhance("delegate")
1169
                protected TypeDescription delegate() {
1170
                    return doResolve(name).resolve();
1✔
1171
                }
1172
            }
1173
        }
1174

1175
        /**
1176
         * An annotation registrant implements a visitor pattern for reading an unknown amount of values of annotations.
1177
         */
1178
        protected interface AnnotationRegistrant {
1179

1180
            /**
1181
             * Registers an annotation value.
1182
             *
1183
             * @param name            The name of the annotation value.
1184
             * @param annotationValue The value of the annotation.
1185
             */
1186
            void register(String name, AnnotationValue<?, ?> annotationValue);
1187

1188
            /**
1189
             * Called once all annotation values are visited.
1190
             */
1191
            void onComplete();
1192

1193
            /**
1194
             * An abstract base implementation of an annotation registrant.
1195
             */
1196
            abstract class AbstractBase implements AnnotationRegistrant {
1197

1198
                /**
1199
                 * The annotation descriptor.
1200
                 */
1201
                private final String descriptor;
1202

1203
                /**
1204
                 * The values that were collected so far.
1205
                 */
1206
                private final Map<String, AnnotationValue<?, ?>> values;
1207

1208
                /**
1209
                 * Creates a new annotation registrant.
1210
                 *
1211
                 * @param descriptor The annotation descriptor.
1212
                 */
1213
                protected AbstractBase(String descriptor) {
1✔
1214
                    this.descriptor = descriptor;
1✔
1215
                    values = new HashMap<String, AnnotationValue<?, ?>>();
1✔
1216
                }
1✔
1217

1218
                /**
1219
                 * {@inheritDoc}
1220
                 */
1221
                public void register(String name, AnnotationValue<?, ?> annotationValue) {
1222
                    values.put(name, annotationValue);
1✔
1223
                }
1✔
1224

1225
                /**
1226
                 * {@inheritDoc}
1227
                 */
1228
                public void onComplete() {
1229
                    getTokens().add(new LazyTypeDescription.AnnotationToken(descriptor, values));
1✔
1230
                }
1✔
1231

1232
                /**
1233
                 * Returns the token list for this collector.
1234
                 *
1235
                 * @return The token list for this collector.
1236
                 */
1237
                protected abstract List<LazyTypeDescription.AnnotationToken> getTokens();
1238

1239
                /**
1240
                 * A base implementation for a collector for a type variable.
1241
                 */
1242
                protected abstract static class ForTypeVariable extends AbstractBase {
1243

1244
                    /**
1245
                     * The type variable's type path.
1246
                     */
1247
                    private final String typePath;
1248

1249
                    /**
1250
                     * Creates a new annotation collector.
1251
                     *
1252
                     * @param descriptor The annotation descriptor.
1253
                     * @param typePath   The type variable's type path.
1254
                     */
1255
                    protected ForTypeVariable(String descriptor, @MaybeNull TypePath typePath) {
1256
                        super(descriptor);
1✔
1257
                        this.typePath = typePath == null
1✔
1258
                                ? LazyTypeDescription.GenericTypeToken.EMPTY_TYPE_PATH
1259
                                : typePath.toString();
1✔
1260
                    }
1✔
1261

1262
                    @Override
1263
                    protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1264
                        Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap = getPathMap();
1✔
1265
                        List<LazyTypeDescription.AnnotationToken> tokens = pathMap.get(typePath);
1✔
1266
                        if (tokens == null) {
1✔
1267
                            tokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
1268
                            pathMap.put(typePath, tokens);
1✔
1269
                        }
1270
                        return tokens;
1✔
1271
                    }
1272

1273
                    /**
1274
                     * Returns this collector's path map.
1275
                     *
1276
                     * @return This collector's path map.
1277
                     */
1278
                    protected abstract Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap();
1279

1280
                    /**
1281
                     * A base implementation for a collector for a type variable with an index.
1282
                     */
1283
                    protected abstract static class WithIndex extends AbstractBase.ForTypeVariable {
1284

1285
                        /**
1286
                         * The type variable's index.
1287
                         */
1288
                        private final int index;
1289

1290
                        /**
1291
                         * Creates a new annotation collector.
1292
                         *
1293
                         * @param descriptor The annotation descriptor.
1294
                         * @param typePath   The type variable's type path.
1295
                         * @param index      The type variable's index.
1296
                         */
1297
                        protected WithIndex(String descriptor, @MaybeNull TypePath typePath, int index) {
1298
                            super(descriptor, typePath);
1✔
1299
                            this.index = index;
1✔
1300
                        }
1✔
1301

1302
                        @Override
1303
                        protected Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap() {
1304
                            Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap = getIndexedPathMap();
1✔
1305
                            Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap = indexedPathMap.get(index);
1✔
1306
                            if (pathMap == null) {
1✔
1307
                                pathMap = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
1308
                                indexedPathMap.put(index, pathMap);
1✔
1309
                            }
1310
                            return pathMap;
1✔
1311
                        }
1312

1313
                        /**
1314
                         * Returns this collector's indexed path map.
1315
                         *
1316
                         * @return This collector's indexed path map.
1317
                         */
1318
                        protected abstract Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap();
1319

1320
                        /**
1321
                         * A base implementation for a collector for a type variable with two indices.
1322
                         */
1323
                        protected abstract static class DoubleIndexed extends WithIndex {
1324

1325
                            /**
1326
                             * The type variable's first index.
1327
                             */
1328
                            private final int preIndex;
1329

1330
                            /**
1331
                             * Creates a new annotation collector.
1332
                             *
1333
                             * @param descriptor The annotation descriptor.
1334
                             * @param typePath   The type variable's type path.
1335
                             * @param index      The type variable's index.
1336
                             * @param preIndex   The type variable's first index.
1337
                             */
1338
                            protected DoubleIndexed(String descriptor, @MaybeNull TypePath typePath, int index, int preIndex) {
1339
                                super(descriptor, typePath, index);
1✔
1340
                                this.preIndex = preIndex;
1✔
1341
                            }
1✔
1342

1343
                            @Override
1344
                            protected Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap() {
1345
                                Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexPathMap = getDoubleIndexedPathMap();
1✔
1346
                                Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap = doubleIndexPathMap.get(preIndex);
1✔
1347
                                if (indexedPathMap == null) {
1✔
1348
                                    indexedPathMap = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
1349
                                    doubleIndexPathMap.put(preIndex, indexedPathMap);
1✔
1350
                                }
1351
                                return indexedPathMap;
1✔
1352
                            }
1353

1354
                            /**
1355
                             * Returns this collector's double indexed path map.
1356
                             *
1357
                             * @return This collector's double indexed path map.
1358
                             */
1359
                            protected abstract Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> getDoubleIndexedPathMap();
1360
                        }
1361
                    }
1362
                }
1363
            }
1364

1365
            /**
1366
             * An annotation collector for a byte code element.
1367
             */
1368
            class ForByteCodeElement extends AbstractBase {
1369

1370
                /**
1371
                 * The target collection.
1372
                 */
1373
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
1374

1375
                /**
1376
                 * Creates a new annotation collector for a byte code element.
1377
                 *
1378
                 * @param descriptor       The annotation descriptor.
1379
                 * @param annotationTokens The target collection.
1380
                 */
1381
                protected ForByteCodeElement(String descriptor, List<LazyTypeDescription.AnnotationToken> annotationTokens) {
1382
                    super(descriptor);
1✔
1383
                    this.annotationTokens = annotationTokens;
1✔
1384
                }
1✔
1385

1386
                @Override
1387
                protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1388
                    return annotationTokens;
1✔
1389
                }
1390

1391
                /**
1392
                 * An annotation collector for a byte code element with an index.
1393
                 */
1394
                public static class WithIndex extends AbstractBase {
1395

1396
                    /**
1397
                     * The byte code element's index.
1398
                     */
1399
                    private final int index;
1400

1401
                    /**
1402
                     * The target collection.
1403
                     */
1404
                    private final Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens;
1405

1406
                    /**
1407
                     * Creates a new annotation collector for a byte code element with an index.
1408
                     *
1409
                     * @param descriptor       The annotation descriptor.
1410
                     * @param index            The byte code element's index.
1411
                     * @param annotationTokens The target collection.
1412
                     */
1413
                    protected WithIndex(String descriptor, int index, Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens) {
1414
                        super(descriptor);
1✔
1415
                        this.index = index;
1✔
1416
                        this.annotationTokens = annotationTokens;
1✔
1417
                    }
1✔
1418

1419
                    @Override
1420
                    protected List<LazyTypeDescription.AnnotationToken> getTokens() {
1421
                        List<LazyTypeDescription.AnnotationToken> annotationTokens = this.annotationTokens.get(index);
1✔
1422
                        if (annotationTokens == null) {
1✔
1423
                            annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
1424
                            this.annotationTokens.put(index, annotationTokens);
1✔
1425
                        }
1426
                        return annotationTokens;
1✔
1427
                    }
1428
                }
1429
            }
1430

1431
            /**
1432
             * An annotation collector for a type variable.
1433
             */
1434
            class ForTypeVariable extends AbstractBase.ForTypeVariable {
1435

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

1441
                /**
1442
                 * Creates a new annotation collector.
1443
                 *
1444
                 * @param descriptor The annotation descriptor.
1445
                 * @param typePath   The type variable's type path.
1446
                 * @param pathMap    The target collection.
1447
                 */
1448
                protected ForTypeVariable(String descriptor, @MaybeNull TypePath typePath, Map<String, List<LazyTypeDescription.AnnotationToken>> pathMap) {
1449
                    super(descriptor, typePath);
1✔
1450
                    this.pathMap = pathMap;
1✔
1451
                }
1✔
1452

1453
                @Override
1454
                protected Map<String, List<LazyTypeDescription.AnnotationToken>> getPathMap() {
1455
                    return pathMap;
1✔
1456
                }
1457

1458
                /**
1459
                 * An annotation collector for a type variable with an index.
1460
                 */
1461
                public static class WithIndex extends AbstractBase.ForTypeVariable.WithIndex {
1462

1463
                    /**
1464
                     * The target collection.
1465
                     */
1466
                    private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap;
1467

1468
                    /**
1469
                     * Creates a new annotation collector.
1470
                     *
1471
                     * @param descriptor     The annotation descriptor.
1472
                     * @param typePath       The type variable's type path.
1473
                     * @param index          The target index.
1474
                     * @param indexedPathMap The target collection.
1475
                     */
1476
                    protected WithIndex(String descriptor,
1477
                                        @MaybeNull TypePath typePath,
1478
                                        int index,
1479
                                        Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> indexedPathMap) {
1480
                        super(descriptor, typePath, index);
1✔
1481
                        this.indexedPathMap = indexedPathMap;
1✔
1482
                    }
1✔
1483

1484
                    @Override
1485
                    protected Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> getIndexedPathMap() {
1486
                        return indexedPathMap;
1✔
1487
                    }
1488

1489
                    /**
1490
                     * An annotation collector for a type variable with two indices.
1491
                     */
1492
                    public static class DoubleIndexed extends AbstractBase.ForTypeVariable.WithIndex.DoubleIndexed {
1493

1494
                        /**
1495
                         * The target collection.
1496
                         */
1497
                        private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexedPathMap;
1498

1499
                        /**
1500
                         * Creates a new annotation collector.
1501
                         *
1502
                         * @param descriptor           The annotation descriptor.
1503
                         * @param typePath             The type variable's type path.
1504
                         * @param index                The target index.
1505
                         * @param preIndex             The initial target index.
1506
                         * @param doubleIndexedPathMap The target collection.
1507
                         */
1508
                        protected DoubleIndexed(String descriptor,
1509
                                                @MaybeNull TypePath typePath,
1510
                                                int index,
1511
                                                int preIndex,
1512
                                                Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> doubleIndexedPathMap) {
1513
                            super(descriptor, typePath, index, preIndex);
1✔
1514
                            this.doubleIndexedPathMap = doubleIndexedPathMap;
1✔
1515
                        }
1✔
1516

1517
                        @Override
1518
                        protected Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> getDoubleIndexedPathMap() {
1519
                            return doubleIndexedPathMap;
1✔
1520
                        }
1521
                    }
1522
                }
1523
            }
1524
        }
1525

1526
        /**
1527
         * A component type locator allows for the lazy location of an array's component type.
1528
         */
1529
        protected interface ComponentTypeLocator {
1530

1531
            /**
1532
             * Binds this component type to a given property name of an annotation.
1533
             *
1534
             * @param name The name of an annotation property which the returned component type reference should
1535
             *             query for resolving an array's component type.
1536
             * @return A component type reference to an annotation value's component type.
1537
             */
1538
            ComponentTypeReference bind(String name);
1539

1540
            /**
1541
             * A component type locator which cannot legally resolve an array's component type.
1542
             */
1543
            enum Illegal implements ComponentTypeLocator {
1✔
1544

1545
                /**
1546
                 * The singleton instance.
1547
                 */
1548
                INSTANCE;
1✔
1549

1550
                /**
1551
                 * {@inheritDoc}
1552
                 */
1553
                public ComponentTypeReference bind(String name) {
1554
                    throw new IllegalStateException("Unexpected lookup of component type for " + name);
1✔
1555
                }
1556
            }
1557

1558
            /**
1559
             * A component type locator that lazily analyses an annotation for resolving an annotation property's
1560
             * array value's component type.
1561
             */
1562
            @HashCodeAndEqualsPlugin.Enhance
1563
            class ForAnnotationProperty implements ComponentTypeLocator {
1564

1565
                /**
1566
                 * The type pool to query for type descriptions.
1567
                 */
1568
                private final TypePool typePool;
1569

1570
                /**
1571
                 * The name of the annotation to analyze.
1572
                 */
1573
                private final String annotationName;
1574

1575
                /**
1576
                 * Creates a new component type locator for an array value.
1577
                 *
1578
                 * @param typePool             The type pool to be used for looking up linked types.
1579
                 * @param annotationDescriptor A descriptor of the annotation to analyze.
1580
                 */
1581
                public ForAnnotationProperty(TypePool typePool, String annotationDescriptor) {
1✔
1582
                    this.typePool = typePool;
1✔
1583
                    annotationName = annotationDescriptor.substring(1, annotationDescriptor.length() - 1).replace('/', '.');
1✔
1584
                }
1✔
1585

1586
                /**
1587
                 * {@inheritDoc}
1588
                 */
1589
                public ComponentTypeReference bind(String name) {
1590
                    return new Bound(name);
1✔
1591
                }
1592

1593
                /**
1594
                 * A bound representation of a
1595
                 * {@link net.bytebuddy.pool.TypePool.Default.ComponentTypeLocator.ForAnnotationProperty}.
1596
                 */
1597
                @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
1598
                protected class Bound implements ComponentTypeReference {
1599

1600
                    /**
1601
                     * The name of the annotation property.
1602
                     */
1603
                    private final String name;
1604

1605
                    /**
1606
                     * Creates a new bound component type locator for an annotation property.
1607
                     *
1608
                     * @param name The name of the annotation property.
1609
                     */
1610
                    protected Bound(String name) {
1✔
1611
                        this.name = name;
1✔
1612
                    }
1✔
1613

1614
                    /**
1615
                     * {@inheritDoc}
1616
                     */
1617
                    @MaybeNull
1618
                    public String resolve() {
1619
                        TypeDescription componentType = typePool.describe(annotationName)
1✔
1620
                                .resolve()
1✔
1621
                                .getDeclaredMethods()
1✔
1622
                                .filter(named(name))
1✔
1623
                                .getOnly()
1✔
1624
                                .getReturnType()
1✔
1625
                                .asErasure()
1✔
1626
                                .getComponentType();
1✔
1627
                        return componentType == null
1✔
1628
                                ? NO_ARRAY
1629
                                : componentType.getName();
1✔
1630
                    }
1631
                }
1632
            }
1633

1634
            /**
1635
             * A component type locator that locates an array type by a method's return value from its method descriptor.
1636
             */
1637
            @HashCodeAndEqualsPlugin.Enhance
1638
            class ForArrayType implements ComponentTypeLocator, ComponentTypeReference {
1639

1640
                /**
1641
                 * The resolved component type's binary name.
1642
                 */
1643
                private final String componentType;
1644

1645
                /**
1646
                 * Creates a new component type locator for an array type.
1647
                 *
1648
                 * @param methodDescriptor The method descriptor to resolve.
1649
                 */
1650
                public ForArrayType(String methodDescriptor) {
1✔
1651
                    String arrayType = Type.getMethodType(methodDescriptor).getReturnType().getClassName();
1✔
1652
                    componentType = arrayType.substring(0, arrayType.length() - 2);
1✔
1653
                }
1✔
1654

1655
                /**
1656
                 * {@inheritDoc}
1657
                 */
1658
                public ComponentTypeReference bind(String name) {
1659
                    return this;
1✔
1660
                }
1661

1662
                /**
1663
                 * {@inheritDoc}
1664
                 */
1665
                public String resolve() {
1666
                    return componentType;
1✔
1667
                }
1668
            }
1669
        }
1670

1671
        /**
1672
         * A type registrant allows to register a generic type token.
1673
         */
1674
        protected interface GenericTypeRegistrant {
1675

1676
            /**
1677
             * Registers a discovered generic type token.
1678
             *
1679
             * @param token The token to be registered.
1680
             */
1681
            void register(LazyTypeDescription.GenericTypeToken token);
1682

1683
            /**
1684
             * A signature visitor that rejects any discovered generic type.
1685
             */
1686
            class RejectingSignatureVisitor extends SignatureVisitor {
1687

1688
                /**
1689
                 * The message of the error message.
1690
                 */
1691
                private static final String MESSAGE = "Unexpected token in generic signature";
1692

1693
                /**
1694
                 * Creates a new rejecting signature visitor.
1695
                 */
1696
                public RejectingSignatureVisitor() {
1697
                    super(OpenedClassReader.ASM_API);
1✔
1698
                }
1✔
1699

1700
                /**
1701
                 * {@inheritDoc}
1702
                 */
1703
                public void visitFormalTypeParameter(String name) {
1704
                    throw new IllegalStateException(MESSAGE);
×
1705
                }
1706

1707
                /**
1708
                 * {@inheritDoc}
1709
                 */
1710
                public SignatureVisitor visitClassBound() {
1711
                    throw new IllegalStateException(MESSAGE);
×
1712
                }
1713

1714
                /**
1715
                 * {@inheritDoc}
1716
                 */
1717
                public SignatureVisitor visitInterfaceBound() {
1718
                    throw new IllegalStateException(MESSAGE);
×
1719
                }
1720

1721
                /**
1722
                 * {@inheritDoc}
1723
                 */
1724
                public SignatureVisitor visitSuperclass() {
1725
                    throw new IllegalStateException(MESSAGE);
1✔
1726
                }
1727

1728
                /**
1729
                 * {@inheritDoc}
1730
                 */
1731
                public SignatureVisitor visitInterface() {
1732
                    throw new IllegalStateException(MESSAGE);
×
1733
                }
1734

1735
                /**
1736
                 * {@inheritDoc}
1737
                 */
1738
                public SignatureVisitor visitParameterType() {
1739
                    throw new IllegalStateException(MESSAGE);
×
1740
                }
1741

1742
                /**
1743
                 * {@inheritDoc}
1744
                 */
1745
                public SignatureVisitor visitReturnType() {
1746
                    throw new IllegalStateException(MESSAGE);
×
1747
                }
1748

1749
                /**
1750
                 * {@inheritDoc}
1751
                 */
1752
                public SignatureVisitor visitExceptionType() {
1753
                    throw new IllegalStateException(MESSAGE);
×
1754
                }
1755

1756
                /**
1757
                 * {@inheritDoc}
1758
                 */
1759
                public void visitBaseType(char descriptor) {
1760
                    throw new IllegalStateException(MESSAGE);
×
1761
                }
1762

1763
                /**
1764
                 * {@inheritDoc}
1765
                 */
1766
                public void visitTypeVariable(String name) {
1767
                    throw new IllegalStateException(MESSAGE);
×
1768
                }
1769

1770
                /**
1771
                 * {@inheritDoc}
1772
                 */
1773
                public SignatureVisitor visitArrayType() {
1774
                    throw new IllegalStateException(MESSAGE);
×
1775
                }
1776

1777
                /**
1778
                 * {@inheritDoc}
1779
                 */
1780
                public void visitClassType(String name) {
1781
                    throw new IllegalStateException(MESSAGE);
×
1782
                }
1783

1784
                /**
1785
                 * {@inheritDoc}
1786
                 */
1787
                public void visitInnerClassType(String name) {
1788
                    throw new IllegalStateException(MESSAGE);
×
1789
                }
1790

1791
                /**
1792
                 * {@inheritDoc}
1793
                 */
1794
                public void visitTypeArgument() {
1795
                    throw new IllegalStateException(MESSAGE);
×
1796
                }
1797

1798
                /**
1799
                 * {@inheritDoc}
1800
                 */
1801
                public SignatureVisitor visitTypeArgument(char wildcard) {
1802
                    throw new IllegalStateException(MESSAGE);
×
1803
                }
1804

1805
                /**
1806
                 * {@inheritDoc}
1807
                 */
1808
                public void visitEnd() {
1809
                    throw new IllegalStateException(MESSAGE);
×
1810
                }
1811
            }
1812
        }
1813

1814
        /**
1815
         * A bag for collecting parameter meta information that is stored as debug information for implemented
1816
         * methods.
1817
         */
1818
        protected static class ParameterBag {
1819

1820
            /**
1821
             * An array of the method's parameter types.
1822
             */
1823
            private final Type[] parameterType;
1824

1825
            /**
1826
             * A map containing the tokens that were collected until now.
1827
             */
1828
            private final Map<Integer, String> parameterRegistry;
1829

1830
            /**
1831
             * Creates a new bag.
1832
             *
1833
             * @param parameterType An array of parameter types for the method on which this parameter bag
1834
             *                      is used.
1835
             */
1836
            protected ParameterBag(Type[] parameterType) {
1✔
1837
                this.parameterType = parameterType;
1✔
1838
                parameterRegistry = new HashMap<Integer, String>();
1✔
1839
            }
1✔
1840

1841
            /**
1842
             * Registers a new parameter.
1843
             *
1844
             * @param offset The offset of the registered entry on the local variable array of the method.
1845
             * @param name   The name of the parameter.
1846
             */
1847
            protected void register(int offset, String name) {
1848
                parameterRegistry.put(offset, name);
1✔
1849
            }
1✔
1850

1851
            /**
1852
             * Resolves the collected parameters as a list of parameter tokens.
1853
             *
1854
             * @param isStatic {@code true} if the analyzed method is static.
1855
             * @return A list of parameter tokens based on the collected information.
1856
             */
1857
            protected List<LazyTypeDescription.MethodToken.ParameterToken> resolve(boolean isStatic) {
1858
                List<LazyTypeDescription.MethodToken.ParameterToken> parameterTokens = new ArrayList<LazyTypeDescription.MethodToken.ParameterToken>(parameterType.length);
1✔
1859
                int offset = isStatic
1✔
1860
                        ? StackSize.ZERO.getSize()
1✔
1861
                        : StackSize.SINGLE.getSize();
1✔
1862
                for (Type aParameterType : parameterType) {
1✔
1863
                    String name = this.parameterRegistry.get(offset);
1✔
1864
                    parameterTokens.add(name == null
1✔
1865
                            ? new LazyTypeDescription.MethodToken.ParameterToken()
1866
                            : new LazyTypeDescription.MethodToken.ParameterToken(name));
1867
                    offset += aParameterType.getSize();
1✔
1868
                }
1869
                return parameterTokens;
1✔
1870
            }
1871
        }
1872

1873
        /**
1874
         * A generic type extractor allows for an iterative extraction of generic type information.
1875
         */
1876
        protected static class GenericTypeExtractor extends GenericTypeRegistrant.RejectingSignatureVisitor implements GenericTypeRegistrant {
1877

1878
            /**
1879
             * A registrant that receives any discovered type.
1880
             */
1881
            private final GenericTypeRegistrant genericTypeRegistrant;
1882

1883
            /**
1884
             * The current token that is in the process of creation.
1885
             */
1886
            @UnknownNull
1887
            private IncompleteToken incompleteToken;
1888

1889
            /**
1890
             * Creates a new generic type extractor.
1891
             *
1892
             * @param genericTypeRegistrant The target to receive the complete type.
1893
             */
1894
            protected GenericTypeExtractor(GenericTypeRegistrant genericTypeRegistrant) {
1✔
1895
                this.genericTypeRegistrant = genericTypeRegistrant;
1✔
1896
            }
1✔
1897

1898
            /**
1899
             * {@inheritDoc}
1900
             */
1901
            public void visitBaseType(char descriptor) {
1902
                genericTypeRegistrant.register(LazyTypeDescription.GenericTypeToken.ForPrimitiveType.of(descriptor));
1✔
1903
            }
1✔
1904

1905
            /**
1906
             * {@inheritDoc}
1907
             */
1908
            public void visitTypeVariable(String name) {
1909
                genericTypeRegistrant.register(new LazyTypeDescription.GenericTypeToken.ForTypeVariable(name));
1✔
1910
            }
1✔
1911

1912
            /**
1913
             * {@inheritDoc}
1914
             */
1915
            public SignatureVisitor visitArrayType() {
1916
                return new GenericTypeExtractor(this);
1✔
1917
            }
1918

1919
            /**
1920
             * {@inheritDoc}
1921
             */
1922
            public void register(LazyTypeDescription.GenericTypeToken componentTypeToken) {
1923
                genericTypeRegistrant.register(new LazyTypeDescription.GenericTypeToken.ForGenericArray(componentTypeToken));
1✔
1924
            }
1✔
1925

1926
            /**
1927
             * {@inheritDoc}
1928
             */
1929
            public void visitClassType(String name) {
1930
                incompleteToken = new IncompleteToken.ForTopLevelType(name);
1✔
1931
            }
1✔
1932

1933
            /**
1934
             * {@inheritDoc}
1935
             */
1936
            public void visitInnerClassType(String name) {
1937
                incompleteToken = new IncompleteToken.ForInnerClass(name, incompleteToken);
1✔
1938
            }
1✔
1939

1940
            /**
1941
             * {@inheritDoc}
1942
             */
1943
            public void visitTypeArgument() {
1944
                incompleteToken.appendPlaceholder();
1✔
1945
            }
1✔
1946

1947
            /**
1948
             * {@inheritDoc}
1949
             */
1950
            public SignatureVisitor visitTypeArgument(char wildcard) {
1951
                switch (wildcard) {
1✔
1952
                    case SignatureVisitor.SUPER:
1953
                        return incompleteToken.appendLowerBound();
1✔
1954
                    case SignatureVisitor.EXTENDS:
1955
                        return incompleteToken.appendUpperBound();
1✔
1956
                    case SignatureVisitor.INSTANCEOF:
1957
                        return incompleteToken.appendDirectBound();
1✔
1958
                    default:
1959
                        throw new IllegalArgumentException("Unknown wildcard: " + wildcard);
×
1960
                }
1961
            }
1962

1963
            /**
1964
             * {@inheritDoc}
1965
             */
1966
            public void visitEnd() {
1967
                genericTypeRegistrant.register(incompleteToken.toToken());
1✔
1968
            }
1✔
1969

1970
            /**
1971
             * An incomplete {@link LazyTypeDescription.GenericTypeToken}.
1972
             */
1973
            protected interface IncompleteToken {
1974

1975
                /**
1976
                 * Appends a lower bound to this token.
1977
                 *
1978
                 * @return A signature visitor for visiting the lower bound's type.
1979
                 */
1980
                SignatureVisitor appendLowerBound();
1981

1982
                /**
1983
                 * Appends an upper bound to this token.
1984
                 *
1985
                 * @return A signature visitor for visiting the upper bound's type.
1986
                 */
1987
                SignatureVisitor appendUpperBound();
1988

1989
                /**
1990
                 * Appends a direct bound to this token.
1991
                 *
1992
                 * @return A signature visitor for visiting the direct bound's type.
1993
                 */
1994
                SignatureVisitor appendDirectBound();
1995

1996
                /**
1997
                 * Appends a placeholder to this token.
1998
                 */
1999
                void appendPlaceholder();
2000

2001
                /**
2002
                 * Returns {@code true} if this token describes a type with parameters.
2003
                 *
2004
                 * @return {@code true} if this token describes a type with parameters.
2005
                 */
2006
                boolean isParameterized();
2007

2008
                /**
2009
                 * Returns the name of this token.
2010
                 *
2011
                 * @return The name of this token.
2012
                 */
2013
                String getName();
2014

2015
                /**
2016
                 * Converts this incomplete token to a completed token.
2017
                 *
2018
                 * @return The finalized token.
2019
                 */
2020
                LazyTypeDescription.GenericTypeToken toToken();
2021

2022
                /**
2023
                 * An abstract base implementation of an incomplete token.
2024
                 */
2025
                abstract class AbstractBase implements IncompleteToken {
2026

2027
                    /**
2028
                     * The parameters of this token.
2029
                     */
2030
                    protected final List<LazyTypeDescription.GenericTypeToken> parameters;
2031

2032
                    /**
2033
                     * Creates a new base implementation of an incomplete token.
2034
                     */
2035
                    public AbstractBase() {
1✔
2036
                        parameters = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2037
                    }
1✔
2038

2039
                    /**
2040
                     * {@inheritDoc}
2041
                     */
2042
                    public SignatureVisitor appendDirectBound() {
2043
                        return new GenericTypeExtractor(new ForDirectBound());
1✔
2044
                    }
2045

2046
                    /**
2047
                     * {@inheritDoc}
2048
                     */
2049
                    public SignatureVisitor appendUpperBound() {
2050
                        return new GenericTypeExtractor(new ForUpperBound());
1✔
2051
                    }
2052

2053
                    /**
2054
                     * {@inheritDoc}
2055
                     */
2056
                    public SignatureVisitor appendLowerBound() {
2057
                        return new GenericTypeExtractor(new ForLowerBound());
1✔
2058
                    }
2059

2060
                    /**
2061
                     * {@inheritDoc}
2062
                     */
2063
                    public void appendPlaceholder() {
2064
                        parameters.add(LazyTypeDescription.GenericTypeToken.ForUnboundWildcard.INSTANCE);
1✔
2065
                    }
1✔
2066

2067
                    /**
2068
                     * A token for registering a direct bound.
2069
                     */
2070
                    protected class ForDirectBound implements GenericTypeRegistrant {
1✔
2071

2072
                        /**
2073
                         * {@inheritDoc}
2074
                         */
2075
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2076
                            parameters.add(token);
1✔
2077
                        }
1✔
2078
                    }
2079

2080
                    /**
2081
                     * A token for registering a wildcard with an upper bound.
2082
                     */
2083
                    protected class ForUpperBound implements GenericTypeRegistrant {
1✔
2084

2085
                        /**
2086
                         * {@inheritDoc}
2087
                         */
2088
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2089
                            parameters.add(new LazyTypeDescription.GenericTypeToken.ForUpperBoundWildcard(token));
1✔
2090
                        }
1✔
2091
                    }
2092

2093
                    /**
2094
                     * A token for registering a wildcard with a lower bound.
2095
                     */
2096
                    protected class ForLowerBound implements GenericTypeRegistrant {
1✔
2097

2098
                        /**
2099
                         * {@inheritDoc}
2100
                         */
2101
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2102
                            parameters.add(new LazyTypeDescription.GenericTypeToken.ForLowerBoundWildcard(token));
1✔
2103
                        }
1✔
2104
                    }
2105
                }
2106

2107
                /**
2108
                 * An incomplete token representing a generic type without an outer type.
2109
                 */
2110
                @HashCodeAndEqualsPlugin.Enhance
2111
                class ForTopLevelType extends AbstractBase {
2112

2113
                    /**
2114
                     * The internal name of the type.
2115
                     */
2116
                    private final String internalName;
2117

2118
                    /**
2119
                     * Creates a new incomplete token representing a type without an outer type.
2120
                     *
2121
                     * @param internalName The internal name of the type.
2122
                     */
2123
                    public ForTopLevelType(String internalName) {
1✔
2124
                        this.internalName = internalName;
1✔
2125
                    }
1✔
2126

2127
                    /**
2128
                     * {@inheritDoc}
2129
                     */
2130
                    public LazyTypeDescription.GenericTypeToken toToken() {
2131
                        return isParameterized()
1✔
2132
                                ? new LazyTypeDescription.GenericTypeToken.ForParameterizedType(getName(), parameters)
1✔
2133
                                : new LazyTypeDescription.GenericTypeToken.ForRawType(getName());
1✔
2134
                    }
2135

2136
                    /**
2137
                     * {@inheritDoc}
2138
                     */
2139
                    public boolean isParameterized() {
2140
                        return !parameters.isEmpty();
1✔
2141
                    }
2142

2143
                    /**
2144
                     * {@inheritDoc}
2145
                     */
2146
                    public String getName() {
2147
                        return internalName.replace('/', '.');
1✔
2148
                    }
2149
                }
2150

2151
                /**
2152
                 * An incomplete generic type token representing a type with an outer type.
2153
                 */
2154
                @HashCodeAndEqualsPlugin.Enhance
2155
                class ForInnerClass extends AbstractBase {
2156

2157
                    /**
2158
                     * The separator that indicates an inner type.
2159
                     */
2160
                    private static final char INNER_CLASS_SEPARATOR = '$';
2161

2162
                    /**
2163
                     * The internal name of the type.
2164
                     */
2165
                    private final String internalName;
2166

2167
                    /**
2168
                     * The token representing the outer type.
2169
                     */
2170
                    private final IncompleteToken outerTypeToken;
2171

2172
                    /**
2173
                     * Creates a new incomplete token representing a type without an outer type.
2174
                     *
2175
                     * @param internalName   The internal name of the type.
2176
                     * @param outerTypeToken The incomplete token representing the outer type.
2177
                     */
2178
                    public ForInnerClass(String internalName, IncompleteToken outerTypeToken) {
1✔
2179
                        this.internalName = internalName;
1✔
2180
                        this.outerTypeToken = outerTypeToken;
1✔
2181
                    }
1✔
2182

2183
                    /**
2184
                     * {@inheritDoc}
2185
                     */
2186
                    public LazyTypeDescription.GenericTypeToken toToken() {
2187
                        return isParameterized() || outerTypeToken.isParameterized()
1✔
2188
                                ? new LazyTypeDescription.GenericTypeToken.ForParameterizedType.Nested(getName(), parameters, outerTypeToken.toToken())
1✔
2189
                                : new LazyTypeDescription.GenericTypeToken.ForRawType(getName());
×
2190
                    }
2191

2192
                    /**
2193
                     * {@inheritDoc}
2194
                     */
2195
                    public boolean isParameterized() {
2196
                        return !parameters.isEmpty() || !outerTypeToken.isParameterized();
1✔
2197
                    }
2198

2199
                    /**
2200
                     * {@inheritDoc}
2201
                     */
2202
                    public String getName() {
2203
                        return outerTypeToken.getName() + INNER_CLASS_SEPARATOR + internalName.replace('/', '.');
1✔
2204
                    }
2205
                }
2206
            }
2207

2208
            /**
2209
             * A signature visitor for extracting a generic type resolution.
2210
             *
2211
             * @param <T> The type of the resolution this visitor extracts.
2212
             */
2213
            protected abstract static class ForSignature<T extends LazyTypeDescription.GenericTypeToken.Resolution>
2214
                    extends RejectingSignatureVisitor
2215
                    implements GenericTypeRegistrant {
2216

2217
                /**
2218
                 * The resolved type variable tokens.
2219
                 */
2220
                protected final List<LazyTypeDescription.GenericTypeToken.OfFormalTypeVariable> typeVariableTokens;
2221

2222
                /**
2223
                 * The name of the currently constructed type.
2224
                 */
2225
                @MaybeNull
2226
                protected String currentTypeParameter;
2227

2228
                /**
2229
                 * The bounds of the currently constructed type.
2230
                 */
2231
                @UnknownNull
2232
                protected List<LazyTypeDescription.GenericTypeToken> currentBounds;
2233

2234
                /**
2235
                 * Creates a new signature visitor.
2236
                 */
2237
                public ForSignature() {
1✔
2238
                    typeVariableTokens = new ArrayList<LazyTypeDescription.GenericTypeToken.OfFormalTypeVariable>();
1✔
2239
                }
1✔
2240

2241
                /**
2242
                 * Applies an extraction of a generic signature given the supplied visitor.
2243
                 *
2244
                 * @param genericSignature The generic signature to interpret.
2245
                 * @param visitor          The visitor to apply.
2246
                 * @param <S>              The type of the generated resolution.
2247
                 * @return The resolution of the supplied signature.
2248
                 */
2249
                protected static <S extends LazyTypeDescription.GenericTypeToken.Resolution> S extract(String genericSignature, ForSignature<S> visitor) {
2250
                    SignatureReader signatureReader = new SignatureReader(genericSignature);
1✔
2251
                    signatureReader.accept(visitor);
1✔
2252
                    return visitor.resolve();
1✔
2253
                }
2254

2255
                /**
2256
                 * {@inheritDoc}
2257
                 */
2258
                public void visitFormalTypeParameter(String name) {
2259
                    collectTypeParameter();
1✔
2260
                    currentTypeParameter = name;
1✔
2261
                    currentBounds = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2262
                }
1✔
2263

2264
                /**
2265
                 * {@inheritDoc}
2266
                 */
2267
                public SignatureVisitor visitClassBound() {
2268
                    return new GenericTypeExtractor(this);
1✔
2269
                }
2270

2271
                /**
2272
                 * {@inheritDoc}
2273
                 */
2274
                public SignatureVisitor visitInterfaceBound() {
2275
                    return new GenericTypeExtractor(this);
1✔
2276
                }
2277

2278
                /**
2279
                 * {@inheritDoc}
2280
                 */
2281
                public void register(LazyTypeDescription.GenericTypeToken token) {
2282
                    if (currentBounds == null) {
1✔
2283
                        throw new IllegalStateException("Did not expect " + token + " before finding formal parameter");
×
2284
                    }
2285
                    currentBounds.add(token);
1✔
2286
                }
1✔
2287

2288
                /**
2289
                 * Collects the currently constructed type.
2290
                 */
2291
                protected void collectTypeParameter() {
2292
                    if (currentTypeParameter != null) {
1✔
2293
                        typeVariableTokens.add(new LazyTypeDescription.GenericTypeToken.ForTypeVariable.Formal(currentTypeParameter, currentBounds));
1✔
2294
                    }
2295
                }
1✔
2296

2297
                /**
2298
                 * Completes the current resolution.
2299
                 *
2300
                 * @return The resolved generic signature.
2301
                 */
2302
                public abstract T resolve();
2303

2304
                /**
2305
                 * A parser for a generic type signature.
2306
                 */
2307
                protected static class OfType extends ForSignature<LazyTypeDescription.GenericTypeToken.Resolution.ForType> {
2308

2309
                    /**
2310
                     * The interface type's generic signatures.
2311
                     */
2312
                    private final List<LazyTypeDescription.GenericTypeToken> interfaceTypeTokens;
2313

2314
                    /**
2315
                     * The super type's generic signature.
2316
                     */
2317
                    @UnknownNull
2318
                    private LazyTypeDescription.GenericTypeToken superClassToken;
2319

2320
                    /**
2321
                     * Creates a new parser for a type signature.
2322
                     */
2323
                    protected OfType() {
1✔
2324
                        interfaceTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2325
                    }
1✔
2326

2327
                    /**
2328
                     * Extracts a generic type resolution of a type signature.
2329
                     *
2330
                     * @param genericSignature The signature to interpret.
2331
                     * @return The interpreted type signature.
2332
                     */
2333
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForType extract(@MaybeNull String genericSignature) {
2334
                        try {
2335
                            return genericSignature == null
1✔
2336
                                    ? LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE
2337
                                    : ForSignature.extract(genericSignature, new OfType());
1✔
2338
                        } catch (RuntimeException ignored) {
1✔
2339
                            return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
1✔
2340
                        }
2341
                    }
2342

2343
                    /**
2344
                     * {@inheritDoc}
2345
                     */
2346
                    public SignatureVisitor visitSuperclass() {
2347
                        collectTypeParameter();
1✔
2348
                        return new GenericTypeExtractor(new SuperClassRegistrant());
1✔
2349
                    }
2350

2351
                    /**
2352
                     * {@inheritDoc}
2353
                     */
2354
                    public SignatureVisitor visitInterface() {
2355
                        return new GenericTypeExtractor(new InterfaceTypeRegistrant());
1✔
2356
                    }
2357

2358
                    /**
2359
                     * {@inheritDoc}
2360
                     */
2361
                    public LazyTypeDescription.GenericTypeToken.Resolution.ForType resolve() {
2362
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForType.Tokenized(superClassToken, interfaceTypeTokens, typeVariableTokens);
1✔
2363
                    }
2364

2365
                    /**
2366
                     * A registrant for the super type.
2367
                     */
2368
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2369
                    protected class SuperClassRegistrant implements GenericTypeRegistrant {
1✔
2370

2371
                        /**
2372
                         * {@inheritDoc}
2373
                         */
2374
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2375
                            superClassToken = token;
1✔
2376
                        }
1✔
2377
                    }
2378

2379
                    /**
2380
                     * A registrant for the interface types.
2381
                     */
2382
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2383
                    protected class InterfaceTypeRegistrant implements GenericTypeRegistrant {
1✔
2384

2385
                        /**
2386
                         * {@inheritDoc}
2387
                         */
2388
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2389
                            interfaceTypeTokens.add(token);
1✔
2390
                        }
1✔
2391
                    }
2392
                }
2393

2394
                /**
2395
                 * A parser for a generic field signature.
2396
                 */
2397
                protected static class OfField implements GenericTypeRegistrant {
1✔
2398

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

2405
                    /**
2406
                     * Extracts a generic field resolution of a field signature.
2407
                     *
2408
                     * @param genericSignature The signature to interpret.
2409
                     * @return The interpreted field signature.
2410
                     */
2411
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForField extract(@MaybeNull String genericSignature) {
2412
                        if (genericSignature == null) {
1✔
2413
                            return LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE;
1✔
2414
                        } else {
2415
                            SignatureReader signatureReader = new SignatureReader(genericSignature);
1✔
2416
                            OfField visitor = new OfField();
1✔
2417
                            try {
2418
                                signatureReader.acceptType(new GenericTypeExtractor(visitor));
1✔
2419
                                return visitor.resolve();
1✔
2420
                            } catch (RuntimeException ignored) {
1✔
2421
                                return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
1✔
2422
                            }
2423
                        }
2424
                    }
2425

2426
                    /**
2427
                     * {@inheritDoc}
2428
                     */
2429
                    public void register(LazyTypeDescription.GenericTypeToken token) {
2430
                        fieldTypeToken = token;
1✔
2431
                    }
1✔
2432

2433
                    /**
2434
                     * Completes the current resolution.
2435
                     *
2436
                     * @return The resolved generic signature.
2437
                     */
2438
                    protected LazyTypeDescription.GenericTypeToken.Resolution.ForField resolve() {
2439
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForField.Tokenized(fieldTypeToken);
1✔
2440
                    }
2441
                }
2442

2443
                /**
2444
                 * A parser for a generic method signature.
2445
                 */
2446
                protected static class OfMethod extends ForSignature<LazyTypeDescription.GenericTypeToken.Resolution.ForMethod> {
2447

2448
                    /**
2449
                     * The generic parameter types.
2450
                     */
2451
                    private final List<LazyTypeDescription.GenericTypeToken> parameterTypeTokens;
2452

2453
                    /**
2454
                     * The generic exception types.
2455
                     */
2456
                    private final List<LazyTypeDescription.GenericTypeToken> exceptionTypeTokens;
2457

2458
                    /**
2459
                     * The generic return type.
2460
                     */
2461
                    @UnknownNull
2462
                    private LazyTypeDescription.GenericTypeToken returnTypeToken;
2463

2464
                    /**
2465
                     * Creates a parser for a generic method signature.
2466
                     */
2467
                    public OfMethod() {
1✔
2468
                        parameterTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2469
                        exceptionTypeTokens = new ArrayList<LazyTypeDescription.GenericTypeToken>();
1✔
2470
                    }
1✔
2471

2472
                    /**
2473
                     * Extracts a generic method resolution of a method signature.
2474
                     *
2475
                     * @param genericSignature The signature to interpret.
2476
                     * @return The interpreted method signature.
2477
                     */
2478
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForMethod extract(@MaybeNull String genericSignature) {
2479
                        try {
2480
                            return genericSignature == null
1✔
2481
                                    ? LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE
2482
                                    : ForSignature.extract(genericSignature, new OfMethod());
1✔
2483
                        } catch (RuntimeException ignored) {
1✔
2484
                            return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
1✔
2485
                        }
2486
                    }
2487

2488
                    /**
2489
                     * {@inheritDoc}
2490
                     */
2491
                    public SignatureVisitor visitParameterType() {
2492
                        return new GenericTypeExtractor(new ParameterTypeRegistrant());
1✔
2493
                    }
2494

2495
                    /**
2496
                     * {@inheritDoc}
2497
                     */
2498
                    public SignatureVisitor visitReturnType() {
2499
                        collectTypeParameter();
1✔
2500
                        return new GenericTypeExtractor(new ReturnTypeTypeRegistrant());
1✔
2501
                    }
2502

2503
                    /**
2504
                     * {@inheritDoc}
2505
                     */
2506
                    public SignatureVisitor visitExceptionType() {
2507
                        return new GenericTypeExtractor(new ExceptionTypeRegistrant());
1✔
2508
                    }
2509

2510
                    /**
2511
                     * {@inheritDoc}
2512
                     */
2513
                    public LazyTypeDescription.GenericTypeToken.Resolution.ForMethod resolve() {
2514
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForMethod.Tokenized(returnTypeToken,
1✔
2515
                                parameterTypeTokens,
2516
                                exceptionTypeTokens,
2517
                                typeVariableTokens);
2518
                    }
2519

2520
                    /**
2521
                     * A registrant for a parameter type.
2522
                     */
2523
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2524
                    protected class ParameterTypeRegistrant implements GenericTypeRegistrant {
1✔
2525

2526
                        /**
2527
                         * {@inheritDoc}
2528
                         */
2529
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2530
                            parameterTypeTokens.add(token);
1✔
2531
                        }
1✔
2532
                    }
2533

2534
                    /**
2535
                     * A registrant for a return type.
2536
                     */
2537
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2538
                    protected class ReturnTypeTypeRegistrant implements GenericTypeRegistrant {
1✔
2539

2540
                        /**
2541
                         * {@inheritDoc}
2542
                         */
2543
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2544
                            returnTypeToken = token;
1✔
2545
                        }
1✔
2546
                    }
2547

2548
                    /**
2549
                     * A registrant for an exception type.
2550
                     */
2551
                    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
2552
                    protected class ExceptionTypeRegistrant implements GenericTypeRegistrant {
1✔
2553

2554
                        /**
2555
                         * {@inheritDoc}
2556
                         */
2557
                        public void register(LazyTypeDescription.GenericTypeToken token) {
2558
                            exceptionTypeTokens.add(token);
1✔
2559
                        }
1✔
2560
                    }
2561
                }
2562

2563
                /**
2564
                 * A parser for a generic field signature.
2565
                 */
2566
                protected static class OfRecordComponent implements GenericTypeRegistrant {
×
2567

2568
                    /**
2569
                     * The generic field type.
2570
                     */
2571
                    @UnknownNull
2572
                    private LazyTypeDescription.GenericTypeToken recordComponentType;
2573

2574
                    /**
2575
                     * Extracts a generic field resolution of a field signature.
2576
                     *
2577
                     * @param genericSignature The signature to interpret.
2578
                     * @return The interpreted field signature.
2579
                     */
2580
                    public static LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent extract(@MaybeNull String genericSignature) {
2581
                        if (genericSignature == null) {
×
2582
                            return LazyTypeDescription.GenericTypeToken.Resolution.Raw.INSTANCE;
×
2583
                        } else {
2584
                            SignatureReader signatureReader = new SignatureReader(genericSignature);
×
2585
                            OfRecordComponent visitor = new OfRecordComponent();
×
2586
                            try {
2587
                                signatureReader.acceptType(new GenericTypeExtractor(visitor));
×
2588
                                return visitor.resolve();
×
2589
                            } catch (RuntimeException ignored) {
×
2590
                                return LazyTypeDescription.GenericTypeToken.Resolution.Malformed.INSTANCE;
×
2591
                            }
2592
                        }
2593
                    }
2594

2595
                    /**
2596
                     * {@inheritDoc}
2597
                     */
2598
                    public void register(LazyTypeDescription.GenericTypeToken token) {
2599
                        recordComponentType = token;
×
2600
                    }
×
2601

2602
                    /**
2603
                     * Completes the current resolution.
2604
                     *
2605
                     * @return The resolved generic signature.
2606
                     */
2607
                    protected LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent resolve() {
2608
                        return new LazyTypeDescription.GenericTypeToken.Resolution.ForRecordComponent.Tokenized(recordComponentType);
×
2609
                    }
2610
                }
2611
            }
2612
        }
2613

2614
        /**
2615
         * A type description that looks up any referenced {@link net.bytebuddy.description.ByteCodeElement} or
2616
         * {@link AnnotationDescription} by querying a type pool at lookup time.
2617
         */
2618
        protected static class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType {
2619

2620
            /**
2621
             * Indicates that a type does not exist and does therefore not have a name.
2622
             */
2623
            @AlwaysNull
2624
            private static final String NO_TYPE = null;
1✔
2625

2626
            /**
2627
             * The type pool to be used for looking up linked types.
2628
             */
2629
            private final TypePool typePool;
2630

2631
            /**
2632
             * The actual modifiers of this type.
2633
             */
2634
            private final int actualModifiers;
2635

2636
            /**
2637
             * The modifiers of this type.
2638
             */
2639
            private final int modifiers;
2640

2641
            /**
2642
             * The binary name of this type.
2643
             */
2644
            private final String name;
2645

2646
            /**
2647
             * The type's super type's descriptor or {@code null} if this type does not define a super type.
2648
             */
2649
            @MaybeNull
2650
            private final String superClassDescriptor;
2651

2652
            /**
2653
             * The type's generic signature as found in the class file or {@code null} if the type is not generic.
2654
             */
2655
            @MaybeNull
2656
            private final String genericSignature;
2657

2658
            /**
2659
             * The resolution of this type's generic type.
2660
             */
2661
            private final GenericTypeToken.Resolution.ForType signatureResolution;
2662

2663
            /**
2664
             * The descriptor of this type's interfaces.
2665
             */
2666
            private final List<String> interfaceTypeDescriptors;
2667

2668
            /**
2669
             * A definition of this type's containment within another type or method.
2670
             */
2671
            private final TypeContainment typeContainment;
2672

2673
            /**
2674
             * The binary name of this type's declaring type or {@code null} if no such type exists.
2675
             */
2676
            @MaybeNull
2677
            private final String declaringTypeName;
2678

2679
            /**
2680
             * A list of descriptors representing the types that are declared by this type.
2681
             */
2682
            private final List<String> declaredTypes;
2683

2684
            /**
2685
             * {@code true} if this type is an anonymous type.
2686
             */
2687
            private final boolean anonymousType;
2688

2689
            /**
2690
             * The binary name of the nest host or {@code null} if no nest host was specified.
2691
             */
2692
            @MaybeNull
2693
            private final String nestHost;
2694

2695
            /**
2696
             * A list of binary names of all specified nest members.
2697
             */
2698
            private final List<String> nestMembers;
2699

2700
            /**
2701
             * A mapping of the super class's annotation tokens.
2702
             */
2703
            private final Map<String, List<AnnotationToken>> superClassAnnotationTokens;
2704

2705
            /**
2706
             * A mapping of type annotations for this type's interface types by their indices.
2707
             */
2708
            private final Map<Integer, Map<String, List<AnnotationToken>>> interfaceAnnotationTokens;
2709

2710
            /**
2711
             * A mapping of type annotations of the type variables' type annotations by their indices.
2712
             */
2713
            private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
2714

2715
            /**
2716
             * A mapping of type annotations of the type variables' bounds' type annotations by their indices and each variable's index.
2717
             */
2718
            private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundsAnnotationTokens;
2719

2720
            /**
2721
             * A list of tokens that represent the annotations of this type.
2722
             */
2723
            private final List<AnnotationToken> annotationTokens;
2724

2725
            /**
2726
             * A list of field tokens describing the field's of this type.
2727
             */
2728
            private final List<FieldToken> fieldTokens;
2729

2730
            /**
2731
             * A list of method tokens describing the method's of this type.
2732
             */
2733
            private final List<MethodToken> methodTokens;
2734

2735
            /**
2736
             * A list of record component tokens describing the record components of this type.
2737
             */
2738
            private final List<RecordComponentToken> recordComponentTokens;
2739

2740
            /**
2741
             * A list of internal names of permitted subclasses.
2742
             */
2743
            private final List<String> permittedSubclasses;
2744

2745
            /**
2746
             * The type's class file version.
2747
             */
2748
            private final ClassFileVersion classFileVersion;
2749

2750
            /**
2751
             * Creates a new lazy type description.
2752
             *
2753
             * @param typePool                           The type pool to be used for looking up linked types.
2754
             * @param actualModifiers                    The actual modifiers of this type.
2755
             * @param modifiers                          The modifiers of this type.
2756
             * @param name                               The binary name of this type.
2757
             * @param superClassInternalName             The internal name of this type's super type or {@code null} if no such super type is defined.
2758
             * @param interfaceInternalName              An array of this type's interfaces or {@code null} if this type does not define any interfaces.
2759
             * @param genericSignature                   The type's generic signature as found in the class file or {@code null} if the type is not generic.
2760
             * @param typeContainment                    A definition of this type's containment within another type or method.
2761
             * @param declaringTypeInternalName          The internal name of this type's declaring type or {@code null} if no such type exists.
2762
             * @param declaredTypes                      A list of descriptors representing the types that are declared by this type.
2763
             * @param anonymousType                      {@code true} if this type is an anonymous type.
2764
             * @param nestHostInternalName               The internal name of the nest host or {@code null} if no nest host was specified.
2765
             * @param nestMemberInternalNames            A list of internal names of the nest members.
2766
             * @param superClassAnnotationTokens         A mapping of the super class's annotation tokens.
2767
             * @param interfaceAnnotationTokens          A mapping of type annotations for this type's interface types by their indices.
2768
             * @param typeVariableAnnotationTokens       A mapping of type annotations of the type variables' type annotations by their indices.
2769
             * @param typeVariableBoundsAnnotationTokens A mapping of type annotations of the type variables' bounds' type annotations by their indices
2770
             *                                           and each variable's index.
2771
             * @param annotationTokens                   A list of tokens that represent the annotations of this type.
2772
             * @param fieldTokens                        A list of field tokens describing the field's of this type.
2773
             * @param methodTokens                       A list of method tokens describing the method's of this type.
2774
             * @param recordComponentTokens              A list of record component tokens describing the record components of this type.
2775
             * @param permittedSubclasses                A list of internal names of permitted subclasses.
2776
             * @param classFileVersion                   The type's class file version.
2777
             */
2778
            protected LazyTypeDescription(TypePool typePool,
2779
                                          int actualModifiers,
2780
                                          int modifiers,
2781
                                          String name,
2782
                                          @MaybeNull String superClassInternalName,
2783
                                          @MaybeNull String[] interfaceInternalName,
2784
                                          @MaybeNull String genericSignature,
2785
                                          TypeContainment typeContainment,
2786
                                          @MaybeNull String declaringTypeInternalName,
2787
                                          List<String> declaredTypes,
2788
                                          boolean anonymousType,
2789
                                          @MaybeNull String nestHostInternalName,
2790
                                          List<String> nestMemberInternalNames,
2791
                                          Map<String, List<AnnotationToken>> superClassAnnotationTokens,
2792
                                          Map<Integer, Map<String, List<AnnotationToken>>> interfaceAnnotationTokens,
2793
                                          Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
2794
                                          Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundsAnnotationTokens,
2795
                                          List<AnnotationToken> annotationTokens,
2796
                                          List<FieldToken> fieldTokens,
2797
                                          List<MethodToken> methodTokens,
2798
                                          List<RecordComponentToken> recordComponentTokens,
2799
                                          List<String> permittedSubclasses,
2800
                                          ClassFileVersion classFileVersion) {
1✔
2801
                this.typePool = typePool;
1✔
2802
                this.actualModifiers = actualModifiers & ~Opcodes.ACC_SUPER;
1✔
2803
                this.modifiers = modifiers & ~(Opcodes.ACC_SUPER | Opcodes.ACC_DEPRECATED);
1✔
2804
                this.name = Type.getObjectType(name).getClassName();
1✔
2805
                this.superClassDescriptor = superClassInternalName == null
1✔
2806
                        ? NO_TYPE
2807
                        : Type.getObjectType(superClassInternalName).getDescriptor();
1✔
2808
                this.genericSignature = genericSignature;
1✔
2809
                signatureResolution = RAW_TYPES
1✔
2810
                        ? GenericTypeToken.Resolution.Raw.INSTANCE
2811
                        : GenericTypeExtractor.ForSignature.OfType.extract(genericSignature);
1✔
2812
                if (interfaceInternalName == null) {
1✔
2813
                    interfaceTypeDescriptors = Collections.emptyList();
×
2814
                } else {
2815
                    interfaceTypeDescriptors = new ArrayList<String>(interfaceInternalName.length);
1✔
2816
                    for (String internalName : interfaceInternalName) {
1✔
2817
                        interfaceTypeDescriptors.add(Type.getObjectType(internalName).getDescriptor());
1✔
2818
                    }
2819
                }
2820
                this.typeContainment = typeContainment;
1✔
2821
                declaringTypeName = declaringTypeInternalName == null
1✔
2822
                        ? NO_TYPE
2823
                        : declaringTypeInternalName.replace('/', '.');
1✔
2824
                this.declaredTypes = declaredTypes;
1✔
2825
                this.anonymousType = anonymousType;
1✔
2826
                nestHost = nestHostInternalName == null
1✔
2827
                        ? NO_TYPE
2828
                        : Type.getObjectType(nestHostInternalName).getClassName();
1✔
2829
                nestMembers = new ArrayList<String>(nestMemberInternalNames.size());
1✔
2830
                for (String nestMemberInternalName : nestMemberInternalNames) {
1✔
2831
                    nestMembers.add(Type.getObjectType(nestMemberInternalName).getClassName());
×
2832
                }
×
2833
                this.superClassAnnotationTokens = superClassAnnotationTokens;
1✔
2834
                this.interfaceAnnotationTokens = interfaceAnnotationTokens;
1✔
2835
                this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
1✔
2836
                this.typeVariableBoundsAnnotationTokens = typeVariableBoundsAnnotationTokens;
1✔
2837
                this.annotationTokens = annotationTokens;
1✔
2838
                this.fieldTokens = fieldTokens;
1✔
2839
                this.methodTokens = methodTokens;
1✔
2840
                this.recordComponentTokens = recordComponentTokens;
1✔
2841
                this.permittedSubclasses = new ArrayList<String>(permittedSubclasses.size());
1✔
2842
                for (String internalName : permittedSubclasses) {
1✔
2843
                    this.permittedSubclasses.add(Type.getObjectType(internalName).getDescriptor());
×
2844
                }
×
2845
                this.classFileVersion = classFileVersion;
1✔
2846
            }
1✔
2847

2848
            /**
2849
             * {@inheritDoc}
2850
             */
2851
            @MaybeNull
2852
            public Generic getSuperClass() {
2853
                return superClassDescriptor == null || isInterface()
1✔
2854
                        ? Generic.UNDEFINED
2855
                        : signatureResolution.resolveSuperClass(superClassDescriptor, typePool, superClassAnnotationTokens, this);
1✔
2856
            }
2857

2858
            /**
2859
             * {@inheritDoc}
2860
             */
2861
            public TypeList.Generic getInterfaces() {
2862
                return signatureResolution.resolveInterfaceTypes(interfaceTypeDescriptors, typePool, interfaceAnnotationTokens, this);
1✔
2863
            }
2864

2865
            /**
2866
             * {@inheritDoc}
2867
             */
2868
            @MaybeNull
2869
            public MethodDescription.InDefinedShape getEnclosingMethod() {
2870
                return typeContainment.getEnclosingMethod(typePool);
1✔
2871
            }
2872

2873
            /**
2874
             * {@inheritDoc}
2875
             */
2876
            @MaybeNull
2877
            public TypeDescription getEnclosingType() {
2878
                return typeContainment.getEnclosingType(typePool);
1✔
2879
            }
2880

2881
            /**
2882
             * {@inheritDoc}
2883
             */
2884
            public TypeList getDeclaredTypes() {
2885
                return new LazyTypeList(typePool, declaredTypes);
1✔
2886
            }
2887

2888
            /**
2889
             * {@inheritDoc}
2890
             */
2891
            public boolean isAnonymousType() {
2892
                return anonymousType;
1✔
2893
            }
2894

2895
            /**
2896
             * {@inheritDoc}
2897
             */
2898
            public boolean isLocalType() {
2899
                return !anonymousType && typeContainment.isLocalType();
1✔
2900
            }
2901

2902
            /**
2903
             * {@inheritDoc}
2904
             */
2905
            public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
2906
                return new FieldTokenList();
1✔
2907
            }
2908

2909
            /**
2910
             * {@inheritDoc}
2911
             */
2912
            public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
2913
                return new MethodTokenList();
1✔
2914
            }
2915

2916
            /**
2917
             * {@inheritDoc}
2918
             */
2919
            @MaybeNull
2920
            public PackageDescription getPackage() {
2921
                String name = getName();
1✔
2922
                int index = name.lastIndexOf('.');
1✔
2923
                return new LazyPackageDescription(typePool, index == -1
1✔
2924
                        ? EMPTY_NAME
2925
                        : name.substring(0, index));
1✔
2926
            }
2927

2928
            /**
2929
             * {@inheritDoc}
2930
             */
2931
            public String getName() {
2932
                return name;
1✔
2933
            }
2934

2935
            /**
2936
             * {@inheritDoc}
2937
             */
2938
            @MaybeNull
2939
            public TypeDescription getDeclaringType() {
2940
                return declaringTypeName == null
1✔
2941
                        ? TypeDescription.UNDEFINED
2942
                        : typePool.describe(declaringTypeName).resolve();
1✔
2943
            }
2944

2945
            /**
2946
             * {@inheritDoc}
2947
             */
2948
            public int getModifiers() {
2949
                return modifiers;
1✔
2950
            }
2951

2952
            /**
2953
             * {@inheritDoc}
2954
             */
2955
            public int getActualModifiers(boolean superFlag) {
2956
                return superFlag ? (actualModifiers | Opcodes.ACC_SUPER) : actualModifiers;
1✔
2957
            }
2958

2959
            /**
2960
             * {@inheritDoc}
2961
             */
2962
            public TypeDescription getNestHost() {
2963
                return nestHost == null
1✔
2964
                        ? this
2965
                        : typePool.describe(nestHost).resolve();
×
2966
            }
2967

2968
            /**
2969
             * {@inheritDoc}
2970
             */
2971
            public TypeList getNestMembers() {
2972
                return nestHost == null
1✔
2973
                        ? new LazyNestMemberList(this, typePool, nestMembers)
2974
                        : typePool.describe(nestHost).resolve().getNestMembers();
×
2975
            }
2976

2977
            /**
2978
             * {@inheritDoc}
2979
             */
2980
            public AnnotationList getDeclaredAnnotations() {
2981
                return LazyAnnotationDescription.asList(typePool, annotationTokens);
1✔
2982
            }
2983

2984
            /**
2985
             * {@inheritDoc}
2986
             */
2987
            public TypeList.Generic getTypeVariables() {
2988
                return signatureResolution.resolveTypeVariables(typePool, this, typeVariableAnnotationTokens, typeVariableBoundsAnnotationTokens);
1✔
2989
            }
2990

2991
            @Override
2992
            @MaybeNull
2993
            public String getGenericSignature() {
2994
                return genericSignature;
1✔
2995
            }
2996

2997
            /**
2998
             * {@inheritDoc}
2999
             */
3000
            public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
3001
                return new RecordComponentTokenList();
1✔
3002
            }
3003

3004
            /**
3005
             * {@inheritDoc}
3006
             */
3007
            public boolean isRecord() {
3008
                return (actualModifiers & Opcodes.ACC_RECORD) != 0 && JavaType.RECORD.getTypeStub().getDescriptor().equals(superClassDescriptor);
1✔
3009
            }
3010

3011
            @Override
3012
            public boolean isSealed() {
3013
                return !permittedSubclasses.isEmpty();
1✔
3014
            }
3015

3016
            /**
3017
             * {@inheritDoc}
3018
             */
3019
            public TypeList getPermittedSubtypes() {
3020
                return new LazyTypeList(typePool, permittedSubclasses);
1✔
3021
            }
3022

3023
            @Override
3024
            public ClassFileVersion getClassFileVersion() {
3025
                return classFileVersion;
×
3026
            }
3027

3028
            /**
3029
             * A list of field tokens representing each entry as a field description.
3030
             */
3031
            protected class FieldTokenList extends FieldList.AbstractBase<FieldDescription.InDefinedShape> {
1✔
3032

3033
                /**
3034
                 * {@inheritDoc}
3035
                 */
3036
                public FieldDescription.InDefinedShape get(int index) {
3037
                    return fieldTokens.get(index).toFieldDescription(LazyTypeDescription.this);
1✔
3038
                }
3039

3040
                /**
3041
                 * {@inheritDoc}
3042
                 */
3043
                public int size() {
3044
                    return fieldTokens.size();
1✔
3045
                }
3046
            }
3047

3048
            /**
3049
             * A list of method tokens representing each entry as a method description.
3050
             */
3051
            protected class MethodTokenList extends MethodList.AbstractBase<MethodDescription.InDefinedShape> {
1✔
3052

3053
                /**
3054
                 * {@inheritDoc}
3055
                 */
3056
                public MethodDescription.InDefinedShape get(int index) {
3057
                    return methodTokens.get(index).toMethodDescription(LazyTypeDescription.this);
1✔
3058
                }
3059

3060
                /**
3061
                 * {@inheritDoc}
3062
                 */
3063
                public int size() {
3064
                    return methodTokens.size();
1✔
3065
                }
3066
            }
3067

3068
            /**
3069
             * A list of record component tokens representing each record component as a description.
3070
             */
3071
            protected class RecordComponentTokenList extends RecordComponentList.AbstractBase<RecordComponentDescription.InDefinedShape> {
1✔
3072

3073
                /**
3074
                 * {@inheritDoc}
3075
                 */
3076
                public RecordComponentDescription.InDefinedShape get(int index) {
3077
                    return recordComponentTokens.get(index).toRecordComponentDescription(LazyTypeDescription.this);
×
3078
                }
3079

3080
                /**
3081
                 * {@inheritDoc}
3082
                 */
3083
                public int size() {
3084
                    return recordComponentTokens.size();
1✔
3085
                }
3086
            }
3087

3088
            /**
3089
             * A declaration context encapsulates information about whether a type was declared within another type
3090
             * or within a method of another type.
3091
             */
3092
            protected interface TypeContainment {
3093

3094
                /**
3095
                 * Returns the enclosing method or {@code null} if no such method exists.
3096
                 *
3097
                 * @param typePool The type pool to be used for looking up linked types.
3098
                 * @return A method description describing the linked type or {@code null}.
3099
                 */
3100
                @MaybeNull
3101
                MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool);
3102

3103
                /**
3104
                 * Returns the enclosing type or {@code null} if no such type exists.
3105
                 *
3106
                 * @param typePool The type pool to be used for looking up linked types.
3107
                 * @return A type description describing the linked type or {@code null}.
3108
                 */
3109
                @MaybeNull
3110
                TypeDescription getEnclosingType(TypePool typePool);
3111

3112
                /**
3113
                 * Returns {@code true} if the type is self-contained.
3114
                 *
3115
                 * @return {@code true} if the type is self-contained.
3116
                 */
3117
                boolean isSelfContained();
3118

3119
                /**
3120
                 * Returns {@code true} if the type is a local type unless it is an anonymous type.
3121
                 *
3122
                 * @return {@code true} if the type is a local type unless it is an anonymous type
3123
                 */
3124
                boolean isLocalType();
3125

3126
                /**
3127
                 * Describes a type that is not contained within another type, a method or a constructor.
3128
                 */
3129
                enum SelfContained implements TypeContainment {
1✔
3130

3131
                    /**
3132
                     * The singleton instance.
3133
                     */
3134
                    INSTANCE;
1✔
3135

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

3144
                    /**
3145
                     * {@inheritDoc}
3146
                     */
3147
                    @MaybeNull
3148
                    public TypeDescription getEnclosingType(TypePool typePool) {
3149
                        return TypeDescription.UNDEFINED;
1✔
3150
                    }
3151

3152
                    /**
3153
                     * {@inheritDoc}
3154
                     */
3155
                    public boolean isSelfContained() {
3156
                        return true;
1✔
3157
                    }
3158

3159
                    /**
3160
                     * {@inheritDoc}
3161
                     */
3162
                    public boolean isLocalType() {
3163
                        return false;
1✔
3164
                    }
3165
                }
3166

3167
                /**
3168
                 * Describes a type that is contained within another type.
3169
                 */
3170
                @HashCodeAndEqualsPlugin.Enhance
3171
                class WithinType implements TypeContainment {
3172

3173
                    /**
3174
                     * The type's binary name.
3175
                     */
3176
                    private final String name;
3177

3178
                    /**
3179
                     * {@code true} if the type is a local type unless it is an anonymous type.
3180
                     */
3181
                    private final boolean localType;
3182

3183
                    /**
3184
                     * Creates a new type containment for a type that is declared within another type.
3185
                     *
3186
                     * @param internalName The type's internal name.
3187
                     * @param localType    {@code true} if the type is a local type unless it is an anonymous type.
3188
                     */
3189
                    protected WithinType(String internalName, boolean localType) {
1✔
3190
                        name = internalName.replace('/', '.');
1✔
3191
                        this.localType = localType;
1✔
3192
                    }
1✔
3193

3194
                    /**
3195
                     * {@inheritDoc}
3196
                     */
3197
                    @MaybeNull
3198
                    public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
3199
                        return MethodDescription.UNDEFINED;
1✔
3200
                    }
3201

3202
                    /**
3203
                     * {@inheritDoc}
3204
                     */
3205
                    public TypeDescription getEnclosingType(TypePool typePool) {
3206
                        return typePool.describe(name).resolve();
1✔
3207
                    }
3208

3209
                    /**
3210
                     * {@inheritDoc}
3211
                     */
3212
                    public boolean isSelfContained() {
3213
                        return false;
1✔
3214
                    }
3215

3216
                    /**
3217
                     * {@inheritDoc}
3218
                     */
3219
                    public boolean isLocalType() {
3220
                        return localType;
1✔
3221
                    }
3222
                }
3223

3224
                /**
3225
                 * Describes a type that is contained within a method or constructor.
3226
                 */
3227
                @HashCodeAndEqualsPlugin.Enhance
3228
                class WithinMethod implements TypeContainment {
3229

3230
                    /**
3231
                     * The method's declaring type's internal name.
3232
                     */
3233
                    private final String name;
3234

3235
                    /**
3236
                     * The method's internal name.
3237
                     */
3238
                    private final String methodName;
3239

3240
                    /**
3241
                     * The method's descriptor.
3242
                     */
3243
                    private final String methodDescriptor;
3244

3245
                    /**
3246
                     * Creates a new type containment for a type that is declared within a method.
3247
                     *
3248
                     * @param internalName     The method's declaring type's internal name.
3249
                     * @param methodName       The method's internal name.
3250
                     * @param methodDescriptor The method's descriptor.
3251
                     */
3252
                    protected WithinMethod(String internalName, String methodName, String methodDescriptor) {
1✔
3253
                        name = internalName.replace('/', '.');
1✔
3254
                        this.methodName = methodName;
1✔
3255
                        this.methodDescriptor = methodDescriptor;
1✔
3256
                    }
1✔
3257

3258
                    /**
3259
                     * {@inheritDoc}
3260
                     */
3261
                    public MethodDescription.InDefinedShape getEnclosingMethod(TypePool typePool) {
3262
                        TypeDescription enclosingType = getEnclosingType(typePool);
1✔
3263
                        if (enclosingType == null) {
1✔
3264
                            throw new IllegalStateException("Could not resolve enclosing type " + name);
×
3265
                        }
3266
                        MethodList<MethodDescription.InDefinedShape> enclosingMethod = enclosingType.getDeclaredMethods()
1✔
3267
                                .filter(hasMethodName(methodName).and(hasDescriptor(methodDescriptor)));
1✔
3268
                        if (enclosingMethod.isEmpty()) {
1✔
3269
                            throw new IllegalStateException(methodName + methodDescriptor + " not declared by " + enclosingType);
×
3270
                        }
3271
                        return enclosingMethod.getOnly();
1✔
3272
                    }
3273

3274
                    /**
3275
                     * {@inheritDoc}
3276
                     */
3277
                    public TypeDescription getEnclosingType(TypePool typePool) {
3278
                        return typePool.describe(name).resolve();
1✔
3279
                    }
3280

3281
                    /**
3282
                     * {@inheritDoc}
3283
                     */
3284
                    public boolean isSelfContained() {
3285
                        return false;
1✔
3286
                    }
3287

3288
                    /**
3289
                     * {@inheritDoc}
3290
                     */
3291
                    public boolean isLocalType() {
3292
                        return true;
1✔
3293
                    }
3294
                }
3295
            }
3296

3297
            /**
3298
             * A token that represents a generic Java type.
3299
             */
3300
            protected interface GenericTypeToken {
3301

3302
                /**
3303
                 * Represents an empty type path.
3304
                 */
3305
                String EMPTY_TYPE_PATH = "";
3306

3307
                /**
3308
                 * Represents a step to a component type within a type path.
3309
                 */
3310
                char COMPONENT_TYPE_PATH = '[';
3311

3312
                /**
3313
                 * Represents a wildcard type step within a type path.
3314
                 */
3315
                char WILDCARD_TYPE_PATH = '*';
3316

3317
                /**
3318
                 * Represents a (reversed) step to an inner class within a type path.
3319
                 */
3320
                char INNER_CLASS_PATH = '.';
3321

3322
                /**
3323
                 * Represents an index type delimiter within a type path.
3324
                 */
3325
                char INDEXED_TYPE_DELIMITER = ';';
3326

3327
                /**
3328
                 * Transforms this token into a generic type representation.
3329
                 *
3330
                 * @param typePool           The type pool to be used for locating non-generic type descriptions.
3331
                 * @param typeVariableSource The type variable source.
3332
                 * @param typePath           The type path of the resolved generic type.
3333
                 * @param annotationTokens   A mapping of the type's annotation tokens by their type path.
3334
                 * @return A description of the represented generic type.
3335
                 */
3336
                Generic toGenericType(TypePool typePool,
3337
                                      TypeVariableSource typeVariableSource,
3338
                                      String typePath,
3339
                                      Map<String, List<AnnotationToken>> annotationTokens);
3340

3341
                /**
3342
                 * Determines if a generic type tokens represents a primary bound of a type variable. This method must only be invoked on types
3343
                 * that represent a {@link Sort#NON_GENERIC},
3344
                 * {@link Sort#PARAMETERIZED} or {@link Sort#VARIABLE}.
3345
                 *
3346
                 * @param typePool The type pool to use.
3347
                 * @return {@code true} if this token represents a primary bound.
3348
                 */
3349
                boolean isPrimaryBound(TypePool typePool);
3350

3351
                /**
3352
                 * Returns the type path prefix that needs to be appended to the existing type path before any further navigation on the parameterized
3353
                 * type. This method must only be called on type tokens that represent parameterized type
3354
                 *
3355
                 * @return A type path segment that needs to be appended to the base type path before any further navigation on the parameterized type.
3356
                 */
3357
                String getTypePathPrefix();
3358

3359
                /**
3360
                 * Represents a generic type token for a formal type variable.
3361
                 */
3362
                interface OfFormalTypeVariable {
3363

3364
                    /**
3365
                     * Transforms this token into a generic type representation.
3366
                     *
3367
                     * @param typePool                 The type pool to be used for locating non-generic type descriptions.
3368
                     * @param typeVariableSource       The type variable source.
3369
                     * @param annotationTokens         A mapping of the type variables' type annotations.
3370
                     * @param boundaryAnnotationTokens A mapping of the type variables' bounds' type annotation by their bound index.
3371
                     * @return A generic type representation of this formal type variable.
3372
                     */
3373
                    Generic toGenericType(TypePool typePool,
3374
                                          TypeVariableSource typeVariableSource,
3375
                                          Map<String, List<AnnotationToken>> annotationTokens,
3376
                                          Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens);
3377
                }
3378

3379
                /**
3380
                 * A generic type token that represents a primitive type.
3381
                 */
3382
                enum ForPrimitiveType implements GenericTypeToken {
1✔
3383

3384
                    /**
3385
                     * The generic type token describing the {@code boolean} type.
3386
                     */
3387
                    BOOLEAN(boolean.class),
1✔
3388

3389
                    /**
3390
                     * The generic type token describing the {@code byte} type.
3391
                     */
3392
                    BYTE(byte.class),
1✔
3393

3394
                    /**
3395
                     * The generic type token describing the {@code short} type.
3396
                     */
3397
                    SHORT(short.class),
1✔
3398

3399
                    /**
3400
                     * The generic type token describing the {@code char} type.
3401
                     */
3402
                    CHAR(char.class),
1✔
3403

3404
                    /**
3405
                     * The generic type token describing the {@code int} type.
3406
                     */
3407
                    INTEGER(int.class),
1✔
3408

3409
                    /**
3410
                     * The generic type token describing the {@code long} type.
3411
                     */
3412
                    LONG(long.class),
1✔
3413

3414
                    /**
3415
                     * The generic type token describing the {@code float} type.
3416
                     */
3417
                    FLOAT(float.class),
1✔
3418

3419
                    /**
3420
                     * The generic type token describing the {@code double} type.
3421
                     */
3422
                    DOUBLE(double.class),
1✔
3423

3424
                    /**
3425
                     * The generic type token describing the {@code void} type.
3426
                     */
3427
                    VOID(void.class);
1✔
3428

3429
                    /**
3430
                     * A description of this primitive type token.
3431
                     */
3432
                    private final TypeDescription typeDescription;
3433

3434
                    /**
3435
                     * Creates a new primitive type token.
3436
                     *
3437
                     * @param type The loaded type representing this primitive.
3438
                     */
3439
                    ForPrimitiveType(Class<?> type) {
1✔
3440
                        typeDescription = ForLoadedType.of(type);
1✔
3441
                    }
1✔
3442

3443
                    /**
3444
                     * Resolves a generic type token of a primitive type.
3445
                     *
3446
                     * @param descriptor The descriptor of the primitive type.
3447
                     * @return The corresponding generic type token.
3448
                     */
3449
                    public static GenericTypeToken of(char descriptor) {
3450
                        switch (descriptor) {
1✔
3451
                            case 'V':
3452
                                return VOID;
1✔
3453
                            case 'Z':
3454
                                return BOOLEAN;
1✔
3455
                            case 'B':
3456
                                return BYTE;
1✔
3457
                            case 'S':
3458
                                return SHORT;
1✔
3459
                            case 'C':
3460
                                return CHAR;
1✔
3461
                            case 'I':
3462
                                return INTEGER;
1✔
3463
                            case 'J':
3464
                                return LONG;
1✔
3465
                            case 'F':
3466
                                return FLOAT;
1✔
3467
                            case 'D':
3468
                                return DOUBLE;
1✔
3469
                            default:
3470
                                throw new IllegalArgumentException("Not a valid primitive type descriptor: " + descriptor);
×
3471
                        }
3472
                    }
3473

3474
                    /**
3475
                     * {@inheritDoc}
3476
                     */
3477
                    public Generic toGenericType(TypePool typePool,
3478
                                                 TypeVariableSource typeVariableSource,
3479
                                                 String typePath,
3480
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
3481
                        return new LazyPrimitiveType(typePool,
1✔
3482
                                typePath,
3483
                                annotationTokens,
3484
                                typeDescription);
3485
                    }
3486

3487
                    /**
3488
                     * {@inheritDoc}
3489
                     */
3490
                    public boolean isPrimaryBound(TypePool typePool) {
3491
                        throw new IllegalStateException("A primitive type cannot be a type variable bound: " + this);
1✔
3492
                    }
3493

3494
                    /**
3495
                     * {@inheritDoc}
3496
                     */
3497
                    public String getTypePathPrefix() {
3498
                        throw new IllegalStateException("A primitive type cannot be the owner of a nested type: " + this);
1✔
3499
                    }
3500

3501
                    /**
3502
                     * A representation of a lazy primitive type.
3503
                     */
3504
                    protected static class LazyPrimitiveType extends Generic.OfNonGenericType {
3505

3506
                        /**
3507
                         * The type pool to use.
3508
                         */
3509
                        private final TypePool typePool;
3510

3511
                        /**
3512
                         * This type's type path.
3513
                         */
3514
                        private final String typePath;
3515

3516
                        /**
3517
                         * This type's type annotation tokens.
3518
                         */
3519
                        private final Map<String, List<AnnotationToken>> annotationTokens;
3520

3521
                        /**
3522
                         * The represented type's description.
3523
                         */
3524
                        private final TypeDescription typeDescription;
3525

3526
                        /**
3527
                         * Creates a new lazy primitive type.
3528
                         *
3529
                         * @param typePool         The type pool to use.
3530
                         * @param typePath         This type's type path.
3531
                         * @param annotationTokens This type's type annotation tokens.
3532
                         * @param typeDescription  The represented type's description.
3533
                         */
3534
                        protected LazyPrimitiveType(TypePool typePool,
3535
                                                    String typePath,
3536
                                                    Map<String, List<AnnotationToken>> annotationTokens,
3537
                                                    TypeDescription typeDescription) {
1✔
3538
                            this.typePool = typePool;
1✔
3539
                            this.typePath = typePath;
1✔
3540
                            this.annotationTokens = annotationTokens;
1✔
3541
                            this.typeDescription = typeDescription;
1✔
3542
                        }
1✔
3543

3544
                        /**
3545
                         * {@inheritDoc}
3546
                         */
3547
                        public TypeDescription asErasure() {
3548
                            return typeDescription;
×
3549
                        }
3550

3551
                        /**
3552
                         * {@inheritDoc}
3553
                         */
3554
                        @MaybeNull
3555
                        public Generic getOwnerType() {
3556
                            return Generic.UNDEFINED;
×
3557
                        }
3558

3559
                        /**
3560
                         * {@inheritDoc}
3561
                         */
3562
                        @MaybeNull
3563
                        public Generic getComponentType() {
3564
                            return Generic.UNDEFINED;
×
3565
                        }
3566

3567
                        /**
3568
                         * {@inheritDoc}
3569
                         */
3570
                        public AnnotationList getDeclaredAnnotations() {
3571
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
3572
                        }
3573
                    }
3574
                }
3575

3576
                /**
3577
                 * A generic type token that represents an unbound wildcard.
3578
                 */
3579
                enum ForUnboundWildcard implements GenericTypeToken {
1✔
3580

3581
                    /**
3582
                     * The singleton instance.
3583
                     */
3584
                    INSTANCE;
1✔
3585

3586
                    /**
3587
                     * {@inheritDoc}
3588
                     */
3589
                    public Generic toGenericType(TypePool typePool,
3590
                                                 TypeVariableSource typeVariableSource,
3591
                                                 String typePath,
3592
                                                 @MaybeNull Map<String, List<AnnotationToken>> annotationTokens) {
3593
                        return new LazyUnboundWildcard(typePool,
1✔
3594
                                typePath,
3595
                                annotationTokens == null
3596
                                        ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
3597
                                        : annotationTokens);
3598
                    }
3599

3600
                    /**
3601
                     * {@inheritDoc}
3602
                     */
3603
                    public boolean isPrimaryBound(TypePool typePool) {
3604
                        throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
1✔
3605
                    }
3606

3607
                    /**
3608
                     * {@inheritDoc}
3609
                     */
3610
                    public String getTypePathPrefix() {
3611
                        throw new IllegalStateException("An unbound wildcard cannot be the owner of a nested type: " + this);
1✔
3612
                    }
3613

3614
                    /**
3615
                     * A generic type representation of a generic unbound wildcard.
3616
                     */
3617
                    protected static class LazyUnboundWildcard extends Generic.OfWildcardType {
3618

3619
                        /**
3620
                         * The type pool to use.
3621
                         */
3622
                        private final TypePool typePool;
3623

3624
                        /**
3625
                         * This type's type path.
3626
                         */
3627
                        private final String typePath;
3628

3629
                        /**
3630
                         * The type's type annotations.
3631
                         */
3632
                        private final Map<String, List<AnnotationToken>> annotationTokens;
3633

3634
                        /**
3635
                         * Creates a new lazy unbound wildcard.
3636
                         *
3637
                         * @param typePool         The type pool to use.
3638
                         * @param typePath         This type's type path.
3639
                         * @param annotationTokens The type's type annotations.
3640
                         */
3641
                        protected LazyUnboundWildcard(TypePool typePool, String typePath, Map<String, List<AnnotationToken>> annotationTokens) {
1✔
3642
                            this.typePool = typePool;
1✔
3643
                            this.typePath = typePath;
1✔
3644
                            this.annotationTokens = annotationTokens;
1✔
3645
                        }
1✔
3646

3647
                        /**
3648
                         * {@inheritDoc}
3649
                         */
3650
                        public TypeList.Generic getUpperBounds() {
3651
                            return new TypeList.Generic.Explicit(Generic.OfNonGenericType.ForLoadedType.of(Object.class));
1✔
3652
                        }
3653

3654
                        /**
3655
                         * {@inheritDoc}
3656
                         */
3657
                        public TypeList.Generic getLowerBounds() {
3658
                            return new TypeList.Generic.Empty();
1✔
3659
                        }
3660

3661
                        /**
3662
                         * {@inheritDoc}
3663
                         */
3664
                        public AnnotationList getDeclaredAnnotations() {
3665
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
3666
                        }
3667
                    }
3668
                }
3669

3670
                /**
3671
                 * A resolution of a type's, method's or field's generic types.
3672
                 */
3673
                interface Resolution {
3674

3675
                    /**
3676
                     * Resolves the type variables of the represented element.
3677
                     *
3678
                     * @param typePool              The type pool to be used for locating non-generic type descriptions.
3679
                     * @param typeVariableSource    The type variable source to use for resolving type variables.
3680
                     * @param annotationTokens      A mapping of the type variables' type annotation tokens by their indices.
3681
                     * @param boundAnnotationTokens A mapping of the type variables' bounds' type annotation tokens by their indices
3682
                     *                              and each type variable's index.
3683
                     * @return A list describing the resolved generic types.
3684
                     */
3685
                    TypeList.Generic resolveTypeVariables(TypePool typePool,
3686
                                                          TypeVariableSource typeVariableSource,
3687
                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3688
                                                          Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens);
3689

3690
                    /**
3691
                     * A resolution of a type's, method's or field's generic types if all of the represented element's are raw.
3692
                     */
3693
                    enum Raw implements ForType, ForField, ForMethod, ForRecordComponent {
1✔
3694

3695
                        /**
3696
                         * The singleton instance.
3697
                         */
3698
                        INSTANCE;
1✔
3699

3700
                        /**
3701
                         * {@inheritDoc}
3702
                         */
3703
                        public Generic resolveSuperClass(String superClassDescriptor,
3704
                                                         TypePool typePool,
3705
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3706
                                                         TypeDescription definingType) {
3707
                            return RawAnnotatedType.of(typePool, annotationTokens, superClassDescriptor);
1✔
3708
                        }
3709

3710
                        /**
3711
                         * {@inheritDoc}
3712
                         */
3713
                        public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
3714
                                                                      TypePool typePool,
3715
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3716
                                                                      TypeDescription definingType) {
3717
                            return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, interfaceTypeDescriptors);
1✔
3718
                        }
3719

3720
                        /**
3721
                         * {@inheritDoc}
3722
                         */
3723
                        public TypeList.Generic resolveTypeVariables(TypePool typePool,
3724
                                                                     TypeVariableSource typeVariableSource,
3725
                                                                     Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3726
                                                                     Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
3727
                            return new TypeList.Generic.Empty();
1✔
3728
                        }
3729

3730
                        /**
3731
                         * {@inheritDoc}
3732
                         */
3733
                        public Generic resolveFieldType(String fieldTypeDescriptor,
3734
                                                        TypePool typePool,
3735
                                                        Map<String, List<AnnotationToken>> annotationTokens,
3736
                                                        FieldDescription.InDefinedShape definingField) {
3737
                            return RawAnnotatedType.of(typePool, annotationTokens, fieldTypeDescriptor);
1✔
3738
                        }
3739

3740
                        /**
3741
                         * {@inheritDoc}
3742
                         */
3743
                        public Generic resolveReturnType(String returnTypeDescriptor,
3744
                                                         TypePool typePool,
3745
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3746
                                                         MethodDescription.InDefinedShape definingMethod) {
3747
                            return RawAnnotatedType.of(typePool, annotationTokens, returnTypeDescriptor);
1✔
3748
                        }
3749

3750
                        /**
3751
                         * {@inheritDoc}
3752
                         */
3753
                        public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
3754
                                                                      TypePool typePool,
3755
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3756
                                                                      MethodDescription.InDefinedShape definingMethod) {
3757
                            return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, parameterTypeDescriptors);
1✔
3758
                        }
3759

3760
                        /**
3761
                         * {@inheritDoc}
3762
                         */
3763
                        public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
3764
                                                                      TypePool typePool,
3765
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3766
                                                                      MethodDescription.InDefinedShape definingMethod) {
3767
                            return RawAnnotatedType.LazyRawAnnotatedTypeList.of(typePool, annotationTokens, exceptionTypeDescriptors);
1✔
3768
                        }
3769

3770
                        /**
3771
                         * {@inheritDoc}
3772
                         */
3773
                        public Generic resolveRecordType(String recordTypeDescriptor,
3774
                                                         TypePool typePool,
3775
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3776
                                                         RecordComponentDescription.InDefinedShape definingRecordComponent) {
3777
                            return RawAnnotatedType.of(typePool, annotationTokens, recordTypeDescriptor);
×
3778
                        }
3779

3780
                        /**
3781
                         * Represents a non-generic type that defines type annotations.
3782
                         */
3783
                        protected static class RawAnnotatedType extends Generic.OfNonGenericType {
3784

3785
                            /**
3786
                             * The type pool to use.
3787
                             */
3788
                            private final TypePool typePool;
3789

3790
                            /**
3791
                             * The type's type path.
3792
                             */
3793
                            private final String typePath;
3794

3795
                            /**
3796
                             * A mapping of this type's type annotations.
3797
                             */
3798
                            private final Map<String, List<AnnotationToken>> annotationTokens;
3799

3800
                            /**
3801
                             * The represented non-generic type.
3802
                             */
3803
                            private final TypeDescription typeDescription;
3804

3805
                            /**
3806
                             * Creates a new raw annotated type.
3807
                             *
3808
                             * @param typePool         The type pool to use.
3809
                             * @param typePath         The type's type path.
3810
                             * @param annotationTokens A mapping of this type's type annotations.
3811
                             * @param typeDescription  The represented non-generic type.
3812
                             */
3813
                            protected RawAnnotatedType(TypePool typePool,
3814
                                                       String typePath,
3815
                                                       Map<String, List<AnnotationToken>> annotationTokens,
3816
                                                       TypeDescription typeDescription) {
1✔
3817
                                this.typePool = typePool;
1✔
3818
                                this.typePath = typePath;
1✔
3819
                                this.annotationTokens = annotationTokens;
1✔
3820
                                this.typeDescription = typeDescription;
1✔
3821
                            }
1✔
3822

3823
                            /**
3824
                             * Creates a new raw annotated type.
3825
                             *
3826
                             * @param typePool         The type pool to use.
3827
                             * @param annotationTokens A mapping of this type's type annotations.
3828
                             * @param descriptor       The descriptor of the represented non-generic type.
3829
                             * @return An annotated non-generic type.
3830
                             */
3831
                            protected static Generic of(TypePool typePool,
3832
                                                        @MaybeNull Map<String, List<AnnotationToken>> annotationTokens,
3833
                                                        String descriptor) {
3834
                                return new RawAnnotatedType(typePool,
1✔
3835
                                        EMPTY_TYPE_PATH,
3836
                                        annotationTokens == null
3837
                                                ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
3838
                                                : annotationTokens,
3839
                                        TokenizedGenericType.toErasure(typePool, descriptor));
1✔
3840
                            }
3841

3842
                            /**
3843
                             * {@inheritDoc}
3844
                             */
3845
                            public TypeDescription asErasure() {
3846
                                return typeDescription;
1✔
3847
                            }
3848

3849
                            /**
3850
                             * {@inheritDoc}
3851
                             */
3852
                            @MaybeNull
3853
                            public Generic getOwnerType() {
3854
                                TypeDescription declaringType = typeDescription.getDeclaringType();
1✔
3855
                                return declaringType == null
1✔
3856
                                        ? Generic.UNDEFINED
3857
                                        : new RawAnnotatedType(typePool, typePath, annotationTokens, declaringType);
3858
                            }
3859

3860
                            /**
3861
                             * {@inheritDoc}
3862
                             */
3863
                            @MaybeNull
3864
                            public Generic getComponentType() {
3865
                                TypeDescription componentType = typeDescription.getComponentType();
1✔
3866
                                return componentType == null
1✔
3867
                                        ? Generic.UNDEFINED
3868
                                        : new RawAnnotatedType(typePool, typePath + COMPONENT_TYPE_PATH, annotationTokens, componentType);
3869
                            }
3870

3871
                            /**
3872
                             * {@inheritDoc}
3873
                             */
3874
                            public AnnotationList getDeclaredAnnotations() {
3875
                                StringBuilder typePath = new StringBuilder(this.typePath);
1✔
3876
                                for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
1✔
3877
                                    typePath = typePath.append(INNER_CLASS_PATH);
1✔
3878
                                }
3879
                                return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath.toString()));
1✔
3880
                            }
3881

3882
                            /**
3883
                             * A generic type list representing raw types.
3884
                             */
3885
                            protected static class LazyRawAnnotatedTypeList extends TypeList.Generic.AbstractBase {
3886

3887
                                /**
3888
                                 * The type pool to use for locating types.
3889
                                 */
3890
                                private final TypePool typePool;
3891

3892
                                /**
3893
                                 * A mapping of the represented types' type annotation tokens by their indices.
3894
                                 */
3895
                                private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
3896

3897
                                /**
3898
                                 * A list of type descriptors that this list represents.
3899
                                 */
3900
                                private final List<String> descriptors;
3901

3902
                                /**
3903
                                 * Creates a generic type list only representing raw types.
3904
                                 *
3905
                                 * @param typePool         The type pool to use for locating types.
3906
                                 * @param annotationTokens A mapping of the represented types' type annotation tokens by their indices.
3907
                                 * @param descriptors      A list of type descriptors that this list represents.
3908
                                 */
3909
                                protected LazyRawAnnotatedTypeList(TypePool typePool,
3910
                                                                   Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3911
                                                                   List<String> descriptors) {
1✔
3912
                                    this.typePool = typePool;
1✔
3913
                                    this.annotationTokens = annotationTokens;
1✔
3914
                                    this.descriptors = descriptors;
1✔
3915
                                }
1✔
3916

3917
                                /**
3918
                                 * Creates generic type list only representing raw types.
3919
                                 *
3920
                                 * @param typePool         The type pool to use for locating types.
3921
                                 * @param annotationTokens A mapping of the represented types' type annotation tokens by their indices or
3922
                                 *                         {@code null} if no type annotations are defined for any type.
3923
                                 * @param descriptors      A list of type descriptors that this list represents.
3924
                                 * @return A generic type list representing the raw types this list represents.
3925
                                 */
3926
                                protected static TypeList.Generic of(TypePool typePool,
3927
                                                                     @MaybeNull Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
3928
                                                                     List<String> descriptors) {
3929
                                    return new LazyRawAnnotatedTypeList(typePool,
1✔
3930
                                            annotationTokens == null
3931
                                                    ? Collections.<Integer, Map<String, List<AnnotationToken>>>emptyMap()
1✔
3932
                                                    : annotationTokens,
3933
                                            descriptors);
3934
                                }
3935

3936
                                /**
3937
                                 * {@inheritDoc}
3938
                                 */
3939
                                public Generic get(int index) {
3940
                                    return RawAnnotatedType.of(typePool, annotationTokens.get(index), descriptors.get(index));
1✔
3941
                                }
3942

3943
                                /**
3944
                                 * {@inheritDoc}
3945
                                 */
3946
                                public int size() {
3947
                                    return descriptors.size();
1✔
3948
                                }
3949

3950
                                /**
3951
                                 * {@inheritDoc}
3952
                                 */
3953
                                public TypeList asErasures() {
3954
                                    return new LazyTypeList(typePool, descriptors);
1✔
3955
                                }
3956

3957
                                /**
3958
                                 * {@inheritDoc}
3959
                                 */
3960
                                public TypeList.Generic asRawTypes() {
3961
                                    return this;
×
3962
                                }
3963

3964
                                /**
3965
                                 * {@inheritDoc}
3966
                                 */
3967
                                public int getStackSize() {
3968
                                    int stackSize = 0;
1✔
3969
                                    for (String descriptor : descriptors) {
1✔
3970
                                        stackSize += Type.getType(descriptor).getSize();
1✔
3971
                                    }
1✔
3972
                                    return stackSize;
1✔
3973
                                }
3974
                            }
3975
                        }
3976
                    }
3977

3978
                    /**
3979
                     * A resolution of a type's, method's or field's generic types if its generic signature is malformed.
3980
                     */
3981
                    enum Malformed implements ForType, ForField, ForMethod, ForRecordComponent {
1✔
3982

3983
                        /**
3984
                         * The singleton instance.
3985
                         */
3986
                        INSTANCE;
1✔
3987

3988
                        /**
3989
                         * {@inheritDoc}
3990
                         */
3991
                        public Generic resolveSuperClass(String superClassDescriptor,
3992
                                                         TypePool typePool,
3993
                                                         Map<String, List<AnnotationToken>> annotationTokens,
3994
                                                         TypeDescription definingType) {
3995
                            return new TokenizedGenericType.Malformed(typePool, superClassDescriptor);
×
3996
                        }
3997

3998
                        /**
3999
                         * {@inheritDoc}
4000
                         */
4001
                        public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
4002
                                                                      TypePool typePool,
4003
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4004
                                                                      TypeDescription definingType) {
4005
                            return new TokenizedGenericType.Malformed.TokenList(typePool, interfaceTypeDescriptors);
1✔
4006
                        }
4007

4008
                        /**
4009
                         * {@inheritDoc}
4010
                         */
4011
                        public TypeList.Generic resolveTypeVariables(TypePool typePool,
4012
                                                                     TypeVariableSource typeVariableSource,
4013
                                                                     Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4014
                                                                     Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
4015
                            throw new GenericSignatureFormatError();
×
4016
                        }
4017

4018
                        /**
4019
                         * {@inheritDoc}
4020
                         */
4021
                        public Generic resolveFieldType(String fieldTypeDescriptor,
4022
                                                        TypePool typePool,
4023
                                                        Map<String, List<AnnotationToken>> annotationTokens,
4024
                                                        FieldDescription.InDefinedShape definingField) {
4025
                            return new TokenizedGenericType.Malformed(typePool, fieldTypeDescriptor);
1✔
4026
                        }
4027

4028
                        /**
4029
                         * {@inheritDoc}
4030
                         */
4031
                        public Generic resolveReturnType(String returnTypeDescriptor,
4032
                                                         TypePool typePool,
4033
                                                         Map<String, List<AnnotationToken>> annotationTokens,
4034
                                                         MethodDescription.InDefinedShape definingMethod) {
4035
                            return new TokenizedGenericType.Malformed(typePool, returnTypeDescriptor);
1✔
4036
                        }
4037

4038
                        /**
4039
                         * {@inheritDoc}
4040
                         */
4041
                        public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
4042
                                                                      TypePool typePool,
4043
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4044
                                                                      MethodDescription.InDefinedShape definingMethod) {
4045
                            return new TokenizedGenericType.Malformed.TokenList(typePool, parameterTypeDescriptors);
×
4046
                        }
4047

4048
                        /**
4049
                         * {@inheritDoc}
4050
                         */
4051
                        public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
4052
                                                                      TypePool typePool,
4053
                                                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4054
                                                                      MethodDescription.InDefinedShape definingMethod) {
4055
                            return new TokenizedGenericType.Malformed.TokenList(typePool, exceptionTypeDescriptors);
×
4056
                        }
4057

4058

4059
                        /**
4060
                         * {@inheritDoc}
4061
                         */
4062
                        public Generic resolveRecordType(String recordTypeDescriptor,
4063
                                                         TypePool typePool,
4064
                                                         Map<String, List<AnnotationToken>> annotationTokens,
4065
                                                         RecordComponentDescription.InDefinedShape definingRecordComponent) {
4066
                            return new TokenizedGenericType.Malformed(typePool, recordTypeDescriptor);
×
4067
                        }
4068
                    }
4069

4070
                    /**
4071
                     * A resolution of the generic types of a {@link TypeDescription}.
4072
                     */
4073
                    interface ForType extends Resolution {
4074

4075
                        /**
4076
                         * Resolves the generic super type of the represented type.
4077
                         *
4078
                         * @param superClassDescriptor The descriptor of the raw super type.
4079
                         * @param typePool             The type pool to be used for locating non-generic type descriptions.
4080
                         * @param annotationTokens     A mapping of the super type's type annotation tokens.
4081
                         * @param definingType         The type that defines this super type.
4082
                         * @return A description of this type's generic super type.
4083
                         */
4084
                        Generic resolveSuperClass(String superClassDescriptor,
4085
                                                  TypePool typePool,
4086
                                                  Map<String, List<AnnotationToken>> annotationTokens,
4087
                                                  TypeDescription definingType);
4088

4089
                        /**
4090
                         * Resolves the generic interface types of the represented type.
4091
                         *
4092
                         * @param interfaceTypeDescriptors The descriptor of the raw interface types.
4093
                         * @param typePool                 The type pool to be used for locating non-generic type descriptions.
4094
                         * @param annotationTokens         A mapping of the interface types' type annotation tokens by their indices.
4095
                         * @param definingType             The type that defines these interface type.
4096
                         * @return A description of this type's generic interface types.
4097
                         */
4098
                        TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
4099
                                                               TypePool typePool,
4100
                                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4101
                                                               TypeDescription definingType);
4102

4103
                        /**
4104
                         * An implementation of a tokenized resolution of generic types of a {@link TypeDescription}.
4105
                         */
4106
                        @HashCodeAndEqualsPlugin.Enhance
4107
                        class Tokenized implements ForType {
4108

4109
                            /**
4110
                             * The super type's generic type token.
4111
                             */
4112
                            private final GenericTypeToken superClassToken;
4113

4114
                            /**
4115
                             * The interface type's generic type tokens.
4116
                             */
4117
                            private final List<GenericTypeToken> interfaceTypeTokens;
4118

4119
                            /**
4120
                             * The type variables generic type tokens.
4121
                             */
4122
                            private final List<OfFormalTypeVariable> typeVariableTokens;
4123

4124
                            /**
4125
                             * Creates a new tokenized resolution of a {@link TypeDescription}'s generic signatures.
4126
                             *
4127
                             * @param superClassToken     The super class's generic type token.
4128
                             * @param interfaceTypeTokens The interface type's generic type tokens.
4129
                             * @param typeVariableTokens  The type variables generic type tokens.
4130
                             */
4131
                            protected Tokenized(GenericTypeToken superClassToken,
4132
                                                List<GenericTypeToken> interfaceTypeTokens,
4133
                                                List<OfFormalTypeVariable> typeVariableTokens) {
1✔
4134
                                this.superClassToken = superClassToken;
1✔
4135
                                this.interfaceTypeTokens = interfaceTypeTokens;
1✔
4136
                                this.typeVariableTokens = typeVariableTokens;
1✔
4137
                            }
1✔
4138

4139
                            /**
4140
                             * {@inheritDoc}
4141
                             */
4142
                            public Generic resolveSuperClass(String superClassDescriptor,
4143
                                                             TypePool typePool,
4144
                                                             Map<String, List<AnnotationToken>> annotationTokens,
4145
                                                             TypeDescription definingType) {
4146
                                return TokenizedGenericType.of(typePool,
1✔
4147
                                        superClassToken,
4148
                                        superClassDescriptor,
4149
                                        annotationTokens,
4150
                                        definingType);
4151
                            }
4152

4153
                            /**
4154
                             * {@inheritDoc}
4155
                             */
4156
                            public TypeList.Generic resolveInterfaceTypes(List<String> interfaceTypeDescriptors,
4157
                                                                          TypePool typePool,
4158
                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4159
                                                                          TypeDescription definingType) {
4160
                                return new TokenizedGenericType.TokenList(typePool, interfaceTypeTokens, annotationTokens, interfaceTypeDescriptors, definingType);
1✔
4161
                            }
4162

4163
                            /**
4164
                             * {@inheritDoc}
4165
                             */
4166
                            public TypeList.Generic resolveTypeVariables(TypePool typePool,
4167
                                                                         TypeVariableSource typeVariableSource,
4168
                                                                         Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4169
                                                                         Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
4170
                                return new TokenizedGenericType.TypeVariableList(typePool, typeVariableTokens, typeVariableSource, annotationTokens, boundAnnotationTokens);
1✔
4171
                            }
4172
                        }
4173
                    }
4174

4175
                    /**
4176
                     * A resolution of the generic type of a {@link FieldDescription}.
4177
                     */
4178
                    interface ForField {
4179

4180
                        /**
4181
                         * Resolves the field type of the represented field.
4182
                         *
4183
                         * @param fieldTypeDescriptor The descriptor of the raw field type.
4184
                         * @param typePool            The type pool to be used for locating non-generic type descriptions.
4185
                         * @param annotationTokens    A mapping of the represented types' type annotation tokens.
4186
                         * @param definingField       The field that defines this type.
4187
                         * @return A generic type representation of the field's type.
4188
                         */
4189
                        Generic resolveFieldType(String fieldTypeDescriptor,
4190
                                                 TypePool typePool,
4191
                                                 Map<String, List<AnnotationToken>> annotationTokens,
4192
                                                 FieldDescription.InDefinedShape definingField);
4193

4194
                        /**
4195
                         * An implementation of a tokenized resolution of the generic type of a {@link FieldDescription}.
4196
                         */
4197
                        @HashCodeAndEqualsPlugin.Enhance
4198
                        class Tokenized implements ForField {
4199

4200
                            /**
4201
                             * The token of the represented field's type.
4202
                             */
4203
                            private final GenericTypeToken fieldTypeToken;
4204

4205
                            /**
4206
                             * Creates a new tokenized resolution of a {@link FieldDescription}'s type.
4207
                             *
4208
                             * @param fieldTypeToken The token of the represented field's type.
4209
                             */
4210
                            protected Tokenized(GenericTypeToken fieldTypeToken) {
1✔
4211
                                this.fieldTypeToken = fieldTypeToken;
1✔
4212
                            }
1✔
4213

4214
                            /**
4215
                             * {@inheritDoc}
4216
                             */
4217
                            public Generic resolveFieldType(String fieldTypeDescriptor,
4218
                                                            TypePool typePool,
4219
                                                            Map<String, List<AnnotationToken>> annotationTokens,
4220
                                                            FieldDescription.InDefinedShape definingField) {
4221
                                return TokenizedGenericType.of(typePool,
1✔
4222
                                        fieldTypeToken,
4223
                                        fieldTypeDescriptor,
4224
                                        annotationTokens,
4225
                                        definingField.getDeclaringType());
1✔
4226
                            }
4227
                        }
4228
                    }
4229

4230
                    /**
4231
                     * A resolution of the generic types of a {@link MethodDescription}.
4232
                     */
4233
                    interface ForMethod extends Resolution {
4234

4235
                        /**
4236
                         * Resolves the return type of the represented method.
4237
                         *
4238
                         * @param returnTypeDescriptor The descriptor of the raw return type.
4239
                         * @param typePool             The type pool to be used for locating non-generic type descriptions.
4240
                         * @param annotationTokens     A mapping of the return type's type annotation tokens.
4241
                         * @param definingMethod       The method that defines this return type.
4242
                         * @return A description of this type's generic return type.
4243
                         */
4244
                        Generic resolveReturnType(String returnTypeDescriptor,
4245
                                                  TypePool typePool,
4246
                                                  Map<String, List<AnnotationToken>> annotationTokens,
4247
                                                  MethodDescription.InDefinedShape definingMethod);
4248

4249
                        /**
4250
                         * Resolves the generic parameter types of the represented method.
4251
                         *
4252
                         * @param parameterTypeDescriptors The descriptor of the raw parameter types.
4253
                         * @param typePool                 The type pool to be used for locating non-generic type descriptions.
4254
                         * @param annotationTokens         A mapping of the parameter types' type annotation tokens by their indices.
4255
                         * @param definingMethod           The method that defines these parameter types.
4256
                         * @return A description of this type's generic interface types.
4257
                         */
4258
                        TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
4259
                                                               TypePool typePool,
4260
                                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4261
                                                               MethodDescription.InDefinedShape definingMethod);
4262

4263
                        /**
4264
                         * Resolves the generic parameter types of the represented method.
4265
                         *
4266
                         * @param exceptionTypeDescriptors The descriptor of the raw exception types.
4267
                         * @param typePool                 The type pool to be used for locating non-generic type descriptions.
4268
                         * @param annotationTokens         A mapping of the exception types' type annotation tokens by their indices.
4269
                         * @param definingMethod           The method that defines these exception types.
4270
                         * @return A description of this type's generic interface types.
4271
                         */
4272
                        TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
4273
                                                               TypePool typePool,
4274
                                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4275
                                                               MethodDescription.InDefinedShape definingMethod);
4276

4277
                        /**
4278
                         * An implementation of a tokenized resolution of generic types of a {@link MethodDescription}.
4279
                         */
4280
                        @HashCodeAndEqualsPlugin.Enhance
4281
                        class Tokenized implements ForMethod {
4282

4283
                            /**
4284
                             * A token describing the represented method's return type.
4285
                             */
4286
                            private final GenericTypeToken returnTypeToken;
4287

4288
                            /**
4289
                             * A token describing the represented method's parameter types.
4290
                             */
4291
                            private final List<GenericTypeToken> parameterTypeTokens;
4292

4293
                            /**
4294
                             * A token describing the represented method's exception types.
4295
                             */
4296
                            private final List<GenericTypeToken> exceptionTypeTokens;
4297

4298
                            /**
4299
                             * A token describing the represented method's type variables.
4300
                             */
4301
                            private final List<OfFormalTypeVariable> typeVariableTokens;
4302

4303
                            /**
4304
                             * Creates a new tokenized resolution of a {@link MethodDescription}'s generic signatures.
4305
                             *
4306
                             * @param returnTypeToken     A token describing the represented method's return type.
4307
                             * @param parameterTypeTokens A token describing the represented method's parameter types.
4308
                             * @param exceptionTypeTokens A token describing the represented method's exception types.
4309
                             * @param typeVariableTokens  A token describing the represented method's type variables.
4310
                             */
4311
                            protected Tokenized(GenericTypeToken returnTypeToken,
4312
                                                List<GenericTypeToken> parameterTypeTokens,
4313
                                                List<GenericTypeToken> exceptionTypeTokens,
4314
                                                List<OfFormalTypeVariable> typeVariableTokens) {
1✔
4315
                                this.returnTypeToken = returnTypeToken;
1✔
4316
                                this.parameterTypeTokens = parameterTypeTokens;
1✔
4317
                                this.exceptionTypeTokens = exceptionTypeTokens;
1✔
4318
                                this.typeVariableTokens = typeVariableTokens;
1✔
4319
                            }
1✔
4320

4321
                            /**
4322
                             * {@inheritDoc}
4323
                             */
4324
                            public Generic resolveReturnType(String returnTypeDescriptor,
4325
                                                             TypePool typePool,
4326
                                                             Map<String, List<AnnotationToken>> annotationTokens,
4327
                                                             MethodDescription.InDefinedShape definingMethod) {
4328
                                return TokenizedGenericType.of(typePool,
1✔
4329
                                        returnTypeToken,
4330
                                        returnTypeDescriptor,
4331
                                        annotationTokens,
4332
                                        definingMethod);
4333
                            }
4334

4335
                            /**
4336
                             * {@inheritDoc}
4337
                             */
4338
                            public TypeList.Generic resolveParameterTypes(List<String> parameterTypeDescriptors,
4339
                                                                          TypePool typePool,
4340
                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4341
                                                                          MethodDescription.InDefinedShape definingMethod) {
4342
                                return new TokenizedGenericType.TokenList(typePool, parameterTypeTokens, annotationTokens, parameterTypeDescriptors, definingMethod);
1✔
4343
                            }
4344

4345
                            /**
4346
                             * {@inheritDoc}
4347
                             */
4348
                            public TypeList.Generic resolveExceptionTypes(List<String> exceptionTypeDescriptors,
4349
                                                                          TypePool typePool,
4350
                                                                          Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4351
                                                                          MethodDescription.InDefinedShape definingMethod) {
4352
                                // Generic signatures of methods are optional.
4353
                                return exceptionTypeTokens.isEmpty()
1✔
4354
                                        ? Raw.INSTANCE.resolveExceptionTypes(exceptionTypeDescriptors, typePool, annotationTokens, definingMethod)
1✔
4355
                                        : new TokenizedGenericType.TokenList(typePool, exceptionTypeTokens, annotationTokens, exceptionTypeDescriptors, definingMethod);
4356
                            }
4357

4358
                            /**
4359
                             * {@inheritDoc}
4360
                             */
4361
                            public TypeList.Generic resolveTypeVariables(TypePool typePool,
4362
                                                                         TypeVariableSource typeVariableSource,
4363
                                                                         Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4364
                                                                         Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
4365
                                return new TokenizedGenericType.TypeVariableList(typePool, typeVariableTokens, typeVariableSource, annotationTokens, boundAnnotationTokens);
1✔
4366
                            }
4367
                        }
4368
                    }
4369

4370
                    /**
4371
                     * A resolution of the generic type of a {@link RecordComponentDescription}.
4372
                     */
4373
                    interface ForRecordComponent {
4374

4375
                        /**
4376
                         * Resolves a record component's type.
4377
                         *
4378
                         * @param recordTypeDescriptor    The record component's descriptor.
4379
                         * @param typePool                The type pool to be used for locating non-generic type descriptions.
4380
                         * @param annotationTokens        A mapping of the represented types' type annotation tokens.
4381
                         * @param definingRecordComponent The defining record component.
4382
                         * @return A generic type representation of the record component's type.
4383
                         */
4384
                        Generic resolveRecordType(String recordTypeDescriptor,
4385
                                                  TypePool typePool,
4386
                                                  Map<String, List<AnnotationToken>> annotationTokens,
4387
                                                  RecordComponentDescription.InDefinedShape definingRecordComponent);
4388

4389
                        /**
4390
                         * An implementation of a tokenized resolution of the generic type of a {@link RecordComponentDescription}.
4391
                         */
4392
                        @HashCodeAndEqualsPlugin.Enhance
4393
                        class Tokenized implements ForRecordComponent {
4394

4395
                            /**
4396
                             * The token of the represented record component's type.
4397
                             */
4398
                            private final GenericTypeToken recordComponentTypeToken;
4399

4400
                            /**
4401
                             * Creates a new tokenized resolution of a {@link RecordComponentDescription}'s type.
4402
                             *
4403
                             * @param recordComponentTypeToken The token of the represented record component's type.
4404
                             */
4405
                            protected Tokenized(GenericTypeToken recordComponentTypeToken) {
×
4406
                                this.recordComponentTypeToken = recordComponentTypeToken;
×
4407
                            }
×
4408

4409
                            /**
4410
                             * {@inheritDoc}
4411
                             */
4412
                            public Generic resolveRecordType(String recordTypeDescriptor,
4413
                                                             TypePool typePool,
4414
                                                             Map<String, List<AnnotationToken>> annotationTokens,
4415
                                                             RecordComponentDescription.InDefinedShape definingRecordComponent) {
4416
                                return TokenizedGenericType.of(typePool,
×
4417
                                        recordComponentTypeToken,
4418
                                        recordTypeDescriptor,
4419
                                        annotationTokens,
4420
                                        definingRecordComponent.getDeclaringType());
×
4421
                            }
4422
                        }
4423
                    }
4424
                }
4425

4426
                /**
4427
                 * A generic type token that represents a non-generic type.
4428
                 */
4429
                @HashCodeAndEqualsPlugin.Enhance
4430
                class ForRawType implements GenericTypeToken {
4431

4432
                    /**
4433
                     * The name of the represented type.
4434
                     */
4435
                    private final String name;
4436

4437
                    /**
4438
                     * Creates a new type token that represents a non-generic type.
4439
                     *
4440
                     * @param name The name of the represented type.
4441
                     */
4442
                    protected ForRawType(String name) {
1✔
4443
                        this.name = name;
1✔
4444
                    }
1✔
4445

4446
                    /**
4447
                     * {@inheritDoc}
4448
                     */
4449
                    public Generic toGenericType(TypePool typePool,
4450
                                                 TypeVariableSource typeVariableSource,
4451
                                                 String typePath,
4452
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4453
                        return new Resolution.Raw.RawAnnotatedType(typePool,
1✔
4454
                                typePath,
4455
                                annotationTokens,
4456
                                typePool.describe(name).resolve());
1✔
4457
                    }
4458

4459
                    /**
4460
                     * {@inheritDoc}
4461
                     */
4462
                    public boolean isPrimaryBound(TypePool typePool) {
4463
                        return !typePool.describe(name).resolve().isInterface();
1✔
4464
                    }
4465

4466
                    /**
4467
                     * {@inheritDoc}
4468
                     */
4469
                    public String getTypePathPrefix() {
4470
                        throw new IllegalStateException("A non-generic type cannot be the owner of a nested type: " + this);
1✔
4471
                    }
4472
                }
4473

4474
                /**
4475
                 * A generic type token that represents a type variable.
4476
                 */
4477
                @HashCodeAndEqualsPlugin.Enhance
4478
                class ForTypeVariable implements GenericTypeToken {
4479

4480
                    /**
4481
                     * This type variable's nominal symbol.
4482
                     */
4483
                    private final String symbol;
4484

4485
                    /**
4486
                     * Creates a generic type token that represents a type variable.
4487
                     *
4488
                     * @param symbol This type variable's nominal symbol.
4489
                     */
4490
                    protected ForTypeVariable(String symbol) {
1✔
4491
                        this.symbol = symbol;
1✔
4492
                    }
1✔
4493

4494
                    /**
4495
                     * {@inheritDoc}
4496
                     */
4497
                    public Generic toGenericType(TypePool typePool,
4498
                                                 TypeVariableSource typeVariableSource,
4499
                                                 String typePath,
4500
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4501
                        Generic typeVariable = typeVariableSource.findVariable(symbol);
1✔
4502
                        return typeVariable == null
1✔
4503
                                ? new UnresolvedTypeVariable(typeVariableSource, typePool, symbol, annotationTokens.get(typePath))
1✔
4504
                                : new AnnotatedTypeVariable(typePool, annotationTokens.get(typePath), typeVariable);
1✔
4505
                    }
4506

4507
                    /**
4508
                     * {@inheritDoc}
4509
                     */
4510
                    public boolean isPrimaryBound(TypePool typePool) {
4511
                        return true;
1✔
4512
                    }
4513

4514
                    /**
4515
                     * {@inheritDoc}
4516
                     */
4517
                    public String getTypePathPrefix() {
4518
                        throw new IllegalStateException("A type variable cannot be the owner of a nested type: " + this);
1✔
4519
                    }
4520

4521
                    /**
4522
                     * An annotated representation of a formal type variable.
4523
                     */
4524
                    protected static class AnnotatedTypeVariable extends Generic.OfTypeVariable {
4525

4526
                        /**
4527
                         * The type pool to use.
4528
                         */
4529
                        private final TypePool typePool;
4530

4531
                        /**
4532
                         * The represented annotation tokens.
4533
                         */
4534
                        private final List<AnnotationToken> annotationTokens;
4535

4536
                        /**
4537
                         * The represented type variable.
4538
                         */
4539
                        private final Generic typeVariable;
4540

4541
                        /**
4542
                         * Creates a new annotated type variable.
4543
                         *
4544
                         * @param typePool         The type pool to use.
4545
                         * @param annotationTokens The represented annotation tokens.
4546
                         * @param typeVariable     The represented type variable.
4547
                         */
4548
                        protected AnnotatedTypeVariable(TypePool typePool, List<AnnotationToken> annotationTokens, Generic typeVariable) {
1✔
4549
                            this.typePool = typePool;
1✔
4550
                            this.annotationTokens = annotationTokens;
1✔
4551
                            this.typeVariable = typeVariable;
1✔
4552
                        }
1✔
4553

4554
                        /**
4555
                         * {@inheritDoc}
4556
                         */
4557
                        public TypeList.Generic getUpperBounds() {
4558
                            return typeVariable.getUpperBounds();
1✔
4559
                        }
4560

4561
                        /**
4562
                         * {@inheritDoc}
4563
                         */
4564
                        public TypeVariableSource getTypeVariableSource() {
4565
                            return typeVariable.getTypeVariableSource();
1✔
4566
                        }
4567

4568
                        /**
4569
                         * {@inheritDoc}
4570
                         */
4571
                        public String getSymbol() {
4572
                            return typeVariable.getSymbol();
1✔
4573
                        }
4574

4575
                        /**
4576
                         * {@inheritDoc}
4577
                         */
4578
                        public AnnotationList getDeclaredAnnotations() {
4579
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
1✔
4580
                        }
4581
                    }
4582

4583
                    /**
4584
                     * Represents a type variable that a type references but that does not exist. Such type variables are only emitted by wrongful
4585
                     * compilation either due to the isolated recompilation of outer classes or due to bugs in compilers.
4586
                     */
4587
                    protected static class UnresolvedTypeVariable extends Generic.OfTypeVariable {
4588

4589
                        /**
4590
                         * The undeclared type variable's source.
4591
                         */
4592
                        private final TypeVariableSource typeVariableSource;
4593

4594
                        /**
4595
                         * The type pool to use.
4596
                         */
4597
                        private final TypePool typePool;
4598

4599
                        /**
4600
                         * The type variable's symbol.
4601
                         */
4602
                        private final String symbol;
4603

4604
                        /**
4605
                         * The type variable's annotation tokens.
4606
                         */
4607
                        private final List<AnnotationToken> annotationTokens;
4608

4609
                        /**
4610
                         * Creates an unresolved type variable.
4611
                         *
4612
                         * @param typeVariableSource The undeclared type variable's source.
4613
                         * @param typePool           The type pool to use.
4614
                         * @param symbol             The type variable's symbol.
4615
                         * @param annotationTokens   The type variable's annotation tokens.
4616
                         */
4617
                        protected UnresolvedTypeVariable(TypeVariableSource typeVariableSource,
4618
                                                         TypePool typePool,
4619
                                                         String symbol,
4620
                                                         List<AnnotationToken> annotationTokens) {
1✔
4621
                            this.typeVariableSource = typeVariableSource;
1✔
4622
                            this.typePool = typePool;
1✔
4623
                            this.symbol = symbol;
1✔
4624
                            this.annotationTokens = annotationTokens;
1✔
4625
                        }
1✔
4626

4627
                        /**
4628
                         * {@inheritDoc}
4629
                         */
4630
                        public TypeList.Generic getUpperBounds() {
4631
                            throw new TypeNotPresentException(symbol, null);
1✔
4632
                        }
4633

4634
                        /**
4635
                         * {@inheritDoc}
4636
                         */
4637
                        public TypeVariableSource getTypeVariableSource() {
4638
                            return typeVariableSource;
×
4639
                        }
4640

4641
                        /**
4642
                         * {@inheritDoc}
4643
                         */
4644
                        public String getSymbol() {
4645
                            return symbol;
×
4646
                        }
4647

4648
                        /**
4649
                         * {@inheritDoc}
4650
                         */
4651
                        public AnnotationList getDeclaredAnnotations() {
4652
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
×
4653
                        }
4654
                    }
4655

4656
                    /**
4657
                     * A generic type token that represent a formal type variable, i.e. a type variable including its upper bounds.
4658
                     */
4659
                    @HashCodeAndEqualsPlugin.Enhance
4660
                    protected static class Formal implements GenericTypeToken.OfFormalTypeVariable {
4661

4662
                        /**
4663
                         * This type variable's nominal symbol.
4664
                         */
4665
                        private final String symbol;
4666

4667
                        /**
4668
                         * A list of tokens that represent this type variable's upper bounds.
4669
                         */
4670
                        private final List<GenericTypeToken> boundTypeTokens;
4671

4672
                        /**
4673
                         * Creates generic type token that represent a formal type variable.
4674
                         *
4675
                         * @param symbol          This type variable's nominal symbol.
4676
                         * @param boundTypeTokens A list of tokens that represent this type variable's upper bounds.
4677
                         */
4678
                        protected Formal(String symbol, List<GenericTypeToken> boundTypeTokens) {
1✔
4679
                            this.symbol = symbol;
1✔
4680
                            this.boundTypeTokens = boundTypeTokens;
1✔
4681
                        }
1✔
4682

4683
                        /**
4684
                         * {@inheritDoc}
4685
                         */
4686
                        public Generic toGenericType(TypePool typePool,
4687
                                                     TypeVariableSource typeVariableSource,
4688
                                                     @MaybeNull Map<String, List<AnnotationToken>> annotationTokens,
4689
                                                     @MaybeNull Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens) {
4690
                            return new LazyTypeVariable(typePool,
1✔
4691
                                    typeVariableSource,
4692
                                    annotationTokens == null
4693
                                            ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
4694
                                            : annotationTokens,
4695
                                    boundaryAnnotationTokens == null
4696
                                            ? Collections.<Integer, Map<String, List<AnnotationToken>>>emptyMap()
1✔
4697
                                            : boundaryAnnotationTokens,
4698
                                    symbol,
4699
                                    boundTypeTokens);
4700
                        }
4701

4702
                        /**
4703
                         * A type description that represents a type variable with bounds that are resolved lazily.
4704
                         */
4705
                        protected static class LazyTypeVariable extends Generic.OfTypeVariable {
4706

4707
                            /**
4708
                             * The type pool to use for locating type descriptions.
4709
                             */
4710
                            private final TypePool typePool;
4711

4712
                            /**
4713
                             * The type variable source to use for locating type variables.
4714
                             */
4715
                            private final TypeVariableSource typeVariableSource;
4716

4717
                            /**
4718
                             * The type variable's type annotation tokens.
4719
                             */
4720
                            private final Map<String, List<AnnotationToken>> annotationTokens;
4721

4722
                            /**
4723
                             * A mapping of the type variable bounds' type annotation tokens by their indices.
4724
                             */
4725
                            private final Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens;
4726

4727
                            /**
4728
                             * The type variable's symbol.
4729
                             */
4730
                            private final String symbol;
4731

4732
                            /**
4733
                             * Tokenized representations of the type variables bound types.
4734
                             */
4735
                            private final List<GenericTypeToken> boundTypeTokens;
4736

4737
                            /**
4738
                             * Creates a lazy type description of a type variables.
4739
                             *
4740
                             * @param typePool                 The type pool to use for locating type descriptions.
4741
                             * @param typeVariableSource       The type variable source to use for locating type variables.
4742
                             * @param annotationTokens         The type variable's type annotation tokens.
4743
                             * @param boundaryAnnotationTokens A mapping of the type variable bounds' type annotation tokens by their indices.
4744
                             * @param symbol                   The type variable's symbol.
4745
                             * @param boundTypeTokens          Tokenized representations of the type variables bound types.
4746
                             */
4747
                            protected LazyTypeVariable(TypePool typePool,
4748
                                                       TypeVariableSource typeVariableSource,
4749
                                                       Map<String, List<AnnotationToken>> annotationTokens,
4750
                                                       Map<Integer, Map<String, List<AnnotationToken>>> boundaryAnnotationTokens,
4751
                                                       String symbol,
4752
                                                       List<GenericTypeToken> boundTypeTokens) {
1✔
4753
                                this.typePool = typePool;
1✔
4754
                                this.typeVariableSource = typeVariableSource;
1✔
4755
                                this.annotationTokens = annotationTokens;
1✔
4756
                                this.boundaryAnnotationTokens = boundaryAnnotationTokens;
1✔
4757
                                this.symbol = symbol;
1✔
4758
                                this.boundTypeTokens = boundTypeTokens;
1✔
4759
                            }
1✔
4760

4761
                            /**
4762
                             * {@inheritDoc}
4763
                             */
4764
                            public TypeList.Generic getUpperBounds() {
4765
                                return new LazyBoundTokenList(typePool, typeVariableSource, boundaryAnnotationTokens, boundTypeTokens);
1✔
4766
                            }
4767

4768
                            /**
4769
                             * {@inheritDoc}
4770
                             */
4771
                            public TypeVariableSource getTypeVariableSource() {
4772
                                return typeVariableSource;
1✔
4773
                            }
4774

4775
                            /**
4776
                             * {@inheritDoc}
4777
                             */
4778
                            public String getSymbol() {
4779
                                return symbol;
1✔
4780
                            }
4781

4782
                            /**
4783
                             * {@inheritDoc}
4784
                             */
4785
                            public AnnotationList getDeclaredAnnotations() {
4786
                                return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(EMPTY_TYPE_PATH));
1✔
4787
                            }
4788

4789
                            /**
4790
                             * A list representing a formal type variable's bounds.
4791
                             */
4792
                            protected static class LazyBoundTokenList extends TypeList.Generic.AbstractBase {
4793

4794
                                /**
4795
                                 * The type pool to use.
4796
                                 */
4797
                                private final TypePool typePool;
4798

4799
                                /**
4800
                                 * The type variable source for locating type variables.
4801
                                 */
4802
                                private final TypeVariableSource typeVariableSource;
4803

4804
                                /**
4805
                                 * A mapping of the bound type's type annotations by their bound index.
4806
                                 */
4807
                                private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
4808

4809
                                /**
4810
                                 * The bound types in their tokenized form.
4811
                                 */
4812
                                private final List<GenericTypeToken> boundTypeTokens;
4813

4814
                                /**
4815
                                 * Creates a new lazy bound token list for a type variable.
4816
                                 *
4817
                                 * @param typePool           The type pool to use.
4818
                                 * @param typeVariableSource The type variable source for locating type variables.
4819
                                 * @param annotationTokens   A mapping of the bound type's type annotations by their bound index.
4820
                                 * @param boundTypeTokens    The bound types in their tokenized form.
4821
                                 */
4822
                                protected LazyBoundTokenList(TypePool typePool,
4823
                                                             TypeVariableSource typeVariableSource,
4824
                                                             Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
4825
                                                             List<GenericTypeToken> boundTypeTokens) {
1✔
4826
                                    this.typePool = typePool;
1✔
4827
                                    this.typeVariableSource = typeVariableSource;
1✔
4828
                                    this.annotationTokens = annotationTokens;
1✔
4829
                                    this.boundTypeTokens = boundTypeTokens;
1✔
4830
                                }
1✔
4831

4832
                                /**
4833
                                 * {@inheritDoc}
4834
                                 */
4835
                                public Generic get(int index) {
4836
                                    // Avoid resolution of interface bound type unless a type annotation can be possibly resolved.
4837
                                    Map<String, List<AnnotationToken>> annotationTokens = !this.annotationTokens.containsKey(index) && !this.annotationTokens.containsKey(index + 1)
1✔
4838
                                            ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
4839
                                            : this.annotationTokens.get(index + (boundTypeTokens.get(0).isPrimaryBound(typePool) ? 0 : 1));
1✔
4840
                                    return boundTypeTokens.get(index).toGenericType(typePool,
1✔
4841
                                            typeVariableSource,
4842
                                            EMPTY_TYPE_PATH,
4843
                                            annotationTokens == null
4844
                                                    ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
4845
                                                    : annotationTokens);
4846
                                }
4847

4848
                                /**
4849
                                 * {@inheritDoc}
4850
                                 */
4851
                                public int size() {
4852
                                    return boundTypeTokens.size();
1✔
4853
                                }
4854
                            }
4855
                        }
4856
                    }
4857
                }
4858

4859
                /**
4860
                 * A generic type token that represents a generic array.
4861
                 */
4862
                @HashCodeAndEqualsPlugin.Enhance
4863
                class ForGenericArray implements GenericTypeToken {
4864

4865
                    /**
4866
                     * The array's component type.
4867
                     */
4868
                    private final GenericTypeToken componentTypeToken;
4869

4870
                    /**
4871
                     * Creates a generic type token that represents a generic array.
4872
                     *
4873
                     * @param componentTypeToken The array's component type.
4874
                     */
4875
                    protected ForGenericArray(GenericTypeToken componentTypeToken) {
1✔
4876
                        this.componentTypeToken = componentTypeToken;
1✔
4877
                    }
1✔
4878

4879
                    /**
4880
                     * {@inheritDoc}
4881
                     */
4882
                    public Generic toGenericType(TypePool typePool,
4883
                                                 TypeVariableSource typeVariableSource,
4884
                                                 String typePath,
4885
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4886
                        return new LazyGenericArray(typePool, typeVariableSource, typePath, annotationTokens, componentTypeToken);
1✔
4887
                    }
4888

4889
                    /**
4890
                     * {@inheritDoc}
4891
                     */
4892
                    public boolean isPrimaryBound(TypePool typePool) {
4893
                        throw new IllegalStateException("A generic array type cannot be a type variable bound: " + this);
1✔
4894
                    }
4895

4896
                    /**
4897
                     * {@inheritDoc}
4898
                     */
4899
                    public String getTypePathPrefix() {
4900
                        throw new IllegalStateException("A generic array type cannot be the owner of a nested type: " + this);
1✔
4901
                    }
4902

4903
                    /**
4904
                     * A generic type representation of a generic array.
4905
                     */
4906
                    protected static class LazyGenericArray extends Generic.OfGenericArray {
4907

4908
                        /**
4909
                         * The type pool to use.
4910
                         */
4911
                        private final TypePool typePool;
4912

4913
                        /**
4914
                         * The type variable source for locating type variables.
4915
                         */
4916
                        private final TypeVariableSource typeVariableSource;
4917

4918
                        /**
4919
                         * This type's type path.
4920
                         */
4921
                        private final String typePath;
4922

4923
                        /**
4924
                         * This type's type annotations.
4925
                         */
4926
                        private final Map<String, List<AnnotationToken>> annotationTokens;
4927

4928
                        /**
4929
                         * A tokenized representation of this generic arrays's component type.
4930
                         */
4931
                        private final GenericTypeToken componentTypeToken;
4932

4933
                        /**
4934
                         * Creates a new lazy generic array.
4935
                         *
4936
                         * @param typePool           The type pool to use.
4937
                         * @param typeVariableSource The type variable source for locating type variables.
4938
                         * @param typePath           This type's type path.
4939
                         * @param annotationTokens   This type's type annotations.
4940
                         * @param componentTypeToken A tokenized representation of this generic arrays's component type.
4941
                         */
4942
                        protected LazyGenericArray(TypePool typePool,
4943
                                                   TypeVariableSource typeVariableSource,
4944
                                                   String typePath,
4945
                                                   Map<String, List<AnnotationToken>> annotationTokens,
4946
                                                   GenericTypeToken componentTypeToken) {
1✔
4947
                            this.typePool = typePool;
1✔
4948
                            this.typeVariableSource = typeVariableSource;
1✔
4949
                            this.typePath = typePath;
1✔
4950
                            this.annotationTokens = annotationTokens;
1✔
4951
                            this.componentTypeToken = componentTypeToken;
1✔
4952
                        }
1✔
4953

4954
                        /**
4955
                         * {@inheritDoc}
4956
                         */
4957
                        public Generic getComponentType() {
4958
                            return componentTypeToken.toGenericType(typePool, typeVariableSource, typePath + COMPONENT_TYPE_PATH, annotationTokens);
1✔
4959
                        }
4960

4961
                        /**
4962
                         * {@inheritDoc}
4963
                         */
4964
                        public AnnotationList getDeclaredAnnotations() {
4965
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
4966
                        }
4967
                    }
4968
                }
4969

4970
                /**
4971
                 * A generic type token for a wildcard that is bound below.
4972
                 */
4973
                @HashCodeAndEqualsPlugin.Enhance
4974
                class ForLowerBoundWildcard implements GenericTypeToken {
4975

4976
                    /**
4977
                     * A token that represents the wildcard's lower bound.
4978
                     */
4979
                    private final GenericTypeToken boundTypeToken;
4980

4981
                    /**
4982
                     * Creates a generic type token for a wildcard that is bound below.
4983
                     *
4984
                     * @param boundTypeToken A token that represents the wildcard's lower bound.
4985
                     */
4986
                    protected ForLowerBoundWildcard(GenericTypeToken boundTypeToken) {
1✔
4987
                        this.boundTypeToken = boundTypeToken;
1✔
4988
                    }
1✔
4989

4990
                    /**
4991
                     * {@inheritDoc}
4992
                     */
4993
                    public Generic toGenericType(TypePool typePool,
4994
                                                 TypeVariableSource typeVariableSource,
4995
                                                 String typePath,
4996
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
4997
                        return new LazyLowerBoundWildcard(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
4998
                    }
4999

5000
                    /**
5001
                     * {@inheritDoc}
5002
                     */
5003
                    public boolean isPrimaryBound(TypePool typePool) {
5004
                        throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
1✔
5005
                    }
5006

5007
                    /**
5008
                     * {@inheritDoc}
5009
                     */
5010
                    public String getTypePathPrefix() {
5011
                        throw new IllegalStateException("A lower bound wildcard cannot be the owner of a nested type: " + this);
1✔
5012
                    }
5013

5014
                    /**
5015
                     * A generic type representation of a lower bound wildcard.
5016
                     */
5017
                    protected static class LazyLowerBoundWildcard extends Generic.OfWildcardType {
5018

5019
                        /**
5020
                         * The type pool to use.
5021
                         */
5022
                        private final TypePool typePool;
5023

5024
                        /**
5025
                         * The type variable source for locating type variables.
5026
                         */
5027
                        private final TypeVariableSource typeVariableSource;
5028

5029
                        /**
5030
                         * This type's type path.
5031
                         */
5032
                        private final String typePath;
5033

5034
                        /**
5035
                         * This type's type annotations.
5036
                         */
5037
                        private final Map<String, List<AnnotationToken>> annotationTokens;
5038

5039
                        /**
5040
                         * A tokenized representation of this wildcard's bound.
5041
                         */
5042
                        private final GenericTypeToken boundTypeToken;
5043

5044
                        /**
5045
                         * Creates a new lazy lower bound wildcard.
5046
                         *
5047
                         * @param typePool           The type pool to use.
5048
                         * @param typeVariableSource The type variable source for locating type variables.
5049
                         * @param typePath           This type's type path.
5050
                         * @param annotationTokens   This type's type annotations.
5051
                         * @param boundTypeToken     A tokenized representation of this wildcard's bound.
5052
                         */
5053
                        protected LazyLowerBoundWildcard(TypePool typePool,
5054
                                                         TypeVariableSource typeVariableSource,
5055
                                                         String typePath,
5056
                                                         Map<String, List<AnnotationToken>> annotationTokens,
5057
                                                         GenericTypeToken boundTypeToken) {
1✔
5058
                            this.typePool = typePool;
1✔
5059
                            this.typeVariableSource = typeVariableSource;
1✔
5060
                            this.typePath = typePath;
1✔
5061
                            this.annotationTokens = annotationTokens;
1✔
5062
                            this.boundTypeToken = boundTypeToken;
1✔
5063
                        }
1✔
5064

5065
                        /**
5066
                         * {@inheritDoc}
5067
                         */
5068
                        public TypeList.Generic getUpperBounds() {
5069
                            return new TypeList.Generic.Explicit(Generic.OfNonGenericType.ForLoadedType.of(Object.class));
1✔
5070
                        }
5071

5072
                        /**
5073
                         * {@inheritDoc}
5074
                         */
5075
                        public TypeList.Generic getLowerBounds() {
5076
                            return new LazyTokenList.ForWildcardBound(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
5077
                        }
5078

5079
                        /**
5080
                         * {@inheritDoc}
5081
                         */
5082
                        public AnnotationList getDeclaredAnnotations() {
5083
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
5084
                        }
5085
                    }
5086
                }
5087

5088
                /**
5089
                 * A generic type token for a wildcard that is bound above.
5090
                 */
5091
                @HashCodeAndEqualsPlugin.Enhance
5092
                class ForUpperBoundWildcard implements GenericTypeToken {
5093

5094
                    /**
5095
                     * A token that represents the wildcard's upper bound.
5096
                     */
5097
                    private final GenericTypeToken boundTypeToken;
5098

5099
                    /**
5100
                     * Creates a generic type token for a wildcard that is bound above.
5101
                     *
5102
                     * @param boundTypeToken A token that represents the wildcard's upper bound.
5103
                     */
5104
                    protected ForUpperBoundWildcard(GenericTypeToken boundTypeToken) {
1✔
5105
                        this.boundTypeToken = boundTypeToken;
1✔
5106
                    }
1✔
5107

5108
                    /**
5109
                     * {@inheritDoc}
5110
                     */
5111
                    public Generic toGenericType(TypePool typePool,
5112
                                                 TypeVariableSource typeVariableSource,
5113
                                                 String typePath,
5114
                                                 Map<String, List<AnnotationToken>> annotationTokens) {
5115
                        return new LazyUpperBoundWildcard(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
5116
                    }
5117

5118
                    /**
5119
                     * {@inheritDoc}
5120
                     */
5121
                    public boolean isPrimaryBound(TypePool typePool) {
5122
                        throw new IllegalStateException("A wildcard type cannot be a type variable bound: " + this);
1✔
5123
                    }
5124

5125
                    /**
5126
                     * {@inheritDoc}
5127
                     */
5128
                    public String getTypePathPrefix() {
5129
                        throw new IllegalStateException("An upper bound wildcard cannot be the owner of a nested type: " + this);
1✔
5130
                    }
5131

5132
                    /**
5133
                     * A generic type representation of a tokenized wildcard with an upper bound.
5134
                     */
5135
                    protected static class LazyUpperBoundWildcard extends Generic.OfWildcardType {
5136

5137
                        /**
5138
                         * The type pool to use.
5139
                         */
5140
                        private final TypePool typePool;
5141

5142
                        /**
5143
                         * The type variable source for locating type variables.
5144
                         */
5145
                        private final TypeVariableSource typeVariableSource;
5146

5147
                        /**
5148
                         * This type's type path.
5149
                         */
5150
                        private final String typePath;
5151

5152
                        /**
5153
                         * This type's type annotations.
5154
                         */
5155
                        private final Map<String, List<AnnotationToken>> annotationTokens;
5156

5157
                        /**
5158
                         * A tokenized representation of this wildcard's bound.
5159
                         */
5160
                        private final GenericTypeToken boundTypeToken;
5161

5162
                        /**
5163
                         * Creates a new lazy upper bound wildcard.
5164
                         *
5165
                         * @param typePool           The type pool to use.
5166
                         * @param typeVariableSource The type variable source for locating type variables.
5167
                         * @param typePath           This type's type path.
5168
                         * @param annotationTokens   This type's type annotations.
5169
                         * @param boundTypeToken     A tokenized representation of this wildcard's bound.
5170
                         */
5171
                        protected LazyUpperBoundWildcard(TypePool typePool,
5172
                                                         TypeVariableSource typeVariableSource,
5173
                                                         String typePath,
5174
                                                         Map<String, List<AnnotationToken>> annotationTokens,
5175
                                                         GenericTypeToken boundTypeToken) {
1✔
5176
                            this.typePool = typePool;
1✔
5177
                            this.typeVariableSource = typeVariableSource;
1✔
5178
                            this.typePath = typePath;
1✔
5179
                            this.annotationTokens = annotationTokens;
1✔
5180
                            this.boundTypeToken = boundTypeToken;
1✔
5181
                        }
1✔
5182

5183
                        /**
5184
                         * {@inheritDoc}
5185
                         */
5186
                        public TypeList.Generic getUpperBounds() {
5187
                            return new LazyTokenList.ForWildcardBound(typePool, typeVariableSource, typePath, annotationTokens, boundTypeToken);
1✔
5188
                        }
5189

5190
                        /**
5191
                         * {@inheritDoc}
5192
                         */
5193
                        public TypeList.Generic getLowerBounds() {
5194
                            return new TypeList.Generic.Empty();
1✔
5195
                        }
5196

5197
                        /**
5198
                         * {@inheritDoc}
5199
                         */
5200
                        public AnnotationList getDeclaredAnnotations() {
5201
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
5202
                        }
5203
                    }
5204
                }
5205

5206
                /**
5207
                 * A generic type token that represents a parameterized type.
5208
                 */
5209
                @HashCodeAndEqualsPlugin.Enhance
5210
                class ForParameterizedType implements GenericTypeToken {
5211

5212
                    /**
5213
                     * The name of the parameterized type's erasure.
5214
                     */
5215
                    private final String name;
5216

5217
                    /**
5218
                     * A list of tokens that represent the parameters of the represented type.
5219
                     */
5220
                    private final List<GenericTypeToken> parameterTypeTokens;
5221

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

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

5243
                    /**
5244
                     * {@inheritDoc}
5245
                     */
5246
                    public boolean isPrimaryBound(TypePool typePool) {
5247
                        return !typePool.describe(name).resolve().isInterface();
1✔
5248
                    }
5249

5250
                    /**
5251
                     * {@inheritDoc}
5252
                     */
5253
                    public String getTypePathPrefix() {
5254
                        return String.valueOf(INNER_CLASS_PATH);
1✔
5255
                    }
5256

5257
                    /**
5258
                     * A generic type token to describe a parameterized type description with a generic owner type.
5259
                     */
5260
                    @HashCodeAndEqualsPlugin.Enhance
5261
                    public static class Nested implements GenericTypeToken {
5262

5263
                        /**
5264
                         * The name of the parameterized type's erasure.
5265
                         */
5266
                        private final String name;
5267

5268
                        /**
5269
                         * A list of tokens that represent the parameters of the represented type.
5270
                         */
5271
                        private final List<GenericTypeToken> parameterTypeTokens;
5272

5273
                        /**
5274
                         * A token that describes the described parameterized type's owner type.
5275
                         */
5276
                        private final GenericTypeToken ownerTypeToken;
5277

5278
                        /**
5279
                         * Creates a type token that represents a parameterized type.
5280
                         *
5281
                         * @param name                The name of the parameterized type's erasure.
5282
                         * @param parameterTypeTokens A list of tokens that represent the parameters of the represented type.
5283
                         * @param ownerTypeToken      A token that describes the described parameterized type's owner type.
5284
                         */
5285
                        protected Nested(String name, List<GenericTypeToken> parameterTypeTokens, GenericTypeToken ownerTypeToken) {
1✔
5286
                            this.name = name;
1✔
5287
                            this.parameterTypeTokens = parameterTypeTokens;
1✔
5288
                            this.ownerTypeToken = ownerTypeToken;
1✔
5289
                        }
1✔
5290

5291
                        /**
5292
                         * {@inheritDoc}
5293
                         */
5294
                        public Generic toGenericType(TypePool typePool,
5295
                                                     TypeVariableSource typeVariableSource,
5296
                                                     String typePath,
5297
                                                     Map<String, List<AnnotationToken>> annotationTokens) {
5298
                            return new LazyParameterizedType(typePool, typeVariableSource, typePath, annotationTokens, name, parameterTypeTokens, ownerTypeToken);
1✔
5299
                        }
5300

5301
                        /**
5302
                         * {@inheritDoc}
5303
                         */
5304
                        public String getTypePathPrefix() {
5305
                            return ownerTypeToken.getTypePathPrefix() + INNER_CLASS_PATH;
×
5306
                        }
5307

5308
                        /**
5309
                         * {@inheritDoc}
5310
                         */
5311
                        public boolean isPrimaryBound(TypePool typePool) {
5312
                            return !typePool.describe(name).resolve().isInterface();
×
5313
                        }
5314

5315
                        /**
5316
                         * A lazy description of a parameterized type with an owner type.
5317
                         */
5318
                        protected static class LazyParameterizedType extends Generic.OfParameterizedType {
5319

5320
                            /**
5321
                             * The type pool that is used for locating a generic type.
5322
                             */
5323
                            private final TypePool typePool;
5324

5325
                            /**
5326
                             * The type variable source to use for resolving type variables.
5327
                             */
5328
                            private final TypeVariableSource typeVariableSource;
5329

5330
                            /**
5331
                             * This type's type path.
5332
                             */
5333
                            private final String typePath;
5334

5335
                            /**
5336
                             * A mapping of type annotations for this type.
5337
                             */
5338
                            private final Map<String, List<AnnotationToken>> annotationTokens;
5339

5340
                            /**
5341
                             * The binary name of this parameterized type's raw type.
5342
                             */
5343
                            private final String name;
5344

5345
                            /**
5346
                             * Tokens that represent this parameterized type's parameters.
5347
                             */
5348
                            private final List<GenericTypeToken> parameterTypeTokens;
5349

5350
                            /**
5351
                             * A token that represents this type's owner type.
5352
                             */
5353
                            private final GenericTypeToken ownerTypeToken;
5354

5355
                            /**
5356
                             * Creates a new lazy parameterized type.
5357
                             *
5358
                             * @param typePool            The type pool that is used for locating a generic type.
5359
                             * @param typeVariableSource  The type variable source to use for resolving type variables.
5360
                             * @param typePath            This type's type path.
5361
                             * @param annotationTokens    A mapping of type annotations for this type.
5362
                             * @param name                The binary name of this parameterized type's raw type.
5363
                             * @param parameterTypeTokens Tokens that represent this parameterized type's parameters.
5364
                             * @param ownerTypeToken      A token that represents this type's owner type.
5365
                             */
5366
                            protected LazyParameterizedType(TypePool typePool,
5367
                                                            TypeVariableSource typeVariableSource,
5368
                                                            String typePath,
5369
                                                            Map<String, List<AnnotationToken>> annotationTokens,
5370
                                                            String name,
5371
                                                            List<GenericTypeToken> parameterTypeTokens,
5372
                                                            GenericTypeToken ownerTypeToken) {
1✔
5373
                                this.typePool = typePool;
1✔
5374
                                this.typeVariableSource = typeVariableSource;
1✔
5375
                                this.typePath = typePath;
1✔
5376
                                this.annotationTokens = annotationTokens;
1✔
5377
                                this.name = name;
1✔
5378
                                this.parameterTypeTokens = parameterTypeTokens;
1✔
5379
                                this.ownerTypeToken = ownerTypeToken;
1✔
5380
                            }
1✔
5381

5382
                            /**
5383
                             * {@inheritDoc}
5384
                             */
5385
                            public TypeDescription asErasure() {
5386
                                return typePool.describe(name).resolve();
1✔
5387
                            }
5388

5389
                            /**
5390
                             * {@inheritDoc}
5391
                             */
5392
                            public TypeList.Generic getTypeArguments() {
5393
                                return new LazyTokenList(typePool, typeVariableSource, typePath + ownerTypeToken.getTypePathPrefix(), annotationTokens, parameterTypeTokens);
1✔
5394
                            }
5395

5396
                            /**
5397
                             * {@inheritDoc}
5398
                             */
5399
                            @MaybeNull
5400
                            public Generic getOwnerType() {
5401
                                return ownerTypeToken.toGenericType(typePool, typeVariableSource, typePath, annotationTokens);
1✔
5402
                            }
5403

5404
                            /**
5405
                             * {@inheritDoc}
5406
                             */
5407
                            public AnnotationList getDeclaredAnnotations() {
5408
                                return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath + ownerTypeToken.getTypePathPrefix()));
1✔
5409
                            }
5410
                        }
5411
                    }
5412

5413
                    /**
5414
                     * A generic type description that represents a parameterized type <b>without</b> an enclosing generic owner type.
5415
                     */
5416
                    protected static class LazyParameterizedType extends Generic.OfParameterizedType {
5417

5418
                        /**
5419
                         * The type pool that is used for locating a generic type.
5420
                         */
5421
                        private final TypePool typePool;
5422

5423
                        /**
5424
                         * The type variable source to use for resolving type variables.
5425
                         */
5426
                        private final TypeVariableSource typeVariableSource;
5427

5428
                        /**
5429
                         * This type's type path.
5430
                         */
5431
                        private final String typePath;
5432

5433
                        /**
5434
                         * A mapping of the represent type's annotation tokens.
5435
                         */
5436
                        private final Map<String, List<AnnotationToken>> annotationTokens;
5437

5438
                        /**
5439
                         * The binary name of the raw type.
5440
                         */
5441
                        private final String name;
5442

5443
                        /**
5444
                         * A list of type tokens representing this type's bounds.
5445
                         */
5446
                        private final List<GenericTypeToken> parameterTypeTokens;
5447

5448
                        /**
5449
                         * Creates a new description of a parameterized type.
5450
                         *
5451
                         * @param typePool            The type pool that is used for locating a generic type.
5452
                         * @param typeVariableSource  The type variable source to use for resolving type variables.
5453
                         * @param typePath            This type's type path.
5454
                         * @param annotationTokens    A mapping of the represent type's annotation tokens,
5455
                         * @param name                The binary name of the raw type.
5456
                         * @param parameterTypeTokens A list of type tokens representing this type's bounds.
5457
                         */
5458
                        protected LazyParameterizedType(TypePool typePool,
5459
                                                        TypeVariableSource typeVariableSource,
5460
                                                        String typePath,
5461
                                                        Map<String, List<AnnotationToken>> annotationTokens,
5462
                                                        String name,
5463
                                                        List<GenericTypeToken> parameterTypeTokens) {
1✔
5464
                            this.typePool = typePool;
1✔
5465
                            this.typeVariableSource = typeVariableSource;
1✔
5466
                            this.typePath = typePath;
1✔
5467
                            this.annotationTokens = annotationTokens;
1✔
5468
                            this.name = name;
1✔
5469
                            this.parameterTypeTokens = parameterTypeTokens;
1✔
5470
                        }
1✔
5471

5472
                        /**
5473
                         * {@inheritDoc}
5474
                         */
5475
                        public TypeDescription asErasure() {
5476
                            return typePool.describe(name).resolve();
1✔
5477
                        }
5478

5479
                        /**
5480
                         * {@inheritDoc}
5481
                         */
5482
                        public TypeList.Generic getTypeArguments() {
5483
                            TypeDescription typeDescription = typePool.describe(name).resolve();
1✔
5484
                            if (typeDescription.getTypeVariables().size() != parameterTypeTokens.size()) {
1✔
5485
                                throw new MalformedParameterizedTypeException();
1✔
5486
                            }
5487
                            return new LazyTokenList(typePool, typeVariableSource, typePath, annotationTokens, parameterTypeTokens);
1✔
5488
                        }
5489

5490
                        /**
5491
                         * {@inheritDoc}
5492
                         */
5493
                        @MaybeNull
5494
                        public Generic getOwnerType() {
5495
                            TypeDescription typeDescription = typePool.describe(name).resolve();
1✔
5496
                            if (typeDescription.getTypeVariables().size() != parameterTypeTokens.size()) {
1✔
5497
                                throw new MalformedParameterizedTypeException();
1✔
5498
                            }
5499
                            TypeDescription ownerType = typeDescription.getEnclosingType();
1✔
5500
                            return ownerType == null
1✔
5501
                                    ? Generic.UNDEFINED
5502
                                    : ownerType.asGenericType();
1✔
5503
                        }
5504

5505
                        /**
5506
                         * {@inheritDoc}
5507
                         */
5508
                        public AnnotationList getDeclaredAnnotations() {
5509
                            return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens.get(typePath));
1✔
5510
                        }
5511
                    }
5512
                }
5513

5514
                /**
5515
                 * A lazy list of type tokens.
5516
                 */
5517
                class LazyTokenList extends TypeList.Generic.AbstractBase {
5518

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

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

5529
                    /**
5530
                     * The represented types' type path to which an index step is added upon resolution.
5531
                     */
5532
                    private final String typePath;
5533

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

5539
                    /**
5540
                     * A list of type tokens this list represents.
5541
                     */
5542
                    private final List<GenericTypeToken> genericTypeTokens;
5543

5544
                    /**
5545
                     * Creates a new type list that represents a list of tokenized types.
5546
                     *
5547
                     * @param typePool           The type pool that is used for locating a generic type.
5548
                     * @param typeVariableSource The type variable source to use for resolving type variables.
5549
                     * @param typePath           The represented types' type path to which an index step is added upon resolution.
5550
                     * @param annotationTokens   A mapping of the represent types' annotation tokens,
5551
                     * @param genericTypeTokens  A list of type tokens this list represents.
5552
                     */
5553
                    protected LazyTokenList(TypePool typePool,
5554
                                            TypeVariableSource typeVariableSource,
5555
                                            String typePath,
5556
                                            Map<String, List<AnnotationToken>> annotationTokens,
5557
                                            List<GenericTypeToken> genericTypeTokens) {
1✔
5558
                        this.typePool = typePool;
1✔
5559
                        this.typeVariableSource = typeVariableSource;
1✔
5560
                        this.typePath = typePath;
1✔
5561
                        this.annotationTokens = annotationTokens;
1✔
5562
                        this.genericTypeTokens = genericTypeTokens;
1✔
5563
                    }
1✔
5564

5565
                    /**
5566
                     * {@inheritDoc}
5567
                     */
5568
                    public Generic get(int index) {
5569
                        return genericTypeTokens.get(index).toGenericType(typePool, typeVariableSource, typePath + index + INDEXED_TYPE_DELIMITER, annotationTokens);
1✔
5570
                    }
5571

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

5579
                    /**
5580
                     * A generic type description representing a tokenized wildcard bound.
5581
                     */
5582
                    protected static class ForWildcardBound extends TypeList.Generic.AbstractBase {
5583

5584
                        /**
5585
                         * The type pool that is used for locating a generic type.
5586
                         */
5587
                        private final TypePool typePool;
5588

5589
                        /**
5590
                         * The type variable source to use for resolving type variables.
5591
                         */
5592
                        private final TypeVariableSource typeVariableSource;
5593

5594
                        /**
5595
                         * The represented types' type path to which a wildcard step is added upon resolution.
5596
                         */
5597
                        private final String typePath;
5598

5599
                        /**
5600
                         * A mapping of the represent types' annotation tokens.
5601
                         */
5602
                        private final Map<String, List<AnnotationToken>> annotationTokens;
5603

5604
                        /**
5605
                         * A token representing the wildcard's bound.
5606
                         */
5607
                        private final GenericTypeToken genericTypeToken;
5608

5609
                        /**
5610
                         * @param typePool           The type pool that is used for locating a generic type.
5611
                         * @param typeVariableSource The type variable source to use for resolving type variables.
5612
                         * @param typePath           The represented types' type path to which a wildcard step is added upon resolution.
5613
                         * @param annotationTokens   A mapping of the represent types' annotation tokens,
5614
                         * @param genericTypeToken   A token representing the wildcard's bound.
5615
                         */
5616
                        protected ForWildcardBound(TypePool typePool,
5617
                                                   TypeVariableSource typeVariableSource,
5618
                                                   String typePath,
5619
                                                   Map<String, List<AnnotationToken>> annotationTokens,
5620
                                                   GenericTypeToken genericTypeToken) {
1✔
5621
                            this.typePool = typePool;
1✔
5622
                            this.typeVariableSource = typeVariableSource;
1✔
5623
                            this.typePath = typePath;
1✔
5624
                            this.annotationTokens = annotationTokens;
1✔
5625
                            this.genericTypeToken = genericTypeToken;
1✔
5626
                        }
1✔
5627

5628
                        /**
5629
                         * {@inheritDoc}
5630
                         */
5631
                        public Generic get(int index) {
5632
                            if (index == 0) {
1✔
5633
                                return genericTypeToken.toGenericType(typePool, typeVariableSource, typePath + WILDCARD_TYPE_PATH, annotationTokens);
1✔
5634
                            } else {
5635
                                throw new IndexOutOfBoundsException("index = " + index);
×
5636
                            }
5637
                        }
5638

5639
                        /**
5640
                         * {@inheritDoc}
5641
                         */
5642
                        public int size() {
5643
                            return 1;
1✔
5644
                        }
5645
                    }
5646
                }
5647
            }
5648

5649
            /**
5650
             * A token for representing collected data on an annotation.
5651
             */
5652
            @HashCodeAndEqualsPlugin.Enhance
5653
            protected static class AnnotationToken {
5654

5655
                /**
5656
                 * The descriptor of the represented annotation.
5657
                 */
5658
                private final String descriptor;
5659

5660
                /**
5661
                 * A map of annotation value names to their value representations.
5662
                 */
5663
                private final Map<String, AnnotationValue<?, ?>> values;
5664

5665
                /**
5666
                 * Creates a new annotation token.
5667
                 *
5668
                 * @param descriptor The descriptor of the represented annotation.
5669
                 * @param values     A map of annotation value names to their value representations.
5670
                 */
5671
                protected AnnotationToken(String descriptor, Map<String, AnnotationValue<?, ?>> values) {
1✔
5672
                    this.descriptor = descriptor;
1✔
5673
                    this.values = values;
1✔
5674
                }
1✔
5675

5676
                /**
5677
                 * Returns the annotation type's binary name.
5678
                 *
5679
                 * @return The annotation type's binary name.
5680
                 */
5681
                protected String getBinaryName() {
5682
                    return descriptor.substring(1, descriptor.length() - 1).replace('/', '.');
1✔
5683
                }
5684

5685
                /**
5686
                 * Transforms this token into an annotation description.
5687
                 *
5688
                 * @param typePool The type pool to be used for looking up linked types.
5689
                 * @return An optional description of this annotation's token.
5690
                 */
5691
                private Resolution toAnnotationDescription(TypePool typePool) {
5692
                    TypePool.Resolution resolution = typePool.describe(getBinaryName());
1✔
5693
                    return resolution.isResolved()
1✔
5694
                            ? new Resolution.Simple(new LazyAnnotationDescription(typePool, resolution.resolve(), values))
1✔
5695
                            : new Resolution.Illegal(getBinaryName());
1✔
5696
                }
5697

5698
                /**
5699
                 * A resolution for an annotation tokens. Any annotation is suppressed if its type is not available.
5700
                 * This conforms to the handling of the Java reflection API.
5701
                 */
5702
                protected interface Resolution {
5703

5704
                    /**
5705
                     * Returns {@code true} if the represented annotation could be resolved.
5706
                     *
5707
                     * @return {@code true} if the represented annotation could be resolved.
5708
                     */
5709
                    boolean isResolved();
5710

5711
                    /**
5712
                     * Returns the resolved annotation. This method throws an exception if this instance is not resolved.
5713
                     *
5714
                     * @return The resolved annotation. This method throws an exception if this instance is not resolved.
5715
                     */
5716
                    AnnotationDescription resolve();
5717

5718
                    /**
5719
                     * A simple resolved annotation.
5720
                     */
5721
                    @HashCodeAndEqualsPlugin.Enhance
5722
                    class Simple implements Resolution {
5723

5724
                        /**
5725
                         * The represented annotation description.
5726
                         */
5727
                        private final AnnotationDescription annotationDescription;
5728

5729
                        /**
5730
                         * Creates a new simple resolution.
5731
                         *
5732
                         * @param annotationDescription The represented annotation description.
5733
                         */
5734
                        protected Simple(AnnotationDescription annotationDescription) {
1✔
5735
                            this.annotationDescription = annotationDescription;
1✔
5736
                        }
1✔
5737

5738
                        /**
5739
                         * {@inheritDoc}
5740
                         */
5741
                        public boolean isResolved() {
5742
                            return true;
1✔
5743
                        }
5744

5745
                        /**
5746
                         * {@inheritDoc}
5747
                         */
5748
                        public AnnotationDescription resolve() {
5749
                            return annotationDescription;
1✔
5750
                        }
5751
                    }
5752

5753
                    /**
5754
                     * An illegal resolution.
5755
                     */
5756
                    @HashCodeAndEqualsPlugin.Enhance
5757
                    class Illegal implements Resolution {
5758

5759
                        /**
5760
                         * The annotation's binary type name.
5761
                         */
5762
                        private final String annotationType;
5763

5764
                        /**
5765
                         * Creates a new illegal resolution.
5766
                         *
5767
                         * @param annotationType The annotation's binary type name.
5768
                         */
5769
                        public Illegal(String annotationType) {
1✔
5770
                            this.annotationType = annotationType;
1✔
5771
                        }
1✔
5772

5773
                        /**
5774
                         * {@inheritDoc}
5775
                         */
5776
                        public boolean isResolved() {
5777
                            return false;
1✔
5778
                        }
5779

5780
                        /**
5781
                         * {@inheritDoc}
5782
                         */
5783
                        public AnnotationDescription resolve() {
5784
                            throw new IllegalStateException("Annotation type is not available: " + annotationType);
1✔
5785
                        }
5786
                    }
5787
                }
5788
            }
5789

5790
            /**
5791
             * A token for representing collected data on a field.
5792
             */
5793
            @HashCodeAndEqualsPlugin.Enhance
5794
            protected static class FieldToken {
5795

5796
                /**
5797
                 * The name of the field.
5798
                 */
5799
                private final String name;
5800

5801
                /**
5802
                 * The modifiers of the represented field.
5803
                 */
5804
                private final int modifiers;
5805

5806
                /**
5807
                 * The descriptor of the field.
5808
                 */
5809
                private final String descriptor;
5810

5811
                /**
5812
                 * The field's generic signature as found in the class file or {@code null} if the field is not generic.
5813
                 */
5814
                @UnknownNull
5815
                private final String genericSignature;
5816

5817
                /**
5818
                 * The resolution of this field's generic type.
5819
                 */
5820
                private final GenericTypeToken.Resolution.ForField signatureResolution;
5821

5822
                /**
5823
                 * A mapping of the field type's type annotation tokens.
5824
                 */
5825
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
5826

5827
                /**
5828
                 * A list of annotation tokens representing the annotations of the represented field.
5829
                 */
5830
                private final List<AnnotationToken> annotationTokens;
5831

5832
                /**
5833
                 * Creates a new field token.
5834
                 *
5835
                 * @param name                 The name of the field.
5836
                 * @param modifiers            The modifiers of the represented field.
5837
                 * @param descriptor           The descriptor of the field.
5838
                 * @param genericSignature     The field's generic signature as found in the class file or {@code null} if the field is not generic.
5839
                 * @param typeAnnotationTokens A mapping of the field type's type annotation tokens.
5840
                 * @param annotationTokens     A list of annotation tokens representing the annotations of the represented field.
5841
                 */
5842
                protected FieldToken(String name,
5843
                                     int modifiers,
5844
                                     String descriptor,
5845
                                     @MaybeNull String genericSignature,
5846
                                     Map<String, List<AnnotationToken>> typeAnnotationTokens,
5847
                                     List<AnnotationToken> annotationTokens) {
1✔
5848
                    this.modifiers = modifiers & ~Opcodes.ACC_DEPRECATED;
1✔
5849
                    this.name = name;
1✔
5850
                    this.descriptor = descriptor;
1✔
5851
                    this.genericSignature = genericSignature;
1✔
5852
                    signatureResolution = RAW_TYPES
1✔
5853
                            ? GenericTypeToken.Resolution.Raw.INSTANCE
5854
                            : GenericTypeExtractor.ForSignature.OfField.extract(genericSignature);
1✔
5855
                    this.typeAnnotationTokens = typeAnnotationTokens;
1✔
5856
                    this.annotationTokens = annotationTokens;
1✔
5857
                }
1✔
5858

5859
                /**
5860
                 * Transforms this token into a lazy field description.
5861
                 *
5862
                 * @param lazyTypeDescription The lazy type description to attach this field description to.
5863
                 * @return A field description resembling this field token.
5864
                 */
5865
                private LazyFieldDescription toFieldDescription(LazyTypeDescription lazyTypeDescription) {
5866
                    return lazyTypeDescription.new LazyFieldDescription(name,
1✔
5867
                            modifiers,
5868
                            descriptor,
5869
                            genericSignature,
5870
                            signatureResolution,
5871
                            typeAnnotationTokens,
5872
                            annotationTokens);
5873
                }
5874
            }
5875

5876
            /**
5877
             * A token for representing collected data on a method.
5878
             */
5879
            @HashCodeAndEqualsPlugin.Enhance
5880
            protected static class MethodToken {
5881

5882
                /**
5883
                 * The internal name of the represented method.
5884
                 */
5885
                private final String name;
5886

5887
                /**
5888
                 * The modifiers of the represented method.
5889
                 */
5890
                private final int modifiers;
5891

5892
                /**
5893
                 * The descriptor of the represented method.
5894
                 */
5895
                private final String descriptor;
5896

5897
                /**
5898
                 * The methods's generic signature as found in the class file or {@code null} if the method is not generic.
5899
                 */
5900
                @UnknownNull
5901
                private final String genericSignature;
5902

5903
                /**
5904
                 * The generic type resolution of this method.
5905
                 */
5906
                private final GenericTypeToken.Resolution.ForMethod signatureResolution;
5907

5908
                /**
5909
                 * An array of internal names of the exceptions of the represented method or {@code null} if there
5910
                 * are no such exceptions.
5911
                 */
5912
                @MaybeNull
5913
                private final String[] exceptionName;
5914

5915
                /**
5916
                 * A mapping of the type variables' type annotation tokens by their indices.
5917
                 */
5918
                private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
5919

5920
                /**
5921
                 * A mapping of the type variables' type bounds' type annotation tokens by their indices and each variable's index.
5922
                 */
5923
                private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens;
5924

5925
                /**
5926
                 * A mapping of the return type's type variable tokens.
5927
                 */
5928
                private final Map<String, List<AnnotationToken>> returnTypeAnnotationTokens;
5929

5930
                /**
5931
                 * A mapping of the parameter types' type annotation tokens by their indices.
5932
                 */
5933
                private final Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens;
5934

5935
                /**
5936
                 * A mapping of the exception types' type annotation tokens by their indices.
5937
                 */
5938
                private final Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens;
5939

5940
                /**
5941
                 * A mapping of the receiver type's annotation tokens.
5942
                 */
5943
                private final Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens;
5944

5945
                /**
5946
                 * A list of annotation tokens that are present on the represented method.
5947
                 */
5948
                private final List<AnnotationToken> annotationTokens;
5949

5950
                /**
5951
                 * A map of parameter indices to tokens that represent their annotations.
5952
                 */
5953
                private final Map<Integer, List<AnnotationToken>> parameterAnnotationTokens;
5954

5955
                /**
5956
                 * A list of tokens describing meta data of the method's parameters.
5957
                 */
5958
                private final List<ParameterToken> parameterTokens;
5959

5960
                /**
5961
                 * The default value of this method or {@code null} if there is no such value.
5962
                 */
5963
                @UnknownNull
5964
                private final AnnotationValue<?, ?> defaultValue;
5965

5966
                /**
5967
                 * Creates a new method token.
5968
                 *
5969
                 * @param name                              The name of the method.
5970
                 * @param modifiers                         The modifiers of the represented method.
5971
                 * @param descriptor                        The descriptor of the represented method.
5972
                 * @param genericSignature                  The methods's generic signature as found in the class file or {@code null} if the method is not generic.
5973
                 * @param exceptionName                     An array of internal names of the exceptions of the represented method or {@code null} if
5974
                 *                                          there are no such exceptions.
5975
                 * @param typeVariableAnnotationTokens      A mapping of the type variables' type annotation tokens by their indices.
5976
                 * @param typeVariableBoundAnnotationTokens A mapping of the type variables' type bounds' type annotation tokens by their
5977
                 *                                          index and each variable's index.
5978
                 * @param returnTypeAnnotationTokens        A mapping of the return type's type variable tokens.
5979
                 * @param parameterTypeAnnotationTokens     A mapping of the parameter types' type annotation tokens by their indices.
5980
                 * @param exceptionTypeAnnotationTokens     A mapping of the exception types' type annotation tokens by their indices.
5981
                 * @param receiverTypeAnnotationTokens      A mapping of the receiver type's annotation tokens.
5982
                 * @param annotationTokens                  A list of annotation tokens that are present on the represented method.
5983
                 * @param parameterAnnotationTokens         A map of parameter indices to tokens that represent their annotations.
5984
                 * @param parameterTokens                   A list of tokens describing meta data of the method's parameters.
5985
                 * @param defaultValue                      The default value of this method or {@code null} if there is no such value.
5986
                 */
5987
                protected MethodToken(String name,
5988
                                      int modifiers,
5989
                                      String descriptor,
5990
                                      @MaybeNull String genericSignature,
5991
                                      @MaybeNull String[] exceptionName,
5992
                                      Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
5993
                                      Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens,
5994
                                      Map<String, List<AnnotationToken>> returnTypeAnnotationTokens,
5995
                                      Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens,
5996
                                      Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens,
5997
                                      Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens,
5998
                                      List<AnnotationToken> annotationTokens,
5999
                                      Map<Integer, List<AnnotationToken>> parameterAnnotationTokens,
6000
                                      List<ParameterToken> parameterTokens,
6001
                                      @MaybeNull AnnotationValue<?, ?> defaultValue) {
1✔
6002
                    this.modifiers = modifiers & ~Opcodes.ACC_DEPRECATED;
1✔
6003
                    this.name = name;
1✔
6004
                    this.descriptor = descriptor;
1✔
6005
                    this.genericSignature = genericSignature;
1✔
6006
                    signatureResolution = RAW_TYPES
1✔
6007
                            ? GenericTypeToken.Resolution.Raw.INSTANCE
6008
                            : GenericTypeExtractor.ForSignature.OfMethod.extract(genericSignature);
1✔
6009
                    this.exceptionName = exceptionName;
1✔
6010
                    this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
1✔
6011
                    this.typeVariableBoundAnnotationTokens = typeVariableBoundAnnotationTokens;
1✔
6012
                    this.returnTypeAnnotationTokens = returnTypeAnnotationTokens;
1✔
6013
                    this.parameterTypeAnnotationTokens = parameterTypeAnnotationTokens;
1✔
6014
                    this.exceptionTypeAnnotationTokens = exceptionTypeAnnotationTokens;
1✔
6015
                    this.receiverTypeAnnotationTokens = receiverTypeAnnotationTokens;
1✔
6016
                    this.annotationTokens = annotationTokens;
1✔
6017
                    this.parameterAnnotationTokens = parameterAnnotationTokens;
1✔
6018
                    this.parameterTokens = parameterTokens;
1✔
6019
                    this.defaultValue = defaultValue;
1✔
6020
                }
1✔
6021

6022
                /**
6023
                 * Transforms this method token to a method description that is attached to a lazy type description.
6024
                 *
6025
                 * @param lazyTypeDescription The lazy type description to attach this method description to.
6026
                 * @return A method description representing this method token.
6027
                 */
6028
                private MethodDescription.InDefinedShape toMethodDescription(LazyTypeDescription lazyTypeDescription) {
6029
                    return lazyTypeDescription.new LazyMethodDescription(name,
1✔
6030
                            modifiers,
6031
                            descriptor,
6032
                            genericSignature,
6033
                            signatureResolution,
6034
                            exceptionName,
6035
                            typeVariableAnnotationTokens,
6036
                            typeVariableBoundAnnotationTokens,
6037
                            returnTypeAnnotationTokens,
6038
                            parameterTypeAnnotationTokens,
6039
                            exceptionTypeAnnotationTokens,
6040
                            receiverTypeAnnotationTokens,
6041
                            annotationTokens,
6042
                            parameterAnnotationTokens,
6043
                            parameterTokens,
6044
                            defaultValue);
6045
                }
6046

6047
                /**
6048
                 * A token representing a method's parameter.
6049
                 */
6050
                @HashCodeAndEqualsPlugin.Enhance
6051
                protected static class ParameterToken {
6052

6053
                    /**
6054
                     * Donates an unknown name of a parameter.
6055
                     */
6056
                    @AlwaysNull
6057
                    protected static final String NO_NAME = null;
1✔
6058

6059
                    /**
6060
                     * Donates an unknown modifier of a parameter.
6061
                     */
6062
                    @AlwaysNull
6063
                    protected static final Integer NO_MODIFIERS = null;
1✔
6064

6065
                    /**
6066
                     * The name of the parameter or {@code null} if no explicit name for this parameter is known.
6067
                     */
6068
                    @MaybeNull
6069
                    @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
6070
                    private final String name;
6071

6072
                    /**
6073
                     * The modifiers of the parameter or {@code null} if no modifiers are known for this parameter.
6074
                     */
6075
                    @MaybeNull
6076
                    @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
6077
                    private final Integer modifiers;
6078

6079
                    /**
6080
                     * Creates a parameter token for a parameter without an explicit name and without specific modifiers.
6081
                     */
6082
                    protected ParameterToken() {
6083
                        this(NO_NAME);
1✔
6084
                    }
1✔
6085

6086
                    /**
6087
                     * Creates a parameter token for a parameter with an explicit name and without specific modifiers.
6088
                     *
6089
                     * @param name The name of the parameter.
6090
                     */
6091
                    protected ParameterToken(@MaybeNull String name) {
6092
                        this(name, NO_MODIFIERS);
1✔
6093
                    }
1✔
6094

6095
                    /**
6096
                     * Creates a parameter token for a parameter with an explicit name and with specific modifiers.
6097
                     *
6098
                     * @param name      The name of the parameter.
6099
                     * @param modifiers The modifiers of the parameter.
6100
                     */
6101
                    protected ParameterToken(@MaybeNull String name, @MaybeNull Integer modifiers) {
1✔
6102
                        this.name = name;
1✔
6103
                        this.modifiers = modifiers;
1✔
6104
                    }
1✔
6105

6106
                    /**
6107
                     * Returns the name of the parameter or {@code null} if there is no such name.
6108
                     *
6109
                     * @return The name of the parameter or {@code null} if there is no such name.
6110
                     */
6111
                    @MaybeNull
6112
                    protected String getName() {
6113
                        return name;
1✔
6114
                    }
6115

6116
                    /**
6117
                     * Returns the modifiers of the parameter or {@code null} if no modifiers are known.
6118
                     *
6119
                     * @return The modifiers of the parameter or {@code null} if no modifiers are known.
6120
                     */
6121
                    @MaybeNull
6122
                    protected Integer getModifiers() {
6123
                        return modifiers;
1✔
6124
                    }
6125
                }
6126
            }
6127

6128
            /**
6129
             * A token representing a record component.
6130
             */
6131
            @HashCodeAndEqualsPlugin.Enhance
6132
            protected static class RecordComponentToken {
6133

6134
                /**
6135
                 * The record component's name.
6136
                 */
6137
                private final String name;
6138

6139
                /**
6140
                 * The record component's descriptor.
6141
                 */
6142
                private final String descriptor;
6143

6144
                /**
6145
                 * The record component's generic signature or {@code null} if it is non-generic.
6146
                 */
6147
                @UnknownNull
6148
                private final String genericSignature;
6149

6150
                /**
6151
                 * The record component's signature resolution.
6152
                 */
6153
                private final GenericTypeToken.Resolution.ForRecordComponent signatureResolution;
6154

6155
                /**
6156
                 * A mapping of the record component's type annotations.
6157
                 */
6158
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
6159

6160
                /**
6161
                 * A list of the record component's annotations.
6162
                 */
6163
                private final List<AnnotationToken> annotationTokens;
6164

6165
                /**
6166
                 * Creates a new record component token.
6167
                 *
6168
                 * @param name                 The record component's name.
6169
                 * @param descriptor           The record component's descriptor.
6170
                 * @param genericSignature     The record component's generic signature or {@code null} if it is non-generic.
6171
                 * @param typeAnnotationTokens A mapping of the record component's type annotations.
6172
                 * @param annotationTokens     A list of the record component's annotations.
6173
                 */
6174
                protected RecordComponentToken(String name,
6175
                                               String descriptor,
6176
                                               @MaybeNull String genericSignature,
6177
                                               Map<String, List<AnnotationToken>> typeAnnotationTokens,
6178
                                               List<AnnotationToken> annotationTokens) {
×
6179
                    this.name = name;
×
6180
                    this.descriptor = descriptor;
×
6181
                    this.genericSignature = genericSignature;
×
6182
                    signatureResolution = RAW_TYPES
×
6183
                            ? GenericTypeToken.Resolution.Raw.INSTANCE
6184
                            : GenericTypeExtractor.ForSignature.OfRecordComponent.extract(genericSignature);
×
6185
                    this.typeAnnotationTokens = typeAnnotationTokens;
×
6186
                    this.annotationTokens = annotationTokens;
×
6187
                }
×
6188

6189
                /**
6190
                 * Transforms this record component token to a record component description that is attached to a lazy type description.
6191
                 *
6192
                 * @param lazyTypeDescription The lazy type description to attach this record component description to.
6193
                 * @return A record component description representing this record component token.
6194
                 */
6195
                private RecordComponentDescription.InDefinedShape toRecordComponentDescription(LazyTypeDescription lazyTypeDescription) {
6196
                    return lazyTypeDescription.new LazyRecordComponentDescription(name,
×
6197
                            descriptor,
6198
                            genericSignature,
6199
                            signatureResolution,
6200
                            typeAnnotationTokens,
6201
                            annotationTokens);
6202
                }
6203
            }
6204

6205
            /**
6206
             * A lazy description of an annotation that looks up types from a type pool when required.
6207
             */
6208
            private static class LazyAnnotationDescription extends AnnotationDescription.AbstractBase {
6209

6210
                /**
6211
                 * The type pool for looking up type references.
6212
                 */
6213
                protected final TypePool typePool;
6214

6215
                /**
6216
                 * The type of this annotation.
6217
                 */
6218
                private final TypeDescription annotationType;
6219

6220
                /**
6221
                 * A map of annotation values by their property name.
6222
                 */
6223
                protected final Map<String, AnnotationValue<?, ?>> values;
6224

6225
                /**
6226
                 * Creates a new lazy annotation description.
6227
                 *
6228
                 * @param typePool       The type pool to be used for looking up linked types.
6229
                 * @param annotationType The annotation's type.
6230
                 * @param values         A map of annotation value names to their value representations.
6231
                 */
6232
                private LazyAnnotationDescription(TypePool typePool, TypeDescription annotationType, Map<String, AnnotationValue<?, ?>> values) {
1✔
6233
                    this.typePool = typePool;
1✔
6234
                    this.annotationType = annotationType;
1✔
6235
                    this.values = values;
1✔
6236
                }
1✔
6237

6238
                /**
6239
                 * Represents a list of annotation tokens in form of a list of lazy type annotations. Any annotation with
6240
                 * a type that cannot be loaded from the type pool is ignored and not included in the list. If the provided
6241
                 * {@code tokens} are {@code null}, an empty list is returned.
6242
                 *
6243
                 * @param typePool The type pool to be used for looking up linked types.
6244
                 * @param tokens   The tokens to represent in the list.
6245
                 * @return A list of the loadable annotations.
6246
                 */
6247
                protected static AnnotationList asListOfNullable(TypePool typePool, @MaybeNull List<? extends AnnotationToken> tokens) {
6248
                    return tokens == null
1✔
6249
                            ? new AnnotationList.Empty()
6250
                            : asList(typePool, tokens);
1✔
6251
                }
6252

6253
                /**
6254
                 * Represents a list of annotation tokens in form of a list of lazy type annotations. Any annotation with
6255
                 * a type that cannot be loaded from the type pool is ignored and not included in the list.
6256
                 *
6257
                 * @param typePool The type pool to be used for looking up linked types.
6258
                 * @param tokens   The tokens to represent in the list.
6259
                 * @return A list of the represented annotations.
6260
                 */
6261
                protected static AnnotationList asList(TypePool typePool, List<? extends AnnotationToken> tokens) {
6262
                    List<AnnotationDescription> annotationDescriptions = new ArrayList<AnnotationDescription>(tokens.size());
1✔
6263
                    for (AnnotationToken token : tokens) {
1✔
6264
                        AnnotationToken.Resolution resolution = token.toAnnotationDescription(typePool);
1✔
6265
                        if (resolution.isResolved() && resolution.resolve().getAnnotationType().isAnnotation()) {
1✔
6266
                            annotationDescriptions.add(resolution.resolve());
1✔
6267
                        }
6268
                    }
1✔
6269
                    return new UnresolvedAnnotationList(annotationDescriptions, tokens);
1✔
6270
                }
6271

6272
                /**
6273
                 * {@inheritDoc}
6274
                 */
6275
                public AnnotationValue<?, ?> getValue(MethodDescription.InDefinedShape property) {
6276
                    if (!property.getDeclaringType().asErasure().equals(annotationType)) {
1✔
6277
                        throw new IllegalArgumentException(property + " is not declared by " + getAnnotationType());
1✔
6278
                    }
6279
                    AnnotationValue<?, ?> annotationValue = values.get(property.getName());
1✔
6280
                    if (annotationValue != null) {
1✔
6281
                        return annotationValue.filter(property);
1✔
6282
                    } else {
6283
                        annotationValue = getAnnotationType().getDeclaredMethods().filter(is(property)).getOnly().getDefaultValue();
1✔
6284
                    }
6285
                    return annotationValue == null
1✔
6286
                            ? new AnnotationValue.ForMissingValue<Void, Void>(annotationType, property.getName())
1✔
6287
                            : annotationValue;
6288
                }
6289

6290
                /**
6291
                 * {@inheritDoc}
6292
                 */
6293
                public TypeDescription getAnnotationType() {
6294
                    return annotationType;
1✔
6295
                }
6296

6297
                /**
6298
                 * {@inheritDoc}
6299
                 */
6300
                public <T extends Annotation> Loadable<T> prepare(Class<T> annotationType) {
6301
                    if (!this.annotationType.represents(annotationType)) {
1✔
6302
                        throw new IllegalArgumentException(annotationType + " does not represent " + this.annotationType);
1✔
6303
                    }
6304
                    return new Loadable<T>(typePool, annotationType, values);
1✔
6305
                }
6306

6307
                /**
6308
                 * A loadable version of a lazy annotation description.
6309
                 *
6310
                 * @param <S> The annotation type.
6311
                 */
6312
                private static class Loadable<S extends Annotation> extends LazyAnnotationDescription implements AnnotationDescription.Loadable<S> {
6313

6314
                    /**
6315
                     * The loaded annotation type.
6316
                     */
6317
                    private final Class<S> annotationType;
6318

6319
                    /**
6320
                     * Creates a new loadable version of a lazy annotation.
6321
                     *
6322
                     * @param typePool       The type pool to be used for looking up linked types.
6323
                     * @param annotationType The annotation's loaded type.
6324
                     * @param values         A map of annotation value names to their value representations.
6325
                     */
6326
                    private Loadable(TypePool typePool, Class<S> annotationType, Map<String, AnnotationValue<?, ?>> values) {
6327
                        super(typePool, ForLoadedType.of(annotationType), values);
1✔
6328
                        this.annotationType = annotationType;
1✔
6329
                    }
1✔
6330

6331
                    /**
6332
                     * {@inheritDoc}
6333
                     */
6334
                    public S load() {
6335
                        return AnnotationInvocationHandler.of(annotationType.getClassLoader(), annotationType, values);
1✔
6336
                    }
6337
                }
6338

6339
                /**
6340
                 * A list of annotations which allows for resolving the names of the annotations even if the annotations cannot be resolved.
6341
                 */
6342
                private static class UnresolvedAnnotationList extends AnnotationList.Explicit {
6343

6344
                    /**
6345
                     * The list of represented annotation tokens.
6346
                     */
6347
                    private final List<? extends AnnotationToken> tokens;
6348

6349
                    /**
6350
                     * Creates a list of unresolved annotations.
6351
                     *
6352
                     * @param annotationDescriptions The list of represented annotation descriptions.
6353
                     * @param tokens                 The list of represented annotation tokens.
6354
                     */
6355
                    private UnresolvedAnnotationList(List<? extends AnnotationDescription> annotationDescriptions, List<? extends AnnotationToken> tokens) {
6356
                        super(annotationDescriptions);
1✔
6357
                        this.tokens = tokens;
1✔
6358
                    }
1✔
6359

6360
                    @Override
6361
                    public List<String> asTypeNames() {
6362
                        List<String> typeNames = new ArrayList<String>(tokens.size());
×
6363
                        for (AnnotationToken token : tokens) {
×
6364
                            typeNames.add(token.getBinaryName());
×
6365
                        }
×
6366
                        return typeNames;
×
6367
                    }
6368
                }
6369
            }
6370

6371
            /**
6372
             * A proxy for a lazy annotation value.
6373
             *
6374
             * @param <U> The represented unloaded type.
6375
             * @param <V> The represented loaded type.
6376
             */
6377
            private abstract static class LazyAnnotationValue<U, V> extends AnnotationValue.AbstractBase<U, V> {
6378

6379
                /**
6380
                 * Resolves the actual annotation value.
6381
                 *
6382
                 * @return The actual annotation value.
6383
                 */
6384
                protected abstract AnnotationValue<U, V> doResolve();
6385

6386
                /**
6387
                 * {@inheritDoc}
6388
                 */
6389
                public State getState() {
6390
                    return doResolve().getState();
×
6391
                }
6392

6393
                /**
6394
                 * {@inheritDoc}
6395
                 */
6396
                public AnnotationValue<U, V> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
6397
                    return doResolve().filter(property, typeDefinition);
1✔
6398
                }
6399

6400
                /**
6401
                 * {@inheritDoc}
6402
                 */
6403
                public U resolve() {
6404
                    return doResolve().resolve();
1✔
6405
                }
6406

6407
                /**
6408
                 * {@inheritDoc}
6409
                 */
6410
                public Loaded<V> load(@MaybeNull ClassLoader classLoader) {
6411
                    return doResolve().load(classLoader);
1✔
6412
                }
6413

6414
                @Override
6415
                @CachedReturnPlugin.Enhance("hashCode")
6416
                public int hashCode() {
6417
                    return doResolve().hashCode();
1✔
6418
                }
6419

6420
                @Override
6421
                public boolean equals(@MaybeNull Object other) {
6422
                    return doResolve().equals(other);
×
6423
                }
6424

6425
                @Override
6426
                public String toString() {
6427
                    return doResolve().toString();
1✔
6428
                }
6429

6430
                /**
6431
                 * A proxy for a mismatched type for which the property is not yet know.
6432
                 *
6433
                 * @param <W> The represented unloaded type.
6434
                 * @param <X> The represented loaded type.
6435
                 */
6436
                @HashCodeAndEqualsPlugin.Enhance
6437
                private static class ForMismatchedType<W, X> extends AbstractBase<W, X> {
6438

6439
                    /**
6440
                     * The mismatched value.
6441
                     */
6442
                    private final String value;
6443

6444
                    /**
6445
                     * The mismatched array type.
6446
                     */
6447
                    private final Sort sort;
6448

6449
                    /**
6450
                     * Creates a new mismatched type proxy.
6451
                     *
6452
                     * @param value The mismatched value.
6453
                     * @param sort  The mismatched array type.
6454
                     */
6455
                    private ForMismatchedType(String value, Sort sort) {
×
6456
                        this.value = value;
×
6457
                        this.sort = sort;
×
6458
                    }
×
6459

6460
                    /**
6461
                     * {@inheritDoc}
6462
                     */
6463
                    public State getState() {
6464
                        return State.UNRESOLVED;
×
6465
                    }
6466

6467
                    /**
6468
                     * {@inheritDoc}
6469
                     */
6470
                    public Sort getSort() {
6471
                        return Sort.NONE;
×
6472
                    }
6473

6474
                    /**
6475
                     * {@inheritDoc}
6476
                     */
6477
                    public AnnotationValue<W, X> filter(MethodDescription.InDefinedShape property, TypeDefinition typeDefinition) {
6478
                        return new ForMismatchedType<W, X>(property, property.getReturnType().isArray()
×
6479
                                ? RenderingDispatcher.CURRENT.toArrayErrorString(sort)
×
6480
                                : value);
6481
                    }
6482

6483
                    /**
6484
                     * {@inheritDoc}
6485
                     */
6486
                    public W resolve() {
6487
                        throw new IllegalStateException("Expected filtering of this unresolved property");
×
6488
                    }
6489

6490
                    /**
6491
                     * {@inheritDoc}
6492
                     */
6493
                    public Loaded<X> load(@MaybeNull ClassLoader classLoader) {
6494
                        throw new IllegalStateException("Expected filtering of this unresolved property");
×
6495
                    }
6496
                }
6497

6498
                /**
6499
                 * A lazy annotation value description for a type value.
6500
                 */
6501
                private static class ForTypeValue extends LazyAnnotationValue<TypeDescription, Class<?>> {
6502

6503
                    /**
6504
                     * The type pool to query for the type.
6505
                     */
6506
                    private final TypePool typePool;
6507

6508
                    /**
6509
                     * The type's binary name.
6510
                     */
6511
                    private final String typeName;
6512

6513
                    /**
6514
                     * Creates a new lazy description of an annotation type constant.
6515
                     *
6516
                     * @param typePool The type pool to query for the type.
6517
                     * @param typeName The type's binary name.
6518
                     */
6519
                    private ForTypeValue(TypePool typePool, String typeName) {
1✔
6520
                        this.typePool = typePool;
1✔
6521
                        this.typeName = typeName;
1✔
6522
                    }
1✔
6523

6524
                    /**
6525
                     * {@inheritDoc}
6526
                     */
6527
                    public Sort getSort() {
6528
                        return Sort.TYPE;
1✔
6529
                    }
6530

6531
                    @Override
6532
                    @CachedReturnPlugin.Enhance("resolved")
6533
                    @SuppressWarnings({"unchecked", "rawtypes"})
6534
                    protected AnnotationValue<TypeDescription, Class<?>> doResolve() {
6535
                        Resolution resolution = typePool.describe(typeName);
1✔
6536
                        return resolution.isResolved()
1✔
6537
                                ? new AnnotationValue.ForTypeDescription(resolution.resolve())
1✔
6538
                                : new AnnotationValue.ForMissingType<TypeDescription, Class<?>>(typeName);
6539
                    }
6540
                }
6541

6542
                /**
6543
                 * A lazy annotation value description for an annotation value.
6544
                 */
6545
                private static class ForAnnotationValue extends LazyAnnotationValue<AnnotationDescription, Annotation> {
6546

6547
                    /**
6548
                     * The type pool to use for resolving the annotation type.
6549
                     */
6550
                    private final TypePool typePool;
6551

6552
                    /**
6553
                     * The annotation token.
6554
                     */
6555
                    private final AnnotationToken annotationToken;
6556

6557
                    /**
6558
                     * Creates a new lazy annotation value.
6559
                     *
6560
                     * @param typePool        The type pool to use for resolving the annotation type.
6561
                     * @param annotationToken The annotation token.
6562
                     */
6563
                    private ForAnnotationValue(TypePool typePool, AnnotationToken annotationToken) {
1✔
6564
                        this.typePool = typePool;
1✔
6565
                        this.annotationToken = annotationToken;
1✔
6566
                    }
1✔
6567

6568
                    /**
6569
                     * {@inheritDoc}
6570
                     */
6571
                    public Sort getSort() {
6572
                        return Sort.ANNOTATION;
1✔
6573
                    }
6574

6575
                    @Override
6576
                    @CachedReturnPlugin.Enhance("resolved")
6577
                    protected AnnotationValue<AnnotationDescription, Annotation> doResolve() {
6578
                        AnnotationToken.Resolution resolution = annotationToken.toAnnotationDescription(typePool);
1✔
6579
                        if (!resolution.isResolved()) {
1✔
6580
                            return new AnnotationValue.ForMissingType<AnnotationDescription, Annotation>(annotationToken.getBinaryName());
×
6581
                        } else if (!resolution.resolve().getAnnotationType().isAnnotation()) {
1✔
6582
                            return new ForMismatchedType<AnnotationDescription, Annotation>(resolution.resolve().getAnnotationType().getName(), Sort.ANNOTATION);
×
6583
                        } else {
6584
                            return new AnnotationValue.ForAnnotationDescription<Annotation>(resolution.resolve());
1✔
6585
                        }
6586
                    }
6587
                }
6588

6589
                /**
6590
                 * A lazy annotation value description for an enumeration value.
6591
                 */
6592
                private static class ForEnumerationValue extends LazyAnnotationValue<EnumerationDescription, Enum<?>> {
6593

6594
                    /**
6595
                     * The type pool to use for looking up types.
6596
                     */
6597
                    private final TypePool typePool;
6598

6599
                    /**
6600
                     * The binary name of the enumeration type.
6601
                     */
6602
                    private final String typeName;
6603

6604
                    /**
6605
                     * The name of the enumeration.
6606
                     */
6607
                    private final String value;
6608

6609
                    /**
6610
                     * Creates a lazy annotation value description for an enumeration.
6611
                     *
6612
                     * @param typePool The type pool to use for looking up types.
6613
                     * @param typeName The binary name of the enumeration type.
6614
                     * @param value    The name of the enumeration.
6615
                     */
6616
                    private ForEnumerationValue(TypePool typePool, String typeName, String value) {
1✔
6617
                        this.typePool = typePool;
1✔
6618
                        this.typeName = typeName;
1✔
6619
                        this.value = value;
1✔
6620
                    }
1✔
6621

6622
                    /**
6623
                     * {@inheritDoc}
6624
                     */
6625
                    public Sort getSort() {
6626
                        return Sort.ENUMERATION;
1✔
6627
                    }
6628

6629
                    @Override
6630
                    @CachedReturnPlugin.Enhance("resolved")
6631
                    @SuppressWarnings({"unchecked", "rawtypes"})
6632
                    protected AnnotationValue<EnumerationDescription, Enum<?>> doResolve() {
6633
                        Resolution resolution = typePool.describe(typeName);
1✔
6634
                        if (!resolution.isResolved()) {
1✔
6635
                            return new AnnotationValue.ForMissingType<EnumerationDescription, Enum<?>>(typeName);
×
6636
                        } else if (!resolution.resolve().isEnum()) {
1✔
6637
                            return new ForMismatchedType<EnumerationDescription, Enum<?>>(typeName + "." + value, Sort.ENUMERATION);
×
6638
                        } else if (resolution.resolve().getDeclaredFields().filter(named(value)).isEmpty()) {
1✔
6639
                            return new AnnotationValue.ForEnumerationDescription.WithUnknownConstant(resolution.resolve(), value);
×
6640
                        } else {
6641
                            return new AnnotationValue.ForEnumerationDescription(new EnumerationDescription.Latent(resolution.resolve(), value));
1✔
6642
                        }
6643
                    }
6644
                }
6645

6646
                /**
6647
                 * A lazy projection of an annotation value that contains an array of values.
6648
                 */
6649
                private static class ForArray extends LazyAnnotationValue<Object, Object> {
6650

6651
                    /**
6652
                     * The type pool to use for looking up types.
6653
                     */
6654
                    private final TypePool typePool;
6655

6656
                    /**
6657
                     * A reference to the component type.
6658
                     */
6659
                    private final ComponentTypeReference componentTypeReference;
6660

6661
                    /**
6662
                     * A list of all values of this array value in their order.
6663
                     */
6664
                    private final List<AnnotationValue<?, ?>> values;
6665

6666
                    /**
6667
                     * Creates a lazy projection for a non-primitive array.
6668
                     *
6669
                     * @param typePool               The type pool to use for looking up types.
6670
                     * @param componentTypeReference A reference to the component type.
6671
                     * @param values                 A list of all values of this array value in their order.
6672
                     */
6673
                    private ForArray(TypePool typePool, ComponentTypeReference componentTypeReference, List<AnnotationValue<?, ?>> values) {
1✔
6674
                        this.typePool = typePool;
1✔
6675
                        this.componentTypeReference = componentTypeReference;
1✔
6676
                        this.values = values;
1✔
6677
                    }
1✔
6678

6679
                    /**
6680
                     * {@inheritDoc}
6681
                     */
6682
                    public Sort getSort() {
6683
                        return Sort.ARRAY;
×
6684
                    }
6685

6686
                    @Override
6687
                    @CachedReturnPlugin.Enhance("resolved")
6688
                    protected AnnotationValue<Object, Object> doResolve() {
6689
                        String typeName = componentTypeReference.resolve();
1✔
6690
                        if (typeName != null) {
1✔
6691
                            Resolution resolution = typePool.describe(typeName);
1✔
6692
                            if (!resolution.isResolved()) {
1✔
6693
                                return new ForMissingType<Object, Object>(typeName);
×
6694
                            } else if (resolution.resolve().isEnum()) {
1✔
6695
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(EnumerationDescription.class, resolution.resolve(), values);
1✔
6696
                            } else if (resolution.resolve().isAnnotation()) {
1✔
6697
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(AnnotationDescription.class, resolution.resolve(), values);
1✔
6698
                            } else if (resolution.resolve().represents(Class.class)) {
1✔
6699
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(TypeDescription.class, resolution.resolve(), values);
1✔
6700
                            } else if (resolution.resolve().represents(String.class)) {
1✔
6701
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(String.class, resolution.resolve(), values);
1✔
6702
                            } else if (resolution.resolve().represents(boolean.class)) {
1✔
6703
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(boolean.class, resolution.resolve(), values);
1✔
6704
                            } else if (resolution.resolve().represents(byte.class)) {
1✔
6705
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(byte.class, resolution.resolve(), values);
1✔
6706
                            } else if (resolution.resolve().represents(short.class)) {
1✔
6707
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(short.class, resolution.resolve(), values);
1✔
6708
                            } else if (resolution.resolve().represents(char.class)) {
1✔
6709
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(char.class, resolution.resolve(), values);
1✔
6710
                            } else if (resolution.resolve().represents(int.class)) {
1✔
6711
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(int.class, resolution.resolve(), values);
1✔
6712
                            } else if (resolution.resolve().represents(long.class)) {
1✔
6713
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(long.class, resolution.resolve(), values);
1✔
6714
                            } else if (resolution.resolve().represents(float.class)) {
1✔
6715
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(float.class, resolution.resolve(), values);
1✔
6716
                            } else if (resolution.resolve().represents(double.class)) {
1✔
6717
                                return new AnnotationValue.ForDescriptionArray<Object, Object>(double.class, resolution.resolve(), values);
1✔
6718
                            }
6719
                        }
6720
                        Sort sort = Sort.NONE;
×
6721
                        ListIterator<AnnotationValue<?, ?>> iterator = values.listIterator(values.size());
×
6722
                        while (iterator.hasPrevious() && !sort.isDefined()) {
×
6723
                            sort = iterator.previous().getSort();
×
6724
                        }
6725
                        return new ForMismatchedType<Object, Object>(RenderingDispatcher.CURRENT.toArrayErrorString(sort), sort);
1✔
6726
                    }
6727
                }
6728
            }
6729

6730
            /**
6731
             * An implementation of a {@link PackageDescription} that only
6732
             * loads its annotations on requirement.
6733
             */
6734
            private static class LazyPackageDescription extends PackageDescription.AbstractBase {
6735

6736
                /**
6737
                 * The type pool to use for look-ups.
6738
                 */
6739
                private final TypePool typePool;
6740

6741
                /**
6742
                 * The name of the package.
6743
                 */
6744
                private final String name;
6745

6746
                /**
6747
                 * Creates a new lazy package description.
6748
                 *
6749
                 * @param typePool The type pool to use for look-ups.
6750
                 * @param name     The name of the package.
6751
                 */
6752
                private LazyPackageDescription(TypePool typePool, String name) {
1✔
6753
                    this.typePool = typePool;
1✔
6754
                    this.name = name;
1✔
6755
                }
1✔
6756

6757
                /**
6758
                 * {@inheritDoc}
6759
                 */
6760
                public AnnotationList getDeclaredAnnotations() {
6761
                    Resolution resolution = typePool.describe(name + "." + PackageDescription.PACKAGE_CLASS_NAME);
1✔
6762
                    return resolution.isResolved()
1✔
6763
                            ? resolution.resolve().getDeclaredAnnotations()
1✔
6764
                            : new AnnotationList.Empty();
6765
                }
6766

6767
                /**
6768
                 * {@inheritDoc}
6769
                 */
6770
                public String getName() {
6771
                    return name;
1✔
6772
                }
6773
            }
6774

6775
            /**
6776
             * A list that is constructing {@link LazyTypeDescription}s.
6777
             */
6778
            protected static class LazyTypeList extends TypeList.AbstractBase {
6779

6780
                /**
6781
                 * The type pool to use for locating types.
6782
                 */
6783
                private final TypePool typePool;
6784

6785
                /**
6786
                 * A list of type descriptors that this list represents.
6787
                 */
6788
                private final List<String> descriptors;
6789

6790
                /**
6791
                 * Creates a list of lazy type descriptions.
6792
                 *
6793
                 * @param typePool    The type pool to use for locating types.
6794
                 * @param descriptors A list of type descriptors that this list represents.
6795
                 */
6796
                protected LazyTypeList(TypePool typePool, List<String> descriptors) {
1✔
6797
                    this.typePool = typePool;
1✔
6798
                    this.descriptors = descriptors;
1✔
6799
                }
1✔
6800

6801
                /**
6802
                 * {@inheritDoc}
6803
                 */
6804
                public TypeDescription get(int index) {
6805
                    return TokenizedGenericType.toErasure(typePool, descriptors.get(index));
1✔
6806
                }
6807

6808
                /**
6809
                 * {@inheritDoc}
6810
                 */
6811
                public int size() {
6812
                    return descriptors.size();
1✔
6813
                }
6814

6815
                /**
6816
                 * {@inheritDoc}
6817
                 */
6818
                @MaybeNull
6819
                public String[] toInternalNames() {
6820
                    String[] internalName = new String[descriptors.size()];
1✔
6821
                    int index = 0;
1✔
6822
                    for (String descriptor : descriptors) {
1✔
6823
                        internalName[index++] = Type.getType(descriptor).getInternalName();
1✔
6824
                    }
1✔
6825
                    return internalName.length == 0
1✔
6826
                            ? NO_INTERFACES
6827
                            : internalName;
6828
                }
6829

6830
                /**
6831
                 * {@inheritDoc}
6832
                 */
6833
                public int getStackSize() {
6834
                    int stackSize = 0;
1✔
6835
                    for (String descriptor : descriptors) {
1✔
6836
                        stackSize += Type.getType(descriptor).getSize();
1✔
6837
                    }
1✔
6838
                    return stackSize;
1✔
6839
                }
6840
            }
6841

6842
            /**
6843
             * A lazy list that represents all nest members of the represented type.
6844
             */
6845
            protected static class LazyNestMemberList extends TypeList.AbstractBase {
6846

6847
                /**
6848
                 * The type for which the nest members are represented.
6849
                 */
6850
                private final TypeDescription typeDescription;
6851

6852
                /**
6853
                 * The type pool to use for looking up types.
6854
                 */
6855
                private final TypePool typePool;
6856

6857
                /**
6858
                 * The binary names of all nest members of this nest mate group excluding the represented type.
6859
                 */
6860
                private final List<String> nestMembers;
6861

6862
                /**
6863
                 * Creates a new lazy type list of all nest members of this group.
6864
                 *
6865
                 * @param typeDescription The type for which the nest members are represented.
6866
                 * @param typePool        The type pool to use for looking up types.
6867
                 * @param nestMembers     The binary names of all nest members of this nest mate group excluding the represented type.
6868
                 */
6869
                protected LazyNestMemberList(TypeDescription typeDescription, TypePool typePool, List<String> nestMembers) {
1✔
6870
                    this.typeDescription = typeDescription;
1✔
6871
                    this.typePool = typePool;
1✔
6872
                    this.nestMembers = nestMembers;
1✔
6873
                }
1✔
6874

6875
                /**
6876
                 * {@inheritDoc}
6877
                 */
6878
                public TypeDescription get(int index) {
6879
                    return index == 0
1✔
6880
                            ? typeDescription
6881
                            : typePool.describe(nestMembers.get(index - 1)).resolve();
×
6882
                }
6883

6884
                /**
6885
                 * {@inheritDoc}
6886
                 */
6887
                public int size() {
6888
                    return nestMembers.size() + 1;
1✔
6889
                }
6890

6891
                /**
6892
                 * {@inheritDoc}
6893
                 */
6894
                public String[] toInternalNames() {
6895
                    String[] internalName = new String[nestMembers.size() + 1];
×
6896
                    internalName[0] = typeDescription.getInternalName();
×
6897
                    int index = 1;
×
6898
                    for (String name : nestMembers) {
×
6899
                        internalName[index++] = name.replace('.', '/');
×
6900
                    }
×
6901
                    return internalName;
×
6902
                }
6903

6904
                /**
6905
                 * {@inheritDoc}
6906
                 */
6907
                public int getStackSize() {
6908
                    return nestMembers.size() + 1;
×
6909
                }
6910
            }
6911

6912
            /**
6913
             * A representation of a generic type that is described by a {@link GenericTypeToken}.
6914
             */
6915
            protected static class TokenizedGenericType extends Generic.LazyProjection.WithEagerNavigation {
6916

6917
                /**
6918
                 * The type pool to use for locating referenced types.
6919
                 */
6920
                private final TypePool typePool;
6921

6922
                /**
6923
                 * The token that describes the represented generic type.
6924
                 */
6925
                private final GenericTypeToken genericTypeToken;
6926

6927
                /**
6928
                 * A descriptor of the generic type's raw type.
6929
                 */
6930
                private final String rawTypeDescriptor;
6931

6932
                /**
6933
                 * The tokenized type's type annotation tokens.
6934
                 */
6935
                private final Map<String, List<AnnotationToken>> annotationTokens;
6936

6937
                /**
6938
                 * The closest type variable source of this generic type's declaration context.
6939
                 */
6940
                private final TypeVariableSource typeVariableSource;
6941

6942
                /**
6943
                 * Creates a new tokenized generic type.
6944
                 *
6945
                 * @param typePool           The type pool to use for locating referenced types.
6946
                 * @param genericTypeToken   The token that describes the represented generic type.
6947
                 * @param rawTypeDescriptor  A descriptor of the generic type's erasure.
6948
                 * @param annotationTokens   The tokenized type's type annotation tokens.
6949
                 * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6950
                 */
6951
                protected TokenizedGenericType(TypePool typePool,
6952
                                               GenericTypeToken genericTypeToken,
6953
                                               String rawTypeDescriptor,
6954
                                               Map<String, List<AnnotationToken>> annotationTokens,
6955
                                               TypeVariableSource typeVariableSource) {
1✔
6956
                    this.typePool = typePool;
1✔
6957
                    this.genericTypeToken = genericTypeToken;
1✔
6958
                    this.rawTypeDescriptor = rawTypeDescriptor;
1✔
6959
                    this.annotationTokens = annotationTokens;
1✔
6960
                    this.typeVariableSource = typeVariableSource;
1✔
6961
                }
1✔
6962

6963
                /**
6964
                 * Creates a new generic type description for a tokenized generic type.
6965
                 *
6966
                 * @param typePool           The type pool to use for locating referenced types.
6967
                 * @param genericTypeToken   The token that describes the represented generic type.
6968
                 * @param rawTypeDescriptor  A descriptor of the generic type's erasure.
6969
                 * @param annotationTokens   The tokenized type's type annotation tokens or {@code null} if no such annotations are defined.
6970
                 * @param typeVariableSource The closest type variable source of this generic type's declaration context.
6971
                 * @return A suitable generic type.
6972
                 */
6973
                protected static Generic of(TypePool typePool,
6974
                                            GenericTypeToken genericTypeToken,
6975
                                            String rawTypeDescriptor,
6976
                                            @MaybeNull Map<String, List<AnnotationToken>> annotationTokens,
6977
                                            TypeVariableSource typeVariableSource) {
6978
                    return new TokenizedGenericType(typePool,
1✔
6979
                            genericTypeToken,
6980
                            rawTypeDescriptor,
6981
                            annotationTokens == null
6982
                                    ? Collections.<String, List<AnnotationToken>>emptyMap()
1✔
6983
                                    : annotationTokens,
6984
                            typeVariableSource);
6985
                }
6986

6987
                /**
6988
                 * Creates a type description from a descriptor by looking up the corresponding type.
6989
                 *
6990
                 * @param typePool   The type pool to use for locating a type.
6991
                 * @param descriptor The descriptor to interpret.
6992
                 * @return A description of the type represented by the descriptor.
6993
                 */
6994
                protected static TypeDescription toErasure(TypePool typePool, String descriptor) {
6995
                    Type type = Type.getType(descriptor);
1✔
6996
                    return typePool.describe(type.getSort() == Type.ARRAY
1✔
6997
                            ? type.getInternalName().replace('/', '.')
1✔
6998
                            : type.getClassName()).resolve();
1✔
6999
                }
7000

7001
                @Override
7002
                @CachedReturnPlugin.Enhance("resolved")
7003
                protected Generic resolve() {
7004
                    return genericTypeToken.toGenericType(typePool, typeVariableSource, GenericTypeToken.EMPTY_TYPE_PATH, annotationTokens);
1✔
7005
                }
7006

7007
                /**
7008
                 * {@inheritDoc}
7009
                 */
7010
                @CachedReturnPlugin.Enhance("erasure")
7011
                public TypeDescription asErasure() {
7012
                    return toErasure(typePool, rawTypeDescriptor);
1✔
7013
                }
7014

7015
                /**
7016
                 * {@inheritDoc}
7017
                 */
7018
                public AnnotationList getDeclaredAnnotations() {
7019
                    return resolve().getDeclaredAnnotations();
1✔
7020
                }
7021

7022
                /**
7023
                 * A tokenized list of generic types.
7024
                 */
7025
                protected static class TokenList extends TypeList.Generic.AbstractBase {
7026

7027
                    /**
7028
                     * The type pool to use for locating types.
7029
                     */
7030
                    private final TypePool typePool;
7031

7032
                    /**
7033
                     * Type tokens that describe the represented generic types.
7034
                     */
7035
                    private final List<GenericTypeToken> genericTypeTokens;
7036

7037
                    /**
7038
                     * A list of the generic types' erasures.
7039
                     */
7040
                    private final List<String> rawTypeDescriptors;
7041

7042
                    /**
7043
                     * The closest type variable source of this generic type's declaration context.
7044
                     */
7045
                    private final TypeVariableSource typeVariableSource;
7046

7047
                    /**
7048
                     * A mapping of each type's type annotation tokens by its index.
7049
                     */
7050
                    private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
7051

7052
                    /**
7053
                     * Creates a list of tokenized generic types.
7054
                     *
7055
                     * @param typePool           The type pool to use for locating type descriptions.
7056
                     * @param genericTypeTokens  A list of tokens describing the represented generic types.
7057
                     * @param annotationTokens   A mapping of each type's type annotation tokens by its index.
7058
                     * @param rawTypeDescriptors A list of the generic types' erasures.
7059
                     * @param typeVariableSource The closest type variable source of this generic type's declaration context.
7060
                     */
7061
                    private TokenList(TypePool typePool,
7062
                                      List<GenericTypeToken> genericTypeTokens,
7063
                                      Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
7064
                                      List<String> rawTypeDescriptors,
7065
                                      TypeVariableSource typeVariableSource) {
1✔
7066
                        this.typePool = typePool;
1✔
7067
                        this.genericTypeTokens = genericTypeTokens;
1✔
7068
                        this.annotationTokens = annotationTokens;
1✔
7069
                        this.rawTypeDescriptors = rawTypeDescriptors;
1✔
7070
                        this.typeVariableSource = typeVariableSource;
1✔
7071
                    }
1✔
7072

7073
                    /**
7074
                     * {@inheritDoc}
7075
                     */
7076
                    public Generic get(int index) {
7077
                        return rawTypeDescriptors.size() == genericTypeTokens.size()
1✔
7078
                                ? TokenizedGenericType.of(typePool, genericTypeTokens.get(index), rawTypeDescriptors.get(index), annotationTokens.get(index), typeVariableSource)
1✔
7079
                                : TokenizedGenericType.toErasure(typePool, rawTypeDescriptors.get(index)).asGenericType();
1✔
7080
                    }
7081

7082
                    /**
7083
                     * {@inheritDoc}
7084
                     */
7085
                    public int size() {
7086
                        return rawTypeDescriptors.size();
1✔
7087
                    }
7088

7089
                    /**
7090
                     * {@inheritDoc}
7091
                     */
7092
                    public TypeList asErasures() {
7093
                        return new LazyTypeList(typePool, rawTypeDescriptors);
1✔
7094
                    }
7095
                }
7096

7097
                /**
7098
                 * A list of tokenized type variables.
7099
                 */
7100
                protected static class TypeVariableList extends TypeList.Generic.AbstractBase {
7101

7102
                    /**
7103
                     * The type pool to use for locating types.
7104
                     */
7105
                    private final TypePool typePool;
7106

7107
                    /**
7108
                     * Type tokens that describe the represented type variables.
7109
                     */
7110
                    private final List<GenericTypeToken.OfFormalTypeVariable> typeVariables;
7111

7112
                    /**
7113
                     * The type variable source of the represented type variables.
7114
                     */
7115
                    private final TypeVariableSource typeVariableSource;
7116

7117
                    /**
7118
                     * A mapping of the type variables' type annotation tokens by their indices.
7119
                     */
7120
                    private final Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens;
7121

7122
                    /**
7123
                     * A mapping of the type variables' bound types' annotation tokens by their indices and each type variable's index..
7124
                     */
7125
                    private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens;
7126

7127
                    /**
7128
                     * Creates a list of type variables.
7129
                     *
7130
                     * @param typePool              The type pool to use for locating types.
7131
                     * @param typeVariables         Type tokens that describe the represented generic types.
7132
                     * @param typeVariableSource    The type variable source of the represented type variables.
7133
                     * @param annotationTokens      A mapping of the type variables' type annotation tokens by their indices.
7134
                     * @param boundAnnotationTokens A mapping of the type variables' bound types' annotation tokens by their indices
7135
                     *                              and each type variable's index.
7136
                     */
7137
                    protected TypeVariableList(TypePool typePool,
7138
                                               List<GenericTypeToken.OfFormalTypeVariable> typeVariables,
7139
                                               TypeVariableSource typeVariableSource,
7140
                                               Map<Integer, Map<String, List<AnnotationToken>>> annotationTokens,
7141
                                               Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> boundAnnotationTokens) {
1✔
7142
                        this.typePool = typePool;
1✔
7143
                        this.typeVariables = typeVariables;
1✔
7144
                        this.typeVariableSource = typeVariableSource;
1✔
7145
                        this.annotationTokens = annotationTokens;
1✔
7146
                        this.boundAnnotationTokens = boundAnnotationTokens;
1✔
7147
                    }
1✔
7148

7149
                    /**
7150
                     * {@inheritDoc}
7151
                     */
7152
                    public Generic get(int index) {
7153
                        return typeVariables.get(index).toGenericType(typePool, typeVariableSource, annotationTokens.get(index), boundAnnotationTokens.get(index));
1✔
7154
                    }
7155

7156
                    /**
7157
                     * {@inheritDoc}
7158
                     */
7159
                    public int size() {
7160
                        return typeVariables.size();
1✔
7161
                    }
7162
                }
7163

7164
                /**
7165
                 * A lazy description of a non-well-defined described generic type.
7166
                 */
7167
                protected static class Malformed extends LazyProjection.WithEagerNavigation {
7168

7169
                    /**
7170
                     * The type pool to use for locating types.
7171
                     */
7172
                    private final TypePool typePool;
7173

7174
                    /**
7175
                     * The descriptor of the type erasure.
7176
                     */
7177
                    private final String rawTypeDescriptor;
7178

7179
                    /**
7180
                     * Creates a lazy description of a non-well-defined described generic type.
7181
                     *
7182
                     * @param typePool          The type pool to use for locating types.
7183
                     * @param rawTypeDescriptor The descriptor of the type erasure.
7184
                     */
7185
                    protected Malformed(TypePool typePool, String rawTypeDescriptor) {
1✔
7186
                        this.typePool = typePool;
1✔
7187
                        this.rawTypeDescriptor = rawTypeDescriptor;
1✔
7188
                    }
1✔
7189

7190
                    @Override
7191
                    protected Generic resolve() {
7192
                        throw new GenericSignatureFormatError();
1✔
7193
                    }
7194

7195
                    /**
7196
                     * {@inheritDoc}
7197
                     */
7198
                    public TypeDescription asErasure() {
7199
                        return toErasure(typePool, rawTypeDescriptor);
×
7200
                    }
7201

7202
                    /**
7203
                     * {@inheritDoc}
7204
                     */
7205
                    public AnnotationList getDeclaredAnnotations() {
7206
                        throw new GenericSignatureFormatError();
×
7207
                    }
7208

7209
                    /**
7210
                     * A tokenized list of non-well-defined generic types.
7211
                     */
7212
                    protected static class TokenList extends TypeList.Generic.AbstractBase {
7213

7214
                        /**
7215
                         * The type pool to use for locating types.
7216
                         */
7217
                        private final TypePool typePool;
7218

7219
                        /**
7220
                         * A list of descriptors of the list's types' erasures.
7221
                         */
7222
                        private final List<String> rawTypeDescriptors;
7223

7224
                        /**
7225
                         * Creates a new tokenized list of generic types.
7226
                         *
7227
                         * @param typePool           The type pool to use for locating types.
7228
                         * @param rawTypeDescriptors A list of descriptors of the list's types' erasures.
7229
                         */
7230
                        protected TokenList(TypePool typePool, List<String> rawTypeDescriptors) {
1✔
7231
                            this.typePool = typePool;
1✔
7232
                            this.rawTypeDescriptors = rawTypeDescriptors;
1✔
7233
                        }
1✔
7234

7235
                        /**
7236
                         * {@inheritDoc}
7237
                         */
7238
                        public Generic get(int index) {
7239
                            return new Malformed(typePool, rawTypeDescriptors.get(index));
1✔
7240
                        }
7241

7242
                        /**
7243
                         * {@inheritDoc}
7244
                         */
7245
                        public int size() {
7246
                            return rawTypeDescriptors.size();
1✔
7247
                        }
7248

7249
                        /**
7250
                         * {@inheritDoc}
7251
                         */
7252
                        public TypeList asErasures() {
7253
                            return new LazyTypeList(typePool, rawTypeDescriptors);
×
7254
                        }
7255
                    }
7256

7257
                }
7258
            }
7259

7260
            /**
7261
             * A lazy field description that only resolved type references when required.
7262
             */
7263
            private class LazyFieldDescription extends FieldDescription.InDefinedShape.AbstractBase {
7264

7265
                /**
7266
                 * The name of the field.
7267
                 */
7268
                private final String name;
7269

7270
                /**
7271
                 * The modifiers of the field.
7272
                 */
7273
                private final int modifiers;
7274

7275
                /**
7276
                 * The descriptor of this field's type.
7277
                 */
7278
                private final String descriptor;
7279

7280
                /**
7281
                 * The field's generic signature as found in the class file or {@code null} if the field is not generic.
7282
                 */
7283
                @MaybeNull
7284
                private final String genericSignature;
7285

7286
                /**
7287
                 * A resolution of this field's generic type.
7288
                 */
7289
                private final GenericTypeToken.Resolution.ForField signatureResolution;
7290

7291
                /**
7292
                 * A mapping of the field type's type annotation tokens.
7293
                 */
7294
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
7295

7296
                /**
7297
                 * A list of annotation descriptions of this field.
7298
                 */
7299
                private final List<AnnotationToken> annotationTokens;
7300

7301
                /**
7302
                 * Creates a new lazy field description.
7303
                 *
7304
                 * @param name                 The name of the field.
7305
                 * @param modifiers            The modifiers of the field.
7306
                 * @param descriptor           The descriptor of this field's type.
7307
                 * @param genericSignature     The field's generic signature as found in the class file or {@code null} if the field is not generic.
7308
                 * @param signatureResolution  A resolution of this field's generic type.
7309
                 * @param typeAnnotationTokens A mapping of the field type's type annotation tokens.
7310
                 * @param annotationTokens     A list of annotation descriptions of this field.
7311
                 */
7312
                private LazyFieldDescription(String name,
7313
                                             int modifiers,
7314
                                             String descriptor,
7315
                                             @MaybeNull String genericSignature,
7316
                                             GenericTypeToken.Resolution.ForField signatureResolution,
7317
                                             Map<String, List<AnnotationToken>> typeAnnotationTokens,
7318
                                             List<AnnotationToken> annotationTokens) {
1✔
7319
                    this.modifiers = modifiers;
1✔
7320
                    this.name = name;
1✔
7321
                    this.descriptor = descriptor;
1✔
7322
                    this.genericSignature = genericSignature;
1✔
7323
                    this.signatureResolution = signatureResolution;
1✔
7324
                    this.typeAnnotationTokens = typeAnnotationTokens;
1✔
7325
                    this.annotationTokens = annotationTokens;
1✔
7326
                }
1✔
7327

7328
                /**
7329
                 * {@inheritDoc}
7330
                 */
7331
                public Generic getType() {
7332
                    return signatureResolution.resolveFieldType(descriptor, typePool, typeAnnotationTokens, this);
1✔
7333
                }
7334

7335
                /**
7336
                 * {@inheritDoc}
7337
                 */
7338
                public AnnotationList getDeclaredAnnotations() {
7339
                    return LazyAnnotationDescription.asListOfNullable(typePool, annotationTokens);
1✔
7340
                }
7341

7342
                /**
7343
                 * {@inheritDoc}
7344
                 */
7345
                public String getName() {
7346
                    return name;
1✔
7347
                }
7348

7349
                /**
7350
                 * {@inheritDoc}
7351
                 */
7352
                @Nonnull
7353
                public TypeDescription getDeclaringType() {
7354
                    return LazyTypeDescription.this;
1✔
7355
                }
7356

7357
                /**
7358
                 * {@inheritDoc}
7359
                 */
7360
                public int getModifiers() {
7361
                    return modifiers;
1✔
7362
                }
7363

7364
                /**
7365
                 * {@inheritDoc}
7366
                 */
7367
                @MaybeNull
7368
                public String getGenericSignature() {
7369
                    return genericSignature;
×
7370
                }
7371
            }
7372

7373
            /**
7374
             * A lazy representation of a method that resolves references to types only on demand.
7375
             */
7376
            private class LazyMethodDescription extends MethodDescription.InDefinedShape.AbstractBase {
7377

7378
                /**
7379
                 * The internal name of this method.
7380
                 */
7381
                private final String internalName;
7382

7383
                /**
7384
                 * The modifiers of this method.
7385
                 */
7386
                private final int modifiers;
7387

7388
                /**
7389
                 * The descriptor of the return type.
7390
                 */
7391
                private final String returnTypeDescriptor;
7392

7393
                /**
7394
                 * The method's generic signature as found in the class file or {@code null} if the method is not generic.
7395
                 */
7396
                @MaybeNull
7397
                private final String genericSignature;
7398

7399
                /**
7400
                 * The generic type token of this method.
7401
                 */
7402
                private final GenericTypeToken.Resolution.ForMethod signatureResolution;
7403

7404
                /**
7405
                 * A list of type descriptions of this method's parameters.
7406
                 */
7407
                private final List<String> parameterTypeDescriptors;
7408

7409
                /**
7410
                 * A list of type descriptions of this method's exception types.
7411
                 */
7412
                private final List<String> exceptionTypeDescriptors;
7413

7414
                /**
7415
                 * A mapping of the type variables' type annotation tokens by their indices.
7416
                 */
7417
                private final Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens;
7418

7419
                /**
7420
                 * A mapping of the type variables' type bounds' type annotation tokens by their indices and each variable's index.
7421
                 */
7422
                private final Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens;
7423

7424
                /**
7425
                 * A mapping of the return type's type variable tokens.
7426
                 */
7427
                private final Map<String, List<AnnotationToken>> returnTypeAnnotationTokens;
7428

7429
                /**
7430
                 * A mapping of the parameter types' type annotation tokens by their indices.
7431
                 */
7432
                private final Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens;
7433

7434
                /**
7435
                 * A mapping of the exception types' type annotation tokens by their indices.
7436
                 */
7437
                private final Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens;
7438

7439
                /**
7440
                 * A mapping of the receiver type's type annotation tokens.
7441
                 */
7442
                private final Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens;
7443

7444
                /**
7445
                 * The annotation tokens representing the method's annotations.
7446
                 */
7447
                private final List<AnnotationToken> annotationTokens;
7448

7449
                /**
7450
                 * The annotation tokens representing the parameter's annotation. Every index can
7451
                 * contain {@code null} if a parameter does not define any annotations.
7452
                 */
7453
                private final Map<Integer, List<AnnotationToken>> parameterAnnotationTokens;
7454

7455
                /**
7456
                 * An array of parameter names which may be {@code null} if no explicit name is known for a parameter.
7457
                 */
7458
                private final String[] parameterNames;
7459

7460
                /**
7461
                 * An array of parameter modifiers which may be {@code null} if no modifiers is known.
7462
                 */
7463
                private final Integer[] parameterModifiers;
7464

7465
                /**
7466
                 * The default value of this method or {@code null} if no such value exists.
7467
                 */
7468
                @MaybeNull
7469
                private final AnnotationValue<?, ?> defaultValue;
7470

7471
                /**
7472
                 * Creates a new lazy method description.
7473
                 *
7474
                 * @param internalName                      The internal name of this method.
7475
                 * @param modifiers                         The modifiers of the represented method.
7476
                 * @param descriptor                        The method descriptor of this method.
7477
                 * @param genericSignature                  The method's generic signature as found in the class file or {@code null} if the method is not generic.
7478
                 * @param signatureResolution               The generic type token of this method.
7479
                 * @param exceptionTypeInternalName         The internal names of the exceptions that are declared by this
7480
                 *                                          method or {@code null} if no exceptions are declared by this
7481
                 *                                          method.
7482
                 * @param typeVariableAnnotationTokens      A mapping of the type variables' type annotation tokens by their indices.
7483
                 * @param typeVariableBoundAnnotationTokens A mapping of the type variables' type bounds' type annotation tokens by their
7484
                 *                                          index and each variable's index.
7485
                 * @param returnTypeAnnotationTokens        A mapping of the return type's type variable tokens.
7486
                 * @param parameterTypeAnnotationTokens     A mapping of the parameter types' type annotation tokens by their indices.
7487
                 * @param exceptionTypeAnnotationTokens     A mapping of the exception types' type annotation tokens by their indices.
7488
                 * @param receiverTypeAnnotationTokens      A mapping of the receiver type's type annotation tokens.
7489
                 * @param annotationTokens                  The annotation tokens representing the method's annotations.
7490
                 * @param parameterAnnotationTokens         The annotation tokens representing the parameter's annotation. Every
7491
                 *                                          index can contain {@code null} if a parameter does not define any annotations.
7492
                 * @param parameterTokens                   A list of parameter tokens which might be empty or even out of sync
7493
                 *                                          with the actual parameters if the debugging information found in a
7494
                 *                                          class was corrupt.
7495
                 * @param defaultValue                      The default value of this method or {@code null} if there is no
7496
                 */
7497
                private LazyMethodDescription(String internalName,
7498
                                              int modifiers,
7499
                                              String descriptor,
7500
                                              @MaybeNull String genericSignature,
7501
                                              GenericTypeToken.Resolution.ForMethod signatureResolution,
7502
                                              @MaybeNull String[] exceptionTypeInternalName,
7503
                                              Map<Integer, Map<String, List<AnnotationToken>>> typeVariableAnnotationTokens,
7504
                                              Map<Integer, Map<Integer, Map<String, List<AnnotationToken>>>> typeVariableBoundAnnotationTokens,
7505
                                              Map<String, List<AnnotationToken>> returnTypeAnnotationTokens,
7506
                                              Map<Integer, Map<String, List<AnnotationToken>>> parameterTypeAnnotationTokens,
7507
                                              Map<Integer, Map<String, List<AnnotationToken>>> exceptionTypeAnnotationTokens,
7508
                                              Map<String, List<AnnotationToken>> receiverTypeAnnotationTokens,
7509
                                              List<AnnotationToken> annotationTokens,
7510
                                              Map<Integer, List<AnnotationToken>> parameterAnnotationTokens,
7511
                                              List<MethodToken.ParameterToken> parameterTokens,
7512
                                              @MaybeNull AnnotationValue<?, ?> defaultValue) {
1✔
7513
                    this.modifiers = modifiers;
1✔
7514
                    this.internalName = internalName;
1✔
7515
                    Type methodType = Type.getMethodType(descriptor);
1✔
7516
                    Type returnType = methodType.getReturnType();
1✔
7517
                    Type[] parameterType = methodType.getArgumentTypes();
1✔
7518
                    returnTypeDescriptor = returnType.getDescriptor();
1✔
7519
                    parameterTypeDescriptors = new ArrayList<String>(parameterType.length);
1✔
7520
                    for (Type type : parameterType) {
1✔
7521
                        parameterTypeDescriptors.add(type.getDescriptor());
1✔
7522
                    }
7523
                    this.genericSignature = genericSignature;
1✔
7524
                    this.signatureResolution = signatureResolution;
1✔
7525
                    if (exceptionTypeInternalName == null) {
1✔
7526
                        exceptionTypeDescriptors = Collections.emptyList();
1✔
7527
                    } else {
7528
                        exceptionTypeDescriptors = new ArrayList<String>(exceptionTypeInternalName.length);
1✔
7529
                        for (String anExceptionTypeInternalName : exceptionTypeInternalName) {
1✔
7530
                            exceptionTypeDescriptors.add(Type.getObjectType(anExceptionTypeInternalName).getDescriptor());
1✔
7531
                        }
7532
                    }
7533
                    this.typeVariableAnnotationTokens = typeVariableAnnotationTokens;
1✔
7534
                    this.typeVariableBoundAnnotationTokens = typeVariableBoundAnnotationTokens;
1✔
7535
                    this.returnTypeAnnotationTokens = returnTypeAnnotationTokens;
1✔
7536
                    this.parameterTypeAnnotationTokens = parameterTypeAnnotationTokens;
1✔
7537
                    this.exceptionTypeAnnotationTokens = exceptionTypeAnnotationTokens;
1✔
7538
                    this.receiverTypeAnnotationTokens = receiverTypeAnnotationTokens;
1✔
7539
                    this.annotationTokens = annotationTokens;
1✔
7540
                    this.parameterAnnotationTokens = parameterAnnotationTokens;
1✔
7541
                    parameterNames = new String[parameterType.length];
1✔
7542
                    parameterModifiers = new Integer[parameterType.length];
1✔
7543
                    if (parameterTokens.size() == parameterType.length) {
1✔
7544
                        int index = 0;
1✔
7545
                        for (MethodToken.ParameterToken parameterToken : parameterTokens) {
1✔
7546
                            parameterNames[index] = parameterToken.getName();
1✔
7547
                            parameterModifiers[index] = parameterToken.getModifiers();
1✔
7548
                            index++;
1✔
7549
                        }
1✔
7550
                    }
7551
                    this.defaultValue = defaultValue;
1✔
7552
                }
1✔
7553

7554
                /**
7555
                 * {@inheritDoc}
7556
                 */
7557
                public Generic getReturnType() {
7558
                    return signatureResolution.resolveReturnType(returnTypeDescriptor, typePool, returnTypeAnnotationTokens, this);
1✔
7559
                }
7560

7561
                /**
7562
                 * {@inheritDoc}
7563
                 */
7564
                public TypeList.Generic getExceptionTypes() {
7565
                    return signatureResolution.resolveExceptionTypes(exceptionTypeDescriptors, typePool, exceptionTypeAnnotationTokens, this);
1✔
7566
                }
7567

7568
                /**
7569
                 * {@inheritDoc}
7570
                 */
7571
                public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
7572
                    return new LazyParameterList();
1✔
7573
                }
7574

7575
                /**
7576
                 * {@inheritDoc}
7577
                 */
7578
                public AnnotationList getDeclaredAnnotations() {
7579
                    return LazyAnnotationDescription.asList(typePool, annotationTokens);
1✔
7580
                }
7581

7582
                /**
7583
                 * {@inheritDoc}
7584
                 */
7585
                public String getInternalName() {
7586
                    return internalName;
1✔
7587
                }
7588

7589
                /**
7590
                 * {@inheritDoc}
7591
                 */
7592
                @Nonnull
7593
                public TypeDescription getDeclaringType() {
7594
                    return LazyTypeDescription.this;
1✔
7595
                }
7596

7597
                /**
7598
                 * {@inheritDoc}
7599
                 */
7600
                public int getModifiers() {
7601
                    return modifiers;
1✔
7602
                }
7603

7604
                /**
7605
                 * {@inheritDoc}
7606
                 */
7607
                public TypeList.Generic getTypeVariables() {
7608
                    return signatureResolution.resolveTypeVariables(typePool, this, typeVariableAnnotationTokens, typeVariableBoundAnnotationTokens);
1✔
7609
                }
7610

7611
                /**
7612
                 * {@inheritDoc}
7613
                 */
7614
                @MaybeNull
7615
                public AnnotationValue<?, ?> getDefaultValue() {
7616
                    return defaultValue;
1✔
7617
                }
7618

7619
                /**
7620
                 * {@inheritDoc}
7621
                 */
7622
                @MaybeNull
7623
                public Generic getReceiverType() {
7624
                    if (isStatic()) {
1✔
7625
                        return Generic.UNDEFINED;
1✔
7626
                    } else if (isConstructor()) {
1✔
7627
                        TypeDescription declaringType = getDeclaringType(), enclosingDeclaringType = declaringType.getEnclosingType();
1✔
7628
                        if (enclosingDeclaringType == null) {
1✔
7629
                            return declaringType.isGenerified()
1✔
7630
                                    ? new LazyParameterizedReceiverType(declaringType)
7631
                                    : new LazyNonGenericReceiverType(declaringType);
7632
                        } else {
7633
                            return !declaringType.isStatic() && declaringType.isGenerified()
1✔
7634
                                    ? new LazyParameterizedReceiverType(enclosingDeclaringType)
7635
                                    : new LazyNonGenericReceiverType(enclosingDeclaringType);
7636
                        }
7637
                    } else {
7638
                        return LazyTypeDescription.this.isGenerified()
1✔
7639
                                ? new LazyParameterizedReceiverType()
7640
                                : new LazyNonGenericReceiverType();
7641
                    }
7642
                }
7643

7644
                /**
7645
                 * {@inheritDoc}
7646
                 */
7647
                @MaybeNull
7648
                public String getGenericSignature() {
7649
                    return genericSignature;
1✔
7650
                }
7651

7652
                /**
7653
                 * A lazy list of parameter descriptions for the enclosing method description.
7654
                 */
7655
                private class LazyParameterList extends ParameterList.AbstractBase<ParameterDescription.InDefinedShape> {
1✔
7656

7657
                    /**
7658
                     * {@inheritDoc}
7659
                     */
7660
                    public ParameterDescription.InDefinedShape get(int index) {
7661
                        return new LazyParameterDescription(index);
1✔
7662
                    }
7663

7664
                    /**
7665
                     * {@inheritDoc}
7666
                     */
7667
                    public boolean hasExplicitMetaData() {
7668
                        for (int i = 0; i < size(); i++) {
×
7669
                            if (parameterNames[i] == null || parameterModifiers[i] == null) {
×
7670
                                return false;
×
7671
                            }
7672
                        }
7673
                        return true;
×
7674
                    }
7675

7676
                    /**
7677
                     * {@inheritDoc}
7678
                     */
7679
                    public int size() {
7680
                        return parameterTypeDescriptors.size();
1✔
7681
                    }
7682

7683
                    /**
7684
                     * {@inheritDoc}
7685
                     */
7686
                    public TypeList.Generic asTypeList() {
7687
                        return signatureResolution.resolveParameterTypes(parameterTypeDescriptors, typePool, parameterTypeAnnotationTokens, LazyMethodDescription.this);
1✔
7688
                    }
7689
                }
7690

7691
                /**
7692
                 * A lazy description of a parameters of the enclosing method.
7693
                 */
7694
                private class LazyParameterDescription extends ParameterDescription.InDefinedShape.AbstractBase {
7695

7696
                    /**
7697
                     * The index of the described parameter.
7698
                     */
7699
                    private final int index;
7700

7701
                    /**
7702
                     * Creates a new description for a given parameter of the enclosing method.
7703
                     *
7704
                     * @param index The index of the described parameter.
7705
                     */
7706
                    protected LazyParameterDescription(int index) {
1✔
7707
                        this.index = index;
1✔
7708
                    }
1✔
7709

7710
                    /**
7711
                     * {@inheritDoc}
7712
                     */
7713
                    public MethodDescription.InDefinedShape getDeclaringMethod() {
7714
                        return LazyMethodDescription.this;
1✔
7715
                    }
7716

7717
                    /**
7718
                     * {@inheritDoc}
7719
                     */
7720
                    public int getIndex() {
7721
                        return index;
1✔
7722
                    }
7723

7724
                    /**
7725
                     * {@inheritDoc}
7726
                     */
7727
                    public boolean isNamed() {
7728
                        return parameterNames[index] != null;
1✔
7729
                    }
7730

7731
                    /**
7732
                     * {@inheritDoc}
7733
                     */
7734
                    public boolean hasModifiers() {
7735
                        return parameterModifiers[index] != null;
1✔
7736
                    }
7737

7738
                    /**
7739
                     * {@inheritDoc}
7740
                     */
7741
                    public String getName() {
7742
                        return isNamed()
1✔
7743
                                ? parameterNames[index]
1✔
7744
                                : super.getName();
1✔
7745
                    }
7746

7747
                    /**
7748
                     * {@inheritDoc}
7749
                     */
7750
                    public int getModifiers() {
7751
                        return hasModifiers()
1✔
7752
                                ? parameterModifiers[index]
1✔
7753
                                : super.getModifiers();
1✔
7754
                    }
7755

7756
                    /**
7757
                     * {@inheritDoc}
7758
                     */
7759
                    public Generic getType() {
7760
                        return signatureResolution.resolveParameterTypes(parameterTypeDescriptors, typePool, parameterTypeAnnotationTokens, LazyMethodDescription.this).get(index);
1✔
7761
                    }
7762

7763
                    /**
7764
                     * {@inheritDoc}
7765
                     */
7766
                    public AnnotationList getDeclaredAnnotations() {
7767
                        return LazyAnnotationDescription.asListOfNullable(typePool, parameterAnnotationTokens.get(index));
1✔
7768
                    }
7769
                }
7770

7771
                /**
7772
                 * A lazy description of a parameterized receiver type.
7773
                 */
7774
                private class LazyParameterizedReceiverType extends Generic.OfParameterizedType {
7775

7776
                    /**
7777
                     * The erasure of the type to be represented as a parameterized receiver type.
7778
                     */
7779
                    private final TypeDescription typeDescription;
7780

7781
                    /**
7782
                     * Creates a new lazy parameterized receiver type of the method's declaring type.
7783
                     */
7784
                    protected LazyParameterizedReceiverType() {
7785
                        this(LazyTypeDescription.this);
1✔
7786
                    }
1✔
7787

7788
                    /**
7789
                     * Creates a new lazy parameterized receiver type of the supplied receiver type.
7790
                     *
7791
                     * @param typeDescription The erasure of the type to be represented as a parameterized receiver type.
7792
                     */
7793
                    protected LazyParameterizedReceiverType(TypeDescription typeDescription) {
1✔
7794
                        this.typeDescription = typeDescription;
1✔
7795
                    }
1✔
7796

7797
                    /**
7798
                     * {@inheritDoc}
7799
                     */
7800
                    public TypeList.Generic getTypeArguments() {
7801
                        return new TypeArgumentList(typeDescription.getTypeVariables());
1✔
7802
                    }
7803

7804
                    /**
7805
                     * {@inheritDoc}
7806
                     */
7807
                    @MaybeNull
7808
                    public Generic getOwnerType() {
7809
                        TypeDescription declaringType = typeDescription.getDeclaringType();
1✔
7810
                        if (declaringType == null) {
1✔
7811
                            return Generic.UNDEFINED;
×
7812
                        } else {
7813
                            return !typeDescription.isStatic() && declaringType.isGenerified()
1✔
7814
                                    ? new LazyParameterizedReceiverType(declaringType)
7815
                                    : new LazyNonGenericReceiverType(declaringType);
7816
                        }
7817
                    }
7818

7819
                    /**
7820
                     * {@inheritDoc}
7821
                     */
7822
                    public AnnotationList getDeclaredAnnotations() {
7823
                        return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(getTypePath()));
1✔
7824
                    }
7825

7826
                    /**
7827
                     * Returns the type path for this type.
7828
                     *
7829
                     * @return This type's type path.
7830
                     */
7831
                    private String getTypePath() {
7832
                        StringBuilder typePath = new StringBuilder();
1✔
7833
                        for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
1✔
7834
                            typePath = typePath.append(GenericTypeToken.INNER_CLASS_PATH);
1✔
7835
                        }
7836
                        return typePath.toString();
1✔
7837
                    }
7838

7839
                    /**
7840
                     * {@inheritDoc}
7841
                     */
7842
                    public TypeDescription asErasure() {
7843
                        return typeDescription;
1✔
7844
                    }
7845

7846
                    /**
7847
                     * A list of generic types representing the receiver type's type arguments.
7848
                     */
7849
                    protected class TypeArgumentList extends TypeList.Generic.AbstractBase {
7850

7851
                        /**
7852
                         * The type variables of the represented receiver type.
7853
                         */
7854
                        private final List<? extends Generic> typeVariables;
7855

7856
                        /**
7857
                         * Creates a new type argument list.
7858
                         *
7859
                         * @param typeVariables The type variables of the represented receiver type.
7860
                         */
7861
                        protected TypeArgumentList(List<? extends Generic> typeVariables) {
1✔
7862
                            this.typeVariables = typeVariables;
1✔
7863
                        }
1✔
7864

7865
                        /**
7866
                         * {@inheritDoc}
7867
                         */
7868
                        public Generic get(int index) {
7869
                            return new AnnotatedTypeVariable(typeVariables.get(index), index);
1✔
7870
                        }
7871

7872
                        /**
7873
                         * {@inheritDoc}
7874
                         */
7875
                        public int size() {
7876
                            return typeVariables.size();
1✔
7877
                        }
7878

7879
                        /**
7880
                         * Represents a type variable as a type argument with type annotations.
7881
                         */
7882
                        protected class AnnotatedTypeVariable extends OfTypeVariable {
7883

7884
                            /**
7885
                             * The type variable's description.
7886
                             */
7887
                            private final Generic typeVariable;
7888

7889
                            /**
7890
                             * The type variable's index.
7891
                             */
7892
                            private final int index;
7893

7894
                            /**
7895
                             * Creates a new description of an annotated type variable as a type argument.
7896
                             *
7897
                             * @param typeVariable The type variable's description.
7898
                             * @param index        The type variable's index.
7899
                             */
7900
                            protected AnnotatedTypeVariable(Generic typeVariable, int index) {
1✔
7901
                                this.typeVariable = typeVariable;
1✔
7902
                                this.index = index;
1✔
7903
                            }
1✔
7904

7905
                            /**
7906
                             * {@inheritDoc}
7907
                             */
7908
                            public TypeList.Generic getUpperBounds() {
7909
                                return typeVariable.getUpperBounds();
×
7910
                            }
7911

7912
                            /**
7913
                             * {@inheritDoc}
7914
                             */
7915
                            public TypeVariableSource getTypeVariableSource() {
7916
                                return typeVariable.getTypeVariableSource();
×
7917
                            }
7918

7919
                            /**
7920
                             * {@inheritDoc}
7921
                             */
7922
                            public String getSymbol() {
7923
                                return typeVariable.getSymbol();
1✔
7924
                            }
7925

7926
                            /**
7927
                             * {@inheritDoc}
7928
                             */
7929
                            public AnnotationList getDeclaredAnnotations() {
7930
                                return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(getTypePath()
1✔
7931
                                        + index
7932
                                        + GenericTypeToken.INDEXED_TYPE_DELIMITER));
7933
                            }
7934
                        }
7935
                    }
7936
                }
7937

7938
                /**
7939
                 * A lazy description of a non-generic receiver type.
7940
                 */
7941
                protected class LazyNonGenericReceiverType extends Generic.OfNonGenericType {
7942

7943
                    /**
7944
                     * The type description of the non-generic receiver type.
7945
                     */
7946
                    private final TypeDescription typeDescription;
7947

7948
                    /**
7949
                     * Creates a new non-generic receiver type of the method's declaring type.
7950
                     */
7951
                    protected LazyNonGenericReceiverType() {
7952
                        this(LazyTypeDescription.this);
1✔
7953
                    }
1✔
7954

7955
                    /**
7956
                     * Creates a new non-generic receiver type of the supplied type.
7957
                     *
7958
                     * @param typeDescription The type to represent as a non-generic receiver type.
7959
                     */
7960
                    protected LazyNonGenericReceiverType(TypeDescription typeDescription) {
1✔
7961
                        this.typeDescription = typeDescription;
1✔
7962
                    }
1✔
7963

7964
                    /**
7965
                     * {@inheritDoc}
7966
                     */
7967
                    @MaybeNull
7968
                    public Generic getOwnerType() {
7969
                        TypeDescription declaringType = typeDescription.getDeclaringType();
1✔
7970
                        return declaringType == null
1✔
7971
                                ? Generic.UNDEFINED
7972
                                : new LazyNonGenericReceiverType(declaringType);
7973
                    }
7974

7975
                    /**
7976
                     * {@inheritDoc}
7977
                     */
7978
                    @MaybeNull
7979
                    public Generic getComponentType() {
7980
                        return Generic.UNDEFINED;
×
7981
                    }
7982

7983
                    /**
7984
                     * {@inheritDoc}
7985
                     */
7986
                    public AnnotationList getDeclaredAnnotations() {
7987
                        StringBuilder typePath = new StringBuilder();
1✔
7988
                        for (int index = 0; index < typeDescription.getInnerClassCount(); index++) {
1✔
7989
                            typePath = typePath.append(GenericTypeToken.INNER_CLASS_PATH);
1✔
7990
                        }
7991
                        return LazyAnnotationDescription.asListOfNullable(typePool, receiverTypeAnnotationTokens.get(typePath.toString()));
1✔
7992
                    }
7993

7994
                    /**
7995
                     * {@inheritDoc}
7996
                     */
7997
                    public TypeDescription asErasure() {
7998
                        return typeDescription;
1✔
7999
                    }
8000
                }
8001
            }
8002

8003
            /**
8004
             * A lazy description of a record component.
8005
             */
8006
            private class LazyRecordComponentDescription extends RecordComponentDescription.InDefinedShape.AbstractBase {
8007

8008
                /**
8009
                 * The record component's name.
8010
                 */
8011
                private final String name;
8012

8013
                /**
8014
                 * The record component's descriptor.
8015
                 */
8016
                private final String descriptor;
8017

8018
                /**
8019
                 * The record component's generic signature or {@code null} if the record component is non-generic.
8020
                 */
8021
                @MaybeNull
8022
                private final String genericSignature;
8023

8024
                /**
8025
                 * The record component's signature resolution.
8026
                 */
8027
                private final GenericTypeToken.Resolution.ForRecordComponent signatureResolution;
8028

8029
                /**
8030
                 * A mapping of the record component's type annotations.
8031
                 */
8032
                private final Map<String, List<AnnotationToken>> typeAnnotationTokens;
8033

8034
                /**
8035
                 * A list of the record components annotations.
8036
                 */
8037
                private final List<AnnotationToken> annotationTokens;
8038

8039
                /**
8040
                 * Creates a new lazy description of a record component.
8041
                 *
8042
                 * @param name                 The record component's name.
8043
                 * @param descriptor           The record component's descriptor.
8044
                 * @param genericSignature     The record component's generic signature or {@code null} if the record component is non-generic.
8045
                 * @param signatureResolution  The record component's signature resolution.
8046
                 * @param typeAnnotationTokens A mapping of the record component's type annotations.
8047
                 * @param annotationTokens     A list of the record components annotations.
8048
                 */
8049
                private LazyRecordComponentDescription(String name,
8050
                                                       String descriptor,
8051
                                                       @MaybeNull String genericSignature,
8052
                                                       GenericTypeToken.Resolution.ForRecordComponent signatureResolution,
8053
                                                       Map<String, List<AnnotationToken>> typeAnnotationTokens,
8054
                                                       List<AnnotationToken> annotationTokens) {
×
8055
                    this.name = name;
×
8056
                    this.descriptor = descriptor;
×
8057
                    this.genericSignature = genericSignature;
×
8058
                    this.signatureResolution = signatureResolution;
×
8059
                    this.typeAnnotationTokens = typeAnnotationTokens;
×
8060
                    this.annotationTokens = annotationTokens;
×
8061
                }
×
8062

8063
                /**
8064
                 * {@inheritDoc}
8065
                 */
8066
                public Generic getType() {
8067
                    return signatureResolution.resolveRecordType(descriptor, typePool, typeAnnotationTokens, this);
×
8068
                }
8069

8070
                /**
8071
                 * {@inheritDoc}
8072
                 */
8073
                @Nonnull
8074
                public TypeDescription getDeclaringType() {
8075
                    return LazyTypeDescription.this;
×
8076
                }
8077

8078
                /**
8079
                 * {@inheritDoc}
8080
                 */
8081
                public String getActualName() {
8082
                    return name;
×
8083
                }
8084

8085
                /**
8086
                 * {@inheritDoc}
8087
                 */
8088
                public AnnotationList getDeclaredAnnotations() {
8089
                    return LazyAnnotationDescription.asList(typePool, annotationTokens);
×
8090
                }
8091

8092
                @Override
8093
                @MaybeNull
8094
                public String getGenericSignature() {
8095
                    return genericSignature;
×
8096
                }
8097
            }
8098
        }
8099

8100
        /**
8101
         * A type extractor reads a class file and collects data that is relevant to create a type description.
8102
         */
8103
        protected class TypeExtractor extends ClassVisitor {
8104

8105
            /**
8106
             * The index of a super class's type annotations.
8107
             */
8108
            private static final int SUPER_CLASS_INDEX = -1;
8109

8110
            /**
8111
             * A mask that cuts off pseudo flags beyond the second byte that are inserted by ASM.
8112
             */
8113
            private static final int REAL_MODIFIER_MASK = 0xFFFF;
8114

8115
            /**
8116
             * A mapping of the super types' type annotation tokens by their indices.
8117
             */
8118
            private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> superTypeAnnotationTokens;
8119

8120
            /**
8121
             * A mapping of the type variables' type annotation tokens by their indices.
8122
             */
8123
            private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> typeVariableAnnotationTokens;
8124

8125
            /**
8126
             * A mapping of the type variables' bounds' type annotation tokens by their indices and each variables index.
8127
             */
8128
            private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> typeVariableBoundsAnnotationTokens;
8129

8130
            /**
8131
             * A list of annotation tokens describing annotations that are found on the visited type.
8132
             */
8133
            private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8134

8135
            /**
8136
             * A list of field tokens describing fields that are found on the visited type.
8137
             */
8138
            private final List<LazyTypeDescription.FieldToken> fieldTokens;
8139

8140
            /**
8141
             * A list of method tokens describing annotations that are found on the visited type.
8142
             */
8143
            private final List<LazyTypeDescription.MethodToken> methodTokens;
8144

8145
            /**
8146
             * A list of record component tokens that are found on the visited type.
8147
             */
8148
            private final List<LazyTypeDescription.RecordComponentToken> recordComponentTokens;
8149

8150
            /**
8151
             * The actual modifiers found for this type.
8152
             */
8153
            private int actualModifiers;
8154

8155
            /**
8156
             * The modifiers found for this type.
8157
             */
8158
            private int modifiers;
8159

8160
            /**
8161
             * The internal name found for this type.
8162
             */
8163
            @MaybeNull
8164
            private String internalName;
8165

8166
            /**
8167
             * The internal name of the super type found for this type or {@code null} if no such type exists.
8168
             */
8169
            @MaybeNull
8170
            private String superClassName;
8171

8172
            /**
8173
             * The generic signature of the type or {@code null} if it is not generic.
8174
             */
8175
            @MaybeNull
8176
            private String genericSignature;
8177

8178
            /**
8179
             * A list of internal names of interfaces implemented by this type or {@code null} if no interfaces
8180
             * are implemented.
8181
             */
8182
            @MaybeNull
8183
            private String[] interfaceName;
8184

8185
            /**
8186
             * {@code true} if this type was found to represent an anonymous type.
8187
             */
8188
            private boolean anonymousType;
8189

8190
            /**
8191
             * The nest host that was found in the class file or {@code null} if no nest host was specified.
8192
             */
8193
            @MaybeNull
8194
            private String nestHost;
8195

8196
            /**
8197
             * A list of nest members that were found in the class file.
8198
             */
8199
            private final List<String> nestMembers;
8200

8201
            /**
8202
             * The declaration context found for this type.
8203
             */
8204
            private LazyTypeDescription.TypeContainment typeContainment;
8205

8206
            /**
8207
             * The binary name of this type's declaring type or {@code null} if no such type exists.
8208
             */
8209
            @MaybeNull
8210
            private String declaringTypeName;
8211

8212
            /**
8213
             * A list of descriptors representing the types that are declared by the parsed type.
8214
             */
8215
            private final List<String> declaredTypes;
8216

8217
            /**
8218
             * A list of internal names of permitted subclasses.
8219
             */
8220
            private final List<String> permittedSubclasses;
8221

8222
            /**
8223
             * The discovered class file version or {@code null} if no version was yet discovered.
8224
             */
8225
            @MaybeNull
8226
            private ClassFileVersion classFileVersion;
8227

8228
            /**
8229
             * Creates a new type extractor.
8230
             */
8231
            protected TypeExtractor() {
1✔
8232
                super(OpenedClassReader.ASM_API);
1✔
8233
                superTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8234
                typeVariableAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8235
                typeVariableBoundsAnnotationTokens = new HashMap<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>>();
1✔
8236
                annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
8237
                fieldTokens = new ArrayList<LazyTypeDescription.FieldToken>();
1✔
8238
                methodTokens = new ArrayList<LazyTypeDescription.MethodToken>();
1✔
8239
                recordComponentTokens = new ArrayList<LazyTypeDescription.RecordComponentToken>();
1✔
8240
                anonymousType = false;
1✔
8241
                typeContainment = LazyTypeDescription.TypeContainment.SelfContained.INSTANCE;
1✔
8242
                nestMembers = new ArrayList<String>();
1✔
8243
                declaredTypes = new ArrayList<String>();
1✔
8244
                permittedSubclasses = new ArrayList<String>();
1✔
8245
            }
1✔
8246

8247
            @Override
8248
            @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "The array is not modified by class contract.")
8249
            public void visit(int classFileVersion,
8250
                              int modifiers,
8251
                              String internalName,
8252
                              @MaybeNull String genericSignature,
8253
                              @MaybeNull String superClassName,
8254
                              @MaybeNull String[] interfaceName) {
8255
                this.modifiers = modifiers & REAL_MODIFIER_MASK;
1✔
8256
                actualModifiers = modifiers;
1✔
8257
                this.internalName = internalName;
1✔
8258
                this.genericSignature = genericSignature;
1✔
8259
                this.superClassName = superClassName;
1✔
8260
                this.interfaceName = interfaceName;
1✔
8261
                this.classFileVersion = ClassFileVersion.ofMinorMajor(classFileVersion);
1✔
8262
            }
1✔
8263

8264
            @Override
8265
            public void visitOuterClass(@MaybeNull String typeName, @MaybeNull String methodName, String methodDescriptor) {
8266
                if (methodName != null && !methodName.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) {
1✔
8267
                    typeContainment = new LazyTypeDescription.TypeContainment.WithinMethod(typeName, methodName, methodDescriptor);
1✔
8268
                } else if (typeName != null) {
1✔
8269
                    typeContainment = new LazyTypeDescription.TypeContainment.WithinType(typeName, true);
1✔
8270
                }
8271
            }
1✔
8272

8273
            @Override
8274
            public void visitInnerClass(String internalName, @MaybeNull String outerName, @MaybeNull String innerName, int modifiers) {
8275
                if (internalName.equals(this.internalName)) {
1✔
8276
                    if (outerName != null) {
1✔
8277
                        declaringTypeName = outerName;
1✔
8278
                        if (typeContainment.isSelfContained()) {
1✔
8279
                            typeContainment = new LazyTypeDescription.TypeContainment.WithinType(outerName, false);
1✔
8280
                        }
8281
                    }
8282
                    if (innerName == null && !typeContainment.isSelfContained()) { // Some compilers define this property inconsistently.
1✔
8283
                        anonymousType = true;
1✔
8284
                    }
8285
                    this.modifiers = modifiers & REAL_MODIFIER_MASK;
1✔
8286
                } else if (outerName != null && innerName != null && outerName.equals(this.internalName)) {
1✔
8287
                    declaredTypes.add("L" + internalName + ";");
1✔
8288
                }
8289
            }
1✔
8290

8291
            @Override
8292
            public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, @MaybeNull TypePath typePath, String descriptor, boolean visible) {
8293
                AnnotationRegistrant annotationRegistrant;
8294
                TypeReference typeReference = new TypeReference(rawTypeReference);
1✔
8295
                switch (typeReference.getSort()) {
1✔
8296
                    case TypeReference.CLASS_EXTENDS:
8297
                        annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex(descriptor,
1✔
8298
                                typePath,
8299
                                typeReference.getSuperTypeIndex(),
1✔
8300
                                superTypeAnnotationTokens);
8301
                        break;
1✔
8302
                    case TypeReference.CLASS_TYPE_PARAMETER:
8303
                        annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex(descriptor,
1✔
8304
                                typePath,
8305
                                typeReference.getTypeParameterIndex(),
1✔
8306
                                typeVariableAnnotationTokens);
8307
                        break;
1✔
8308
                    case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
8309
                        annotationRegistrant = new AnnotationRegistrant.ForTypeVariable.WithIndex.DoubleIndexed(descriptor,
1✔
8310
                                typePath,
8311
                                typeReference.getTypeParameterBoundIndex(),
1✔
8312
                                typeReference.getTypeParameterIndex(),
1✔
8313
                                typeVariableBoundsAnnotationTokens);
8314
                        break;
1✔
8315
                    default:
8316
                        throw new IllegalArgumentException("Unexpected type reference: " + typeReference.getSort());
×
8317
                }
8318
                return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8319
            }
8320

8321
            @Override
8322
            public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8323
                return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8324
            }
8325

8326
            @Override
8327
            public FieldVisitor visitField(int modifiers, String internalName, String descriptor, @MaybeNull String genericSignature, @MaybeNull Object value) {
8328
                return new FieldExtractor(modifiers & REAL_MODIFIER_MASK, internalName, descriptor, genericSignature);
1✔
8329
            }
8330

8331
            @Override
8332
            @MaybeNull
8333
            public MethodVisitor visitMethod(int modifiers, String internalName, String descriptor, @MaybeNull String genericSignature, @MaybeNull String[] exceptionName) {
8334
                return internalName.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)
1✔
8335
                        ? IGNORE_METHOD
1✔
8336
                        : new MethodExtractor(modifiers & REAL_MODIFIER_MASK, internalName, descriptor, genericSignature, exceptionName);
8337
            }
8338

8339
            @Override
8340
            public void visitNestHost(String nestHost) {
8341
                this.nestHost = nestHost;
×
8342
            }
×
8343

8344
            @Override
8345
            public void visitNestMember(String nestMember) {
8346
                nestMembers.add(nestMember);
×
8347
            }
×
8348

8349
            @Override
8350
            public RecordComponentVisitor visitRecordComponent(String name, String descriptor, @MaybeNull String signature) {
8351
                return new RecordComponentExtractor(name, descriptor, signature);
×
8352
            }
8353

8354
            @Override
8355
            public void visitPermittedSubclass(String permittedSubclass) {
8356
                permittedSubclasses.add(permittedSubclass);
×
8357
            }
×
8358

8359
            /**
8360
             * Creates a type description from all data that is currently collected. This method should only be invoked
8361
             * after a class file was parsed fully.
8362
             *
8363
             * @return A type description reflecting the data that was collected by this instance.
8364
             */
8365
            protected TypeDescription toTypeDescription() {
8366
                if (internalName == null || classFileVersion == null) {
1✔
8367
                    throw new IllegalStateException("Internal name or class file version were not set");
×
8368
                }
8369
                Map<String, List<LazyTypeDescription.AnnotationToken>> superClassAnnotationTokens = superTypeAnnotationTokens.remove(SUPER_CLASS_INDEX);
1✔
8370
                return new LazyTypeDescription(Default.this,
1✔
8371
                        actualModifiers,
8372
                        modifiers,
8373
                        internalName,
8374
                        superClassName,
8375
                        interfaceName,
8376
                        genericSignature,
8377
                        typeContainment,
8378
                        declaringTypeName,
8379
                        declaredTypes,
8380
                        anonymousType,
8381
                        nestHost,
8382
                        nestMembers,
8383
                        superClassAnnotationTokens == null
8384
                                ? Collections.<String, List<LazyTypeDescription.AnnotationToken>>emptyMap()
1✔
8385
                                : superClassAnnotationTokens,
8386
                        superTypeAnnotationTokens,
8387
                        typeVariableAnnotationTokens,
8388
                        typeVariableBoundsAnnotationTokens,
8389
                        annotationTokens,
8390
                        fieldTokens,
8391
                        methodTokens,
8392
                        recordComponentTokens,
8393
                        permittedSubclasses,
8394
                        classFileVersion);
8395
            }
8396

8397
            /**
8398
             * An annotation extractor reads an annotation found in a class field an collects data that
8399
             * is relevant to creating a related annotation description.
8400
             */
8401
            protected class AnnotationExtractor extends AnnotationVisitor {
8402

8403
                /**
8404
                 * The annotation registrant to register found annotation values on.
8405
                 */
8406
                private final AnnotationRegistrant annotationRegistrant;
8407

8408
                /**
8409
                 * A locator for the component type of any found annotation value.
8410
                 */
8411
                private final ComponentTypeLocator componentTypeLocator;
8412

8413
                /**
8414
                 * Creates a new annotation extractor for a byte code element without an index.
8415
                 *
8416
                 * @param descriptor           The annotation descriptor.
8417
                 * @param annotationTokens     The collection for storing any discovered annotation tokens.
8418
                 * @param componentTypeLocator The component type locator to use.
8419
                 */
8420
                protected AnnotationExtractor(String descriptor, List<LazyTypeDescription.AnnotationToken> annotationTokens, ComponentTypeLocator componentTypeLocator) {
8421
                    this(new AnnotationRegistrant.ForByteCodeElement(descriptor, annotationTokens), componentTypeLocator);
1✔
8422
                }
1✔
8423

8424
                /**
8425
                 * Creates a new annotation extractor for a byte code element with an index.
8426
                 *
8427
                 * @param descriptor           The annotation descriptor.
8428
                 * @param index                The index of the element for which the annotations are collected.
8429
                 * @param annotationTokens     The collection for storing any discovered annotation tokens.
8430
                 * @param componentTypeLocator The component type locator to use.
8431
                 */
8432
                protected AnnotationExtractor(String descriptor,
8433
                                              int index,
8434
                                              Map<Integer, List<LazyTypeDescription.AnnotationToken>> annotationTokens,
8435
                                              ComponentTypeLocator componentTypeLocator) {
8436
                    this(new AnnotationRegistrant.ForByteCodeElement.WithIndex(descriptor, index, annotationTokens), componentTypeLocator);
1✔
8437
                }
1✔
8438

8439
                /**
8440
                 * Creates a new annotation extractor.
8441
                 *
8442
                 * @param annotationRegistrant The annotation registrant to register found annotation values on.
8443
                 * @param componentTypeLocator A locator for the component type of any found annotation value.
8444
                 */
8445
                protected AnnotationExtractor(AnnotationRegistrant annotationRegistrant, ComponentTypeLocator componentTypeLocator) {
1✔
8446
                    super(OpenedClassReader.ASM_API);
1✔
8447
                    this.annotationRegistrant = annotationRegistrant;
1✔
8448
                    this.componentTypeLocator = componentTypeLocator;
1✔
8449
                }
1✔
8450

8451
                @Override
8452
                public void visit(String name, Object value) {
8453
                    if (value instanceof Type) {
1✔
8454
                        Type type = (Type) value;
1✔
8455
                        annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForTypeValue(Default.this, type.getSort() == Type.ARRAY
1✔
8456
                                ? type.getInternalName().replace('/', '.')
1✔
8457
                                : type.getClassName()));
1✔
8458
                    } else {
1✔
8459
                        annotationRegistrant.register(name, AnnotationValue.ForConstant.of(value));
1✔
8460
                    }
8461
                }
1✔
8462

8463
                @Override
8464
                public void visitEnum(String name, String descriptor, String value) {
8465
                    annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForEnumerationValue(Default.this,
1✔
8466
                            descriptor.substring(1, descriptor.length() - 1).replace('/', '.'),
1✔
8467
                            value));
8468
                }
1✔
8469

8470
                @Override
8471
                public AnnotationVisitor visitAnnotation(String name, String descriptor) {
8472
                    return new AnnotationExtractor(new AnnotationLookup(descriptor, name), new ComponentTypeLocator.ForAnnotationProperty(TypePool.Default.this, descriptor));
1✔
8473
                }
8474

8475
                @Override
8476
                public AnnotationVisitor visitArray(String name) {
8477
                    return new AnnotationExtractor(new ArrayLookup(name, componentTypeLocator.bind(name)), ComponentTypeLocator.Illegal.INSTANCE);
1✔
8478
                }
8479

8480
                @Override
8481
                public void visitEnd() {
8482
                    annotationRegistrant.onComplete();
1✔
8483
                }
1✔
8484

8485
                /**
8486
                 * An annotation registrant for registering values of an array.
8487
                 */
8488
                protected class ArrayLookup implements AnnotationRegistrant {
8489

8490
                    /**
8491
                     * The name of the annotation property the collected array is representing.
8492
                     */
8493
                    private final String name;
8494

8495
                    /**
8496
                     * A lazy reference to resolve the component type of the collected array.
8497
                     */
8498
                    private final ComponentTypeReference componentTypeReference;
8499

8500
                    /**
8501
                     * A list of all annotation values that are found on this array.
8502
                     */
8503
                    private final List<AnnotationValue<?, ?>> values;
8504

8505
                    /**
8506
                     * Creates a new annotation registrant for an array lookup.
8507
                     *
8508
                     * @param name                   The name of the annotation property the collected array is representing.
8509
                     * @param componentTypeReference A lazy reference to resolve the component type of the collected array.
8510
                     */
8511
                    private ArrayLookup(String name, ComponentTypeReference componentTypeReference) {
1✔
8512
                        this.name = name;
1✔
8513
                        this.componentTypeReference = componentTypeReference;
1✔
8514
                        values = new ArrayList<AnnotationValue<?, ?>>();
1✔
8515
                    }
1✔
8516

8517
                    /**
8518
                     * {@inheritDoc}
8519
                     */
8520
                    public void register(String ignored, AnnotationValue<?, ?> annotationValue) {
8521
                        values.add(annotationValue);
1✔
8522
                    }
1✔
8523

8524
                    /**
8525
                     * {@inheritDoc}
8526
                     */
8527
                    public void onComplete() {
8528
                        annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForArray(Default.this,
1✔
8529
                                componentTypeReference,
8530
                                values));
8531
                    }
1✔
8532
                }
8533

8534
                /**
8535
                 * An annotation registrant for registering the values on an array that is itself an annotation property.
8536
                 */
8537
                protected class AnnotationLookup implements AnnotationRegistrant {
8538

8539
                    /**
8540
                     * The descriptor of the original annotation for which the annotation values are looked up.
8541
                     */
8542
                    private final String descriptor;
8543

8544
                    /**
8545
                     * The name of the original annotation for which the annotation values are looked up.
8546
                     */
8547
                    private final String name;
8548

8549
                    /**
8550
                     * This annotation's values mapped by their attribute name.
8551
                     */
8552
                    private final Map<String, AnnotationValue<?, ?>> values;
8553

8554
                    /**
8555
                     * Creates a new annotation registrant for a recursive annotation lookup.
8556
                     *
8557
                     * @param descriptor The descriptor of the original annotation for which the annotation values are looked up.
8558
                     * @param name       The name of the original annotation for which the annotation values are looked up.
8559
                     */
8560
                    protected AnnotationLookup(String descriptor, String name) {
1✔
8561
                        this.descriptor = descriptor;
1✔
8562
                        this.name = name;
1✔
8563
                        values = new HashMap<String, AnnotationValue<?, ?>>();
1✔
8564
                    }
1✔
8565

8566
                    /**
8567
                     * {@inheritDoc}
8568
                     */
8569
                    public void register(String name, AnnotationValue<?, ?> annotationValue) {
8570
                        values.put(name, annotationValue);
1✔
8571
                    }
1✔
8572

8573
                    /**
8574
                     * {@inheritDoc}
8575
                     */
8576
                    public void onComplete() {
8577
                        annotationRegistrant.register(name, new LazyTypeDescription.LazyAnnotationValue.ForAnnotationValue(Default.this,
1✔
8578
                                new LazyTypeDescription.AnnotationToken(descriptor, values)));
8579
                    }
1✔
8580
                }
8581
            }
8582

8583
            /**
8584
             * A field extractor reads a field within a class file and collects data that is relevant
8585
             * to creating a related field description.
8586
             */
8587
            protected class FieldExtractor extends FieldVisitor {
8588

8589
                /**
8590
                 * The modifiers found on the field.
8591
                 */
8592
                private final int modifiers;
8593

8594
                /**
8595
                 * The name of the field.
8596
                 */
8597
                private final String internalName;
8598

8599
                /**
8600
                 * The descriptor of the field type.
8601
                 */
8602
                private final String descriptor;
8603

8604
                /**
8605
                 * The generic signature of the field or {@code null} if it is not generic.
8606
                 */
8607
                @MaybeNull
8608
                private final String genericSignature;
8609

8610
                /**
8611
                 * A mapping of the field type's type annotations.
8612
                 */
8613
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> typeAnnotationTokens;
8614

8615
                /**
8616
                 * A list of annotation tokens found for this field.
8617
                 */
8618
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8619

8620
                /**
8621
                 * Creates a new field extractor.
8622
                 *
8623
                 * @param modifiers        The modifiers found for this field.
8624
                 * @param internalName     The name of the field.
8625
                 * @param descriptor       The descriptor of the field type.
8626
                 * @param genericSignature The generic signature of the field or {@code null} if it is not generic.
8627
                 */
8628
                protected FieldExtractor(int modifiers,
8629
                                         String internalName,
8630
                                         String descriptor,
8631
                                         @MaybeNull String genericSignature) {
1✔
8632
                    super(OpenedClassReader.ASM_API);
1✔
8633
                    this.modifiers = modifiers;
1✔
8634
                    this.internalName = internalName;
1✔
8635
                    this.descriptor = descriptor;
1✔
8636
                    this.genericSignature = genericSignature;
1✔
8637
                    typeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
8638
                    annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
8639
                }
1✔
8640

8641
                @Override
8642
                @MaybeNull
8643
                public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, @MaybeNull TypePath typePath, String descriptor, boolean visible) {
8644
                    AnnotationRegistrant annotationRegistrant;
8645
                    TypeReference typeReference = new TypeReference(rawTypeReference);
1✔
8646
                    switch (typeReference.getSort()) {
1✔
8647
                        case TypeReference.FIELD:
8648
                            annotationRegistrant = new AnnotationRegistrant.ForTypeVariable(descriptor, typePath, typeAnnotationTokens);
1✔
8649
                            break;
1✔
8650
                        default:
8651
                            throw new IllegalStateException("Unexpected type reference on field: " + typeReference.getSort());
×
8652
                    }
8653
                    return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8654
                }
8655

8656
                @Override
8657
                public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8658
                    return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8659
                }
8660

8661
                @Override
8662
                public void visitEnd() {
8663
                    fieldTokens.add(new LazyTypeDescription.FieldToken(internalName,
1✔
8664
                            modifiers,
8665
                            descriptor,
8666
                            genericSignature,
8667
                            typeAnnotationTokens,
8668
                            annotationTokens));
8669
                }
1✔
8670
            }
8671

8672
            /**
8673
             * A method extractor reads a method within a class file and collects data that is relevant
8674
             * to creating a related method description.
8675
             */
8676
            protected class MethodExtractor extends MethodVisitor implements AnnotationRegistrant {
8677

8678
                /**
8679
                 * The modifiers found for this method.
8680
                 */
8681
                private final int modifiers;
8682

8683
                /**
8684
                 * The internal name found for this method.
8685
                 */
8686
                private final String internalName;
8687

8688
                /**
8689
                 * The descriptor found for this method.
8690
                 */
8691
                private final String descriptor;
8692

8693
                /**
8694
                 * The generic signature of the method or {@code null} if it is not generic.
8695
                 */
8696
                @MaybeNull
8697
                private final String genericSignature;
8698

8699
                /**
8700
                 * An array of internal names of the exceptions of the found method
8701
                 * or {@code null} if there are no such exceptions.
8702
                 */
8703
                @MaybeNull
8704
                private final String[] exceptionName;
8705

8706
                /**
8707
                 * A mapping of the method's type variables' type annotations by their indices.
8708
                 */
8709
                private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> typeVariableAnnotationTokens;
8710

8711
                /**
8712
                 * A mapping of the method's type variables' bounds' type annotations by their indices and each variable's index.
8713
                 */
8714
                private final Map<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>> typeVariableBoundAnnotationTokens;
8715

8716
                /**
8717
                 * A mapping of the method's return type's type annotations.
8718
                 */
8719
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> returnTypeAnnotationTokens;
8720

8721
                /**
8722
                 * A mapping of the parameters' type annotations by their indices.
8723
                 */
8724
                private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> parameterTypeAnnotationTokens;
8725

8726
                /**
8727
                 * A mapping of the exception types' type annotations by their indices.
8728
                 */
8729
                private final Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>> exceptionTypeAnnotationTokens;
8730

8731
                /**
8732
                 * A mapping of the receiver type's type annotations.
8733
                 */
8734
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> receiverTypeAnnotationTokens;
8735

8736
                /**
8737
                 * A list of annotation tokens declared on the found method.
8738
                 */
8739
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8740

8741
                /**
8742
                 * A mapping of parameter indices to annotation tokens found for the parameters at these indices.
8743
                 */
8744
                private final Map<Integer, List<LazyTypeDescription.AnnotationToken>> parameterAnnotationTokens;
8745

8746
                /**
8747
                 * A list of tokens representing meta information of a parameter as it is available for method's
8748
                 * that are compiled in the Java 8 version format.
8749
                 */
8750
                private final List<LazyTypeDescription.MethodToken.ParameterToken> parameterTokens;
8751

8752
                /**
8753
                 * A bag of parameter meta information representing debugging information which allows to extract
8754
                 * a method's parameter names.
8755
                 */
8756
                private final ParameterBag legacyParameterBag;
8757

8758
                /**
8759
                 * The first label that is found in the method's body, if any, denoting the start of the method.
8760
                 * This label can be used to identify names of local variables that describe the method's parameters.
8761
                 */
8762
                @MaybeNull
8763
                private Label firstLabel;
8764

8765
                /**
8766
                 * A shift index for visible parameters that indicates a deviation of the actual parameter index.
8767
                 */
8768
                private int visibleParameterShift;
8769

8770
                /**
8771
                 * A shift index for invisible parameters that indicates a deviation of the actual parameter index.
8772
                 */
8773
                private int invisibleParameterShift;
8774

8775
                /**
8776
                 * The default value of the found method or {@code null} if no such value exists.
8777
                 */
8778
                @MaybeNull
8779
                private AnnotationValue<?, ?> defaultValue;
8780

8781
                /**
8782
                 * Creates a method extractor.
8783
                 *
8784
                 * @param modifiers        The modifiers found for this method.
8785
                 * @param internalName     The internal name found for this method.
8786
                 * @param descriptor       The descriptor found for this method.
8787
                 * @param genericSignature The generic signature of the method or {@code null} if it is not generic.
8788
                 * @param exceptionName    An array of internal names of the exceptions of the found method
8789
                 *                         or {@code null} if there are no such exceptions.
8790
                 */
8791
                protected MethodExtractor(int modifiers,
8792
                                          String internalName,
8793
                                          String descriptor,
8794
                                          @MaybeNull String genericSignature,
8795
                                          @MaybeNull String[] exceptionName) {
1✔
8796
                    super(OpenedClassReader.ASM_API);
1✔
8797
                    this.modifiers = modifiers;
1✔
8798
                    this.internalName = internalName;
1✔
8799
                    this.descriptor = descriptor;
1✔
8800
                    this.genericSignature = genericSignature;
1✔
8801
                    this.exceptionName = exceptionName;
1✔
8802
                    typeVariableAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8803
                    typeVariableBoundAnnotationTokens = new HashMap<Integer, Map<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>>();
1✔
8804
                    returnTypeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
8805
                    parameterTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8806
                    exceptionTypeAnnotationTokens = new HashMap<Integer, Map<String, List<LazyTypeDescription.AnnotationToken>>>();
1✔
8807
                    receiverTypeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
1✔
8808
                    annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
1✔
8809
                    parameterAnnotationTokens = new HashMap<Integer, List<LazyTypeDescription.AnnotationToken>>();
1✔
8810
                    parameterTokens = new ArrayList<LazyTypeDescription.MethodToken.ParameterToken>();
1✔
8811
                    legacyParameterBag = new ParameterBag(Type.getMethodType(descriptor).getArgumentTypes());
1✔
8812
                }
1✔
8813

8814
                @Override
8815
                @MaybeNull
8816
                public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
8817
                    AnnotationRegistrant annotationRegistrant;
8818
                    TypeReference typeReference = new TypeReference(rawTypeReference);
1✔
8819
                    switch (typeReference.getSort()) {
1✔
8820
                        case TypeReference.METHOD_TYPE_PARAMETER:
8821
                            annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
1✔
8822
                                    typePath,
8823
                                    typeReference.getTypeParameterIndex(),
1✔
8824
                                    typeVariableAnnotationTokens);
8825
                            break;
1✔
8826
                        case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
8827
                            annotationRegistrant = new ForTypeVariable.WithIndex.DoubleIndexed(descriptor,
1✔
8828
                                    typePath,
8829
                                    typeReference.getTypeParameterBoundIndex(),
1✔
8830
                                    typeReference.getTypeParameterIndex(),
1✔
8831
                                    typeVariableBoundAnnotationTokens);
8832
                            break;
1✔
8833
                        case TypeReference.METHOD_RETURN:
8834
                            annotationRegistrant = new ForTypeVariable(descriptor,
1✔
8835
                                    typePath,
8836
                                    returnTypeAnnotationTokens);
8837
                            break;
1✔
8838
                        case TypeReference.METHOD_FORMAL_PARAMETER:
8839
                            annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
1✔
8840
                                    typePath,
8841
                                    typeReference.getFormalParameterIndex(),
1✔
8842
                                    parameterTypeAnnotationTokens);
8843
                            break;
1✔
8844
                        case TypeReference.THROWS:
8845
                            annotationRegistrant = new ForTypeVariable.WithIndex(descriptor,
1✔
8846
                                    typePath,
8847
                                    typeReference.getExceptionIndex(),
1✔
8848
                                    exceptionTypeAnnotationTokens);
8849
                            break;
1✔
8850
                        case TypeReference.METHOD_RECEIVER:
8851
                            annotationRegistrant = new ForTypeVariable(descriptor,
1✔
8852
                                    typePath,
8853
                                    receiverTypeAnnotationTokens);
8854
                            break;
1✔
8855
                        case TypeReference.FIELD: // Emitted by mistake by javac for records in Java 14.
8856
                            return null;
×
8857
                        default:
8858
                            throw new IllegalStateException("Unexpected type reference on method: " + typeReference.getSort());
×
8859
                    }
8860
                    return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8861
                }
8862

8863
                @Override
8864
                public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
8865
                    return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
1✔
8866
                }
8867

8868
                @Override
8869
                public void visitAnnotableParameterCount(int count, boolean visible) {
8870
                    if (visible) {
1✔
8871
                        visibleParameterShift = Type.getMethodType(descriptor).getArgumentTypes().length - count;
1✔
8872
                    } else {
8873
                        invisibleParameterShift = Type.getMethodType(descriptor).getArgumentTypes().length - count;
×
8874
                    }
8875
                }
1✔
8876

8877
                @Override
8878
                public AnnotationVisitor visitParameterAnnotation(int index, String descriptor, boolean visible) {
8879
                    return new AnnotationExtractor(descriptor,
1✔
8880
                            index + (visible ? visibleParameterShift : invisibleParameterShift),
8881
                            parameterAnnotationTokens,
8882
                            new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
8883
                }
8884

8885
                @Override
8886
                public void visitLabel(Label label) {
8887
                    if (readerMode.isExtended() && firstLabel == null) {
1✔
8888
                        firstLabel = label;
1✔
8889
                    }
8890
                }
1✔
8891

8892
                @Override
8893
                public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int offset) {
8894
                    if (readerMode.isExtended() && start == firstLabel) {
1✔
8895
                        legacyParameterBag.register(offset, name);
1✔
8896
                    }
8897
                }
1✔
8898

8899
                @Override
8900
                public void visitParameter(String name, int modifiers) {
8901
                    parameterTokens.add(new LazyTypeDescription.MethodToken.ParameterToken(name, modifiers));
1✔
8902
                }
1✔
8903

8904
                @Override
8905
                public AnnotationVisitor visitAnnotationDefault() {
8906
                    return new AnnotationExtractor(this, new ComponentTypeLocator.ForArrayType(descriptor));
1✔
8907
                }
8908

8909
                /**
8910
                 * {@inheritDoc}
8911
                 */
8912
                public void register(String ignored, AnnotationValue<?, ?> annotationValue) {
8913
                    defaultValue = annotationValue;
1✔
8914
                }
1✔
8915

8916
                /**
8917
                 * {@inheritDoc}
8918
                 */
8919
                public void onComplete() {
8920
                    /* do nothing, as the register method is called at most once for default values */
8921
                }
1✔
8922

8923
                @Override
8924
                public void visitEnd() {
8925
                    methodTokens.add(new LazyTypeDescription.MethodToken(internalName,
1✔
8926
                            modifiers,
8927
                            descriptor,
8928
                            genericSignature,
8929
                            exceptionName,
8930
                            typeVariableAnnotationTokens,
8931
                            typeVariableBoundAnnotationTokens,
8932
                            returnTypeAnnotationTokens,
8933
                            parameterTypeAnnotationTokens,
8934
                            exceptionTypeAnnotationTokens,
8935
                            receiverTypeAnnotationTokens,
8936
                            annotationTokens,
8937
                            parameterAnnotationTokens,
8938
                            parameterTokens.isEmpty()
1✔
8939
                                    ? legacyParameterBag.resolve((modifiers & Opcodes.ACC_STATIC) != 0)
1✔
8940
                                    : parameterTokens,
8941
                            defaultValue));
8942
                }
1✔
8943
            }
8944

8945
            /**
8946
             * A record component extractor reads a record component's information within a class file.
8947
             */
8948
            protected class RecordComponentExtractor extends RecordComponentVisitor {
8949

8950
                /**
8951
                 * The record component's name.
8952
                 */
8953
                private final String name;
8954

8955
                /**
8956
                 * The record component's descriptor.
8957
                 */
8958
                private final String descriptor;
8959

8960
                /**
8961
                 * The record component's generic signature.
8962
                 */
8963
                @MaybeNull
8964
                private final String genericSignature;
8965

8966
                /**
8967
                 * A mapping of the record component's type annotations.
8968
                 */
8969
                private final Map<String, List<LazyTypeDescription.AnnotationToken>> typeAnnotationTokens;
8970

8971
                /**
8972
                 * A list of the record component's annotations.
8973
                 */
8974
                private final List<LazyTypeDescription.AnnotationToken> annotationTokens;
8975

8976
                /**
8977
                 * Creates a new record component extractor.
8978
                 *
8979
                 * @param name             The record component's name.
8980
                 * @param descriptor       The record component's descriptor.
8981
                 * @param genericSignature The record component's generic signature.
8982
                 */
8983
                protected RecordComponentExtractor(String name, String descriptor, @MaybeNull String genericSignature) {
×
8984
                    super(OpenedClassReader.ASM_API);
×
8985
                    this.name = name;
×
8986
                    this.descriptor = descriptor;
×
8987
                    this.genericSignature = genericSignature;
×
8988
                    typeAnnotationTokens = new HashMap<String, List<LazyTypeDescription.AnnotationToken>>();
×
8989
                    annotationTokens = new ArrayList<LazyTypeDescription.AnnotationToken>();
×
8990
                }
×
8991

8992
                @Override
8993
                public AnnotationVisitor visitTypeAnnotation(int rawTypeReference, TypePath typePath, String descriptor, boolean visible) {
8994
                    AnnotationRegistrant annotationRegistrant;
8995
                    TypeReference typeReference = new TypeReference(rawTypeReference);
×
8996
                    switch (typeReference.getSort()) {
×
8997
                        case TypeReference.FIELD:
8998
                            annotationRegistrant = new AnnotationRegistrant.ForTypeVariable(descriptor, typePath, typeAnnotationTokens);
×
8999
                            break;
×
9000
                        default:
9001
                            throw new IllegalStateException("Unexpected type reference on record component: " + typeReference.getSort());
×
9002
                    }
9003
                    return new AnnotationExtractor(annotationRegistrant, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
×
9004
                }
9005

9006
                @Override
9007
                public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
9008
                    return new AnnotationExtractor(descriptor, annotationTokens, new ComponentTypeLocator.ForAnnotationProperty(Default.this, descriptor));
×
9009
                }
9010

9011
                @Override
9012
                public void visitEnd() {
9013
                    recordComponentTokens.add(new LazyTypeDescription.RecordComponentToken(name,
×
9014
                            descriptor,
9015
                            genericSignature,
9016
                            typeAnnotationTokens,
9017
                            annotationTokens));
9018
                }
×
9019
            }
9020
        }
9021
    }
9022

9023
    /**
9024
     * 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.
9025
     */
9026
    @HashCodeAndEqualsPlugin.Enhance
9027
    class LazyFacade extends AbstractBase {
9028

9029
        /**
9030
         * The type pool to delegate to.
9031
         */
9032
        private final TypePool typePool;
9033

9034
        /**
9035
         * Creates a lazy facade for a type pool.
9036
         *
9037
         * @param typePool The type pool to delegate to.
9038
         */
9039
        public LazyFacade(TypePool typePool) {
9040
            super(CacheProvider.NoOp.INSTANCE);
1✔
9041
            this.typePool = typePool;
1✔
9042
        }
1✔
9043

9044
        @Override
9045
        protected Resolution doDescribe(String name) {
9046
            return new LazyResolution(typePool, name);
1✔
9047
        }
9048

9049
        /**
9050
         * {@inheritDoc}
9051
         */
9052
        public void clear() {
9053
            typePool.clear();
1✔
9054
        }
1✔
9055

9056
        /**
9057
         * The lazy resolution for a lazy facade for a type pool.
9058
         */
9059
        @HashCodeAndEqualsPlugin.Enhance
9060
        protected static class LazyResolution implements Resolution {
9061

9062
            /**
9063
             * The type pool to delegate to.
9064
             */
9065
            private final TypePool typePool;
9066

9067
            /**
9068
             * The name of the type that is represented by this resolution.
9069
             */
9070
            private final String name;
9071

9072
            /**
9073
             * Creates a lazy resolution for a lazy facade for a type pool.
9074
             *
9075
             * @param typePool The type pool to delegate to.
9076
             * @param name     The name of the type that is represented by this resolution.
9077
             */
9078
            protected LazyResolution(TypePool typePool, String name) {
1✔
9079
                this.typePool = typePool;
1✔
9080
                this.name = name;
1✔
9081
            }
1✔
9082

9083
            /**
9084
             * {@inheritDoc}
9085
             */
9086
            public boolean isResolved() {
9087
                return typePool.describe(name).isResolved();
1✔
9088
            }
9089

9090
            /**
9091
             * {@inheritDoc}
9092
             */
9093
            public TypeDescription resolve() {
9094
                return new LazyTypeDescription(typePool, name);
1✔
9095
            }
9096
        }
9097

9098
        /**
9099
         * A description of a type that delegates to another type pool once a property that is not the name is resolved.
9100
         */
9101
        protected static class LazyTypeDescription extends TypeDescription.AbstractBase.OfSimpleType.WithDelegation {
9102

9103
            /**
9104
             * The type pool to delegate to.
9105
             */
9106
            private final TypePool typePool;
9107

9108
            /**
9109
             * The name of the type that is represented by this resolution.
9110
             */
9111
            private final String name;
9112

9113
            /**
9114
             * Creates a new lazy type resolution.
9115
             *
9116
             * @param typePool The type pool to delegate to.
9117
             * @param name     The name of the type.
9118
             */
9119
            protected LazyTypeDescription(TypePool typePool, String name) {
1✔
9120
                this.typePool = typePool;
1✔
9121
                this.name = name;
1✔
9122
            }
1✔
9123

9124
            /**
9125
             * {@inheritDoc}
9126
             */
9127
            public String getName() {
9128
                return name;
1✔
9129
            }
9130

9131
            @Override
9132
            @CachedReturnPlugin.Enhance("delegate")
9133
            protected TypeDescription delegate() {
9134
                return typePool.describe(name).resolve();
1✔
9135
            }
9136
        }
9137
    }
9138

9139
    /**
9140
     * A type pool that attempts to load a class.
9141
     */
9142
    @HashCodeAndEqualsPlugin.Enhance
9143
    class ClassLoading extends AbstractBase.Hierarchical {
9144

9145
        /**
9146
         * The class loader to query.
9147
         */
9148
        @MaybeNull
9149
        @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.REVERSE_NULLABILITY)
9150
        private final ClassLoader classLoader;
9151

9152
        /**
9153
         * Creates a class loadings type pool.
9154
         *
9155
         * @param cacheProvider The cache provider to use.
9156
         * @param parent        The parent type pool.
9157
         * @param classLoader   The class loader to use for locating files.
9158
         */
9159
        public ClassLoading(CacheProvider cacheProvider, TypePool parent, @MaybeNull ClassLoader classLoader) {
9160
            super(cacheProvider, parent);
1✔
9161
            this.classLoader = classLoader;
1✔
9162
        }
1✔
9163

9164
        /**
9165
         * Returns a type pool that attempts type descriptions by loadings types from the given class loader.
9166
         *
9167
         * @param classLoader The class loader to use.
9168
         * @return An class loading type pool.
9169
         */
9170
        public static TypePool of(@MaybeNull ClassLoader classLoader) {
9171
            return of(classLoader, Empty.INSTANCE);
1✔
9172
        }
9173

9174
        /**
9175
         * Returns a type pool that attempts type descriptions by loadings types from the given class loader.
9176
         *
9177
         * @param classLoader The class loader to use.
9178
         * @param parent      The parent type pool to use.
9179
         * @return An class loading type pool.
9180
         */
9181
        public static TypePool of(@MaybeNull ClassLoader classLoader, TypePool parent) {
9182
            return new ClassLoading(new CacheProvider.Simple(), parent, classLoader);
1✔
9183
        }
9184

9185
        /**
9186
         * Returns a type pool that attempts type descriptions by loadings types from the system class loader.
9187
         *
9188
         * @return An class loading type pool for the system class loader.
9189
         */
9190
        public static TypePool ofSystemLoader() {
9191
            return of(ClassLoader.getSystemClassLoader());
1✔
9192
        }
9193

9194
        /**
9195
         * Returns a type pool that attempts type descriptions by loadings types from the platform class loader.
9196
         * If the current VM is Java 8 or older, the extension class loader is represented instead.
9197
         *
9198
         * @return An class loading type pool for the system class loader.
9199
         */
9200
        public static TypePool ofPlatformLoader() {
9201
            return of(ClassLoader.getSystemClassLoader().getParent());
1✔
9202
        }
9203

9204
        /**
9205
         * Returns a type pool that attempts type descriptions by loadings types from the bootstrap class loader.
9206
         *
9207
         * @return An class loading type pool for the bootstrap class loader.
9208
         */
9209
        public static TypePool ofBootLoader() {
9210
            return of(ClassLoadingStrategy.BOOTSTRAP_LOADER);
1✔
9211
        }
9212

9213
        @Override
9214
        protected Resolution doDescribe(String name) {
9215
            try {
9216
                return new Resolution.Simple(TypeDescription.ForLoadedType.of(Class.forName(name, false, classLoader)));
1✔
9217
            } catch (ClassNotFoundException ignored) {
1✔
9218
                return new Resolution.Illegal(name);
1✔
9219
            }
9220
        }
9221
    }
9222

9223
    /**
9224
     * A type pool that supplies explicitly known type descriptions.
9225
     */
9226
    @HashCodeAndEqualsPlugin.Enhance
9227
    class Explicit extends AbstractBase.Hierarchical {
9228

9229
        /**
9230
         * A mapping from type names to type descriptions of that name.
9231
         */
9232
        private final Map<String, TypeDescription> types;
9233

9234
        /**
9235
         * Creates a new explicit type pool without a parent.
9236
         *
9237
         * @param types A mapping from type names to type descriptions of that name.
9238
         */
9239
        public Explicit(Map<String, TypeDescription> types) {
9240
            this(Empty.INSTANCE, types);
×
9241
        }
×
9242

9243
        /**
9244
         * Creates a new explicit type pool.
9245
         *
9246
         * @param parent The parent type pool.
9247
         * @param types  A mapping from type names to type descriptions of that name.
9248
         */
9249
        public Explicit(TypePool parent, Map<String, TypeDescription> types) {
9250
            super(CacheProvider.NoOp.INSTANCE, parent);
1✔
9251
            this.types = types;
1✔
9252
        }
1✔
9253

9254
        /**
9255
         * Wraps another type pool for an instrumented type and its auxiliary types.
9256
         *
9257
         * @param instrumentedType The instrumented type.
9258
         * @param auxiliaryTypes   The auxiliary types.
9259
         * @param typePool         The type pool to wrap.
9260
         * @return A type pool that also represents the instrumented type and its auxiliary types.
9261
         */
9262
        public static TypePool wrap(TypeDescription instrumentedType, List<? extends DynamicType> auxiliaryTypes, TypePool typePool) {
9263
            Map<String, TypeDescription> typeDescriptions = new HashMap<String, TypeDescription>();
1✔
9264
            typeDescriptions.put(instrumentedType.getName(), instrumentedType);
1✔
9265
            for (DynamicType auxiliaryType : auxiliaryTypes) {
1✔
9266
                for (TypeDescription typeDescription : auxiliaryType.getAllTypes().keySet()) {
1✔
9267
                    typeDescriptions.put(typeDescription.getName(), typeDescription);
1✔
9268
                }
1✔
9269
            }
1✔
9270
            return new Explicit(typePool, typeDescriptions);
1✔
9271
        }
9272

9273
        @Override
9274
        protected Resolution doDescribe(String name) {
9275
            TypeDescription typeDescription = types.get(name);
1✔
9276
            return typeDescription == null
1✔
9277
                    ? new Resolution.Illegal(name)
9278
                    : new Resolution.Simple(typeDescription);
9279
        }
9280
    }
9281
}
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