1 /*
2 * Copyright 2014 - 2020 Rafael Winterhalter
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.bytebuddy.description.type;
17
18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 import net.bytebuddy.build.CachedReturnPlugin;
20 import net.bytebuddy.description.ByteCodeElement;
21 import net.bytebuddy.description.TypeVariableSource;
22 import net.bytebuddy.description.annotation.AnnotationList;
23 import net.bytebuddy.description.field.FieldDescription;
24 import net.bytebuddy.description.method.MethodDescription;
25 import net.bytebuddy.description.method.ParameterDescription;
26 import net.bytebuddy.implementation.bytecode.StackSize;
27 import net.bytebuddy.matcher.ElementMatcher;
28 import net.bytebuddy.matcher.FilterableList;
29 import net.bytebuddy.jar.asm.Type;
30
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.GenericDeclaration;
33 import java.lang.reflect.Method;
34 import java.lang.reflect.TypeVariable;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.List;
38
39 /**
40 * Implementations represent a list of type descriptions.
41 */
42 public interface TypeList extends FilterableList<TypeDescription, TypeList> {
43
44 /**
45 * Represents that a type list does not contain any values for ASM interoperability which is represented by {@code null}.
46 */
47 @SuppressFBWarnings(value = {"MS_MUTABLE_ARRAY", "MS_OOI_PKGPROTECT"}, justification = "Value is null")
48 String[] NO_INTERFACES = null;
49
50 /**
51 * Returns a list of internal names of all types represented by this list.
52 *
53 * @return An array of all internal names or {@code null} if the list is empty.
54 */
55 String[] toInternalNames();
56
57 /**
58 * Returns the sum of the size of all types contained in this list.
59 *
60 * @return The sum of the size of all types contained in this list.
61 */
62 int getStackSize();
63
64 /**
65 * An abstract base implementation of a type list.
66 */
67 abstract class AbstractBase extends FilterableList.AbstractBase<TypeDescription, TypeList> implements TypeList {
68
69 @Override
70 protected TypeList wrap(List<TypeDescription> values) {
71 return new Explicit(values);
72 }
73
74 /**
75 * {@inheritDoc}
76 */
77 public int getStackSize() {
78 return StackSize.of(this);
79 }
80
81 /**
82 * {@inheritDoc}
83 */
84 public String[] toInternalNames() {
85 String[] internalNames = new String[size()];
86 int i = 0;
87 for (TypeDescription typeDescription : this) {
88 internalNames[i++] = typeDescription.getInternalName();
89 }
90 return internalNames.length == 0
91 ? NO_INTERFACES
92 : internalNames;
93 }
94 }
95
96 /**
97 * Implementation of a type list for an array of loaded types.
98 */
99 class ForLoadedTypes extends AbstractBase {
100
101 /**
102 * The loaded types this type list represents.
103 */
104 private final List<? extends Class<?>> types;
105
106 /**
107 * Creates a new type list for an array of loaded types.
108 *
109 * @param type The types to be represented by this list.
110 */
111 public ForLoadedTypes(Class<?>... type) {
112 this(Arrays.asList(type));
113 }
114
115 /**
116 * Creates a new type list for an array of loaded types.
117 *
118 * @param types The types to be represented by this list.
119 */
120 public ForLoadedTypes(List<? extends Class<?>> types) {
121 this.types = types;
122 }
123
124 /**
125 * {@inheritDoc}
126 */
127 public TypeDescription get(int index) {
128 return TypeDescription.ForLoadedType.of(types.get(index));
129 }
130
131 /**
132 * {@inheritDoc}
133 */
134 public int size() {
135 return types.size();
136 }
137
138 /**
139 * {@inheritDoc}
140 */
141 public String[] toInternalNames() {
142 String[] internalNames = new String[types.size()];
143 int i = 0;
144 for (Class<?> type : types) {
145 internalNames[i++] = Type.getInternalName(type);
146 }
147 return internalNames.length == 0
148 ? NO_INTERFACES
149 : internalNames;
150 }
151 }
152
153 /**
154 * A wrapper implementation of an explicit list of types.
155 */
156 class Explicit extends AbstractBase {
157
158 /**
159 * The list of type descriptions this list represents.
160 */
161 private final List<? extends TypeDescription> typeDescriptions;
162
163 /**
164 * Creates an immutable wrapper.
165 *
166 * @param typeDescription The list of types to be represented by this wrapper.
167 */
168 public Explicit(TypeDescription... typeDescription) {
169 this(Arrays.asList(typeDescription));
170 }
171
172 /**
173 * Creates an immutable wrapper.
174 *
175 * @param typeDescriptions The list of types to be represented by this wrapper.
176 */
177 public Explicit(List<? extends TypeDescription> typeDescriptions) {
178 this.typeDescriptions = typeDescriptions;
179 }
180
181 /**
182 * {@inheritDoc}
183 */
184 public TypeDescription get(int index) {
185 return typeDescriptions.get(index);
186 }
187
188 /**
189 * {@inheritDoc}
190 */
191 public int size() {
192 return typeDescriptions.size();
193 }
194 }
195
196 /**
197 * An implementation of an empty type list.
198 */
199 class Empty extends FilterableList.Empty<TypeDescription, TypeList> implements TypeList {
200
201 /**
202 * {@inheritDoc}
203 */
204 @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Value is null")
205 public String[] toInternalNames() {
206 return NO_INTERFACES;
207 }
208
209 /**
210 * {@inheritDoc}
211 */
212 public int getStackSize() {
213 return 0;
214 }
215 }
216
217 /**
218 * A list containing descriptions of generic types.
219 */
220 interface Generic extends FilterableList<TypeDescription.Generic, Generic> {
221
222 /**
223 * Returns a list of the generic types' erasures.
224 *
225 * @return A list of the generic types' erasures.
226 */
227 TypeList asErasures();
228
229 /**
230 * Returns a list of the generic types' raw types.
231 *
232 * @return A list of the generic types' raw types.
233 */
234 Generic asRawTypes();
235
236 /**
237 * Transforms a list of attached type variables into their tokenized form. Calling this method throws an {@link IllegalStateException}
238 * if any type in this list does not represent a type variable ({@link net.bytebuddy.description.type.TypeDefinition.Sort#VARIABLE}).
239 *
240 * @param visitor The visitor to use for detaching the type variable's bounds.
241 * @return A list of tokens representing the type variables contained in this list.
242 */
243 ByteCodeElement.Token.TokenList<TypeVariableToken> asTokenList(ElementMatcher<? super TypeDescription> visitor);
244
245 /**
246 * Transforms the generic types by applying the supplied visitor to each of them.
247 *
248 * @param visitor The visitor to apply to each type.
249 * @return A list of the types returned by the supplied visitor.
250 */
251 Generic accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor);
252
253 /**
254 * Returns the sum of the size of all types contained in this list.
255 *
256 * @return The sum of the size of all types contained in this list.
257 */
258 int getStackSize();
259
260 /**
261 * An abstract base implementation of a generic type list.
262 */
263 abstract class AbstractBase extends FilterableList.AbstractBase<TypeDescription.Generic, Generic> implements Generic {
264
265 @Override
266 protected Generic wrap(List<TypeDescription.Generic> values) {
267 return new Explicit(values);
268 }
269
270 /**
271 * {@inheritDoc}
272 */
273 public Generic accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
274 List<TypeDescription.Generic> visited = new ArrayList<TypeDescription.Generic>(size());
275 for (TypeDescription.Generic typeDescription : this) {
276 visited.add(typeDescription.accept(visitor));
277 }
278 return new Explicit(visited);
279 }
280
281 /**
282 * {@inheritDoc}
283 */
284 public ByteCodeElement.Token.TokenList<TypeVariableToken> asTokenList(ElementMatcher<? super TypeDescription> matcher) {
285 List<TypeVariableToken> tokens = new ArrayList<TypeVariableToken>(size());
286 for (TypeDescription.Generic typeVariable : this) {
287 tokens.add(TypeVariableToken.of(typeVariable, matcher));
288 }
289 return new ByteCodeElement.Token.TokenList<TypeVariableToken>(tokens);
290 }
291
292 /**
293 * {@inheritDoc}
294 */
295 public int getStackSize() {
296 int stackSize = 0;
297 for (TypeDescription.Generic typeDescription : this) {
298 stackSize += typeDescription.getStackSize().getSize();
299 }
300 return stackSize;
301 }
302
303 /**
304 * {@inheritDoc}
305 */
306 public TypeList asErasures() {
307 List<TypeDescription> typeDescriptions = new ArrayList<TypeDescription>(size());
308 for (TypeDescription.Generic typeDescription : this) {
309 typeDescriptions.add(typeDescription.asErasure());
310 }
311 return new TypeList.Explicit(typeDescriptions);
312 }
313
314 /**
315 * {@inheritDoc}
316 */
317 public Generic asRawTypes() {
318 List<TypeDescription.Generic> typeDescriptions = new ArrayList<TypeDescription.Generic>(size());
319 for (TypeDescription.Generic typeDescription : this) {
320 typeDescriptions.add(typeDescription.asRawType());
321 }
322 return new Explicit(typeDescriptions);
323 }
324 }
325
326 /**
327 * An explicit list of generic types.
328 */
329 class Explicit extends AbstractBase {
330
331 /**
332 * The generic types represented by this list.
333 */
334 private final List<? extends TypeDefinition> typeDefinitions;
335
336 /**
337 * Creates a new explicit list of generic types.
338 *
339 * @param typeDefinition The generic types represented by this list.
340 */
341 public Explicit(TypeDefinition... typeDefinition) {
342 this(Arrays.asList(typeDefinition));
343 }
344
345 /**
346 * Creates a new explicit list of generic types.
347 *
348 * @param typeDefinitions The generic types represented by this list.
349 */
350 public Explicit(List<? extends TypeDefinition> typeDefinitions) {
351 this.typeDefinitions = typeDefinitions;
352 }
353
354 /**
355 * {@inheritDoc}
356 */
357 public TypeDescription.Generic get(int index) {
358 return typeDefinitions.get(index).asGenericType();
359 }
360
361 /**
362 * {@inheritDoc}
363 */
364 public int size() {
365 return typeDefinitions.size();
366 }
367 }
368
369 /**
370 * A list of loaded generic types.
371 */
372 class ForLoadedTypes extends AbstractBase {
373
374 /**
375 * The loaded types this list represents.
376 */
377 private final List<? extends java.lang.reflect.Type> types;
378
379 /**
380 * Creates a list of loaded generic types.
381 *
382 * @param type The loaded types this list represents.
383 */
384 public ForLoadedTypes(java.lang.reflect.Type... type) {
385 this(Arrays.asList(type));
386 }
387
388 /**
389 * Creates a list of loaded generic types.
390 *
391 * @param types The loaded types this list represents.
392 */
393 public ForLoadedTypes(List<? extends java.lang.reflect.Type> types) {
394 this.types = types;
395 }
396
397 /**
398 * {@inheritDoc}
399 */
400 public TypeDescription.Generic get(int index) {
401 return TypeDefinition.Sort.describe(types.get(index));
402 }
403
404 /**
405 * {@inheritDoc}
406 */
407 public int size() {
408 return types.size();
409 }
410
411 /**
412 * A type list that represents loaded type variables.
413 */
414 public static class OfTypeVariables extends Generic.AbstractBase {
415
416 /**
417 * The type variables this list represents.
418 */
419 private final List<TypeVariable<?>> typeVariables;
420
421 /**
422 * Creates a new type list for loaded type variables.
423 *
424 * @param typeVariable The type variables this list represents.
425 */
426 protected OfTypeVariables(TypeVariable<?>... typeVariable) {
427 this(Arrays.asList(typeVariable));
428 }
429
430 /**
431 * Creates a new type list for loaded type variables.
432 *
433 * @param typeVariables The type variables this list represents.
434 */
435 protected OfTypeVariables(List<TypeVariable<?>> typeVariables) {
436 this.typeVariables = typeVariables;
437 }
438
439 /**
440 * Creates a list of the type variables of the supplied generic declaration.
441 *
442 * @param genericDeclaration The generic declaration to represent.
443 * @return A generic type list for the returned generic declaration.
444 */
445 public static Generic of(GenericDeclaration genericDeclaration) {
446 return new OfTypeVariables(genericDeclaration.getTypeParameters());
447 }
448
449 /**
450 * {@inheritDoc}
451 */
452 public TypeDescription.Generic get(int index) {
453 TypeVariable<?> typeVariable = typeVariables.get(index);
454 return TypeDefinition.Sort.describe(typeVariable, TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveTypeVariable(typeVariable));
455 }
456
457 /**
458 * {@inheritDoc}
459 */
460 public int size() {
461 return typeVariables.size();
462 }
463 }
464 }
465
466 /**
467 * A list of detached types that are attached on reception.
468 */
469 class ForDetachedTypes extends AbstractBase {
470
471 /**
472 * The detached types this list represents.
473 */
474 private final List<? extends TypeDescription.Generic> detachedTypes;
475
476 /**
477 * The visitor to use for attaching the detached types.
478 */
479 private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
480
481 /**
482 * Creates a list of detached types that are attached on reception.
483 *
484 * @param detachedTypes The detached types this list represents.
485 * @param visitor The visitor to use for attaching the detached types.
486 */
487 public ForDetachedTypes(List<? extends TypeDescription.Generic> detachedTypes,
488 TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
489 this.detachedTypes = detachedTypes;
490 this.visitor = visitor;
491 }
492
493 /**
494 * Creates a list of type variables that are attached to the provided type.
495 *
496 * @param typeDescription The type to which the type variables are to be attached to.
497 * @param detachedTypeVariables A mapping of type variable symbols to their detached type variable bounds.
498 * @return A type list representing the symbolic type variables in their attached state to the given type description.
499 */
500 public static Generic attachVariables(TypeDescription typeDescription, List<? extends TypeVariableToken> detachedTypeVariables) {
501 return new OfTypeVariables(typeDescription, detachedTypeVariables, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(typeDescription));
502 }
503
504 /**
505 * Creates a list of types that are attached to the provided field.
506 *
507 * @param fieldDescription The field to which the detached variables are attached to.
508 * @param detachedTypes The detached types.
509 * @return A type list representing the detached types being attached to the provided field description.
510 */
511 public static Generic attach(FieldDescription fieldDescription, List<? extends TypeDescription.Generic> detachedTypes) {
512 return new ForDetachedTypes(detachedTypes, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(fieldDescription));
513 }
514
515 /**
516 * Creates a list of types that are attached to the provided method.
517 *
518 * @param methodDescription The method to which the detached variables are attached to.
519 * @param detachedTypes The detached types.
520 * @return A type list representing the detached types being attached to the provided method description.
521 */
522 public static Generic attach(MethodDescription methodDescription, List<? extends TypeDescription.Generic> detachedTypes) {
523 return new ForDetachedTypes(detachedTypes, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(methodDescription));
524 }
525
526 /**
527 * Creates a list of type variables that are attached to the provided method.
528 *
529 * @param methodDescription The method to which the type variables are to be attached to.
530 * @param detachedTypeVariables A mapping of type variable symbols to their detached type variable bounds.
531 * @return A type list representing the symbolic type variables in their attached state to the given method description.
532 */
533 public static Generic attachVariables(MethodDescription methodDescription, List<? extends TypeVariableToken> detachedTypeVariables) {
534 return new OfTypeVariables(methodDescription, detachedTypeVariables, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(methodDescription));
535 }
536
537 /**
538 * Creates a list of types that are attached to the provided parameter.
539 *
540 * @param parameterDescription The parameter to which the detached variables are attached to.
541 * @param detachedTypes The detached types.
542 * @return A type list representing the detached types being attached to the provided parameter description.
543 */
544 public static Generic attach(ParameterDescription parameterDescription, List<? extends TypeDescription.Generic> detachedTypes) {
545 return new ForDetachedTypes(detachedTypes, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(parameterDescription));
546 }
547
548 /**
549 * {@inheritDoc}
550 */
551 public TypeDescription.Generic get(int index) {
552 return detachedTypes.get(index).accept(visitor);
553 }
554
555 /**
556 * {@inheritDoc}
557 */
558 public int size() {
559 return detachedTypes.size();
560 }
561
562 /**
563 * A list of detached types that are attached on reception but not when computing an erasure.
564 */
565 public static class WithResolvedErasure extends Generic.AbstractBase {
566
567 /**
568 * The detached types this list represents.
569 */
570 private final List<? extends TypeDescription.Generic> detachedTypes;
571
572 /**
573 * The visitor to use for attaching the detached types.
574 */
575 private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
576
577 /**
578 * Creates a list of generic type descriptions that are resolved lazily, i.e. type variables are not resolved
579 * when computing an erasure.
580 *
581 * @param detachedTypes The detached types this list represents.
582 * @param visitor The visitor to use for attaching the detached types.
583 */
584 public WithResolvedErasure(List<? extends TypeDescription.Generic> detachedTypes,
585 TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
586 this.detachedTypes = detachedTypes;
587 this.visitor = visitor;
588 }
589
590 /**
591 * {@inheritDoc}
592 */
593 public TypeDescription.Generic get(int index) {
594 return new TypeDescription.Generic.LazyProjection.WithResolvedErasure(detachedTypes.get(index), visitor);
595 }
596
597 /**
598 * {@inheritDoc}
599 */
600 public int size() {
601 return detachedTypes.size();
602 }
603 }
604
605 /**
606 * A list of attached type variables represented by a list of type variable tokens.
607 */
608 public static class OfTypeVariables extends Generic.AbstractBase {
609
610 /**
611 * The type variable's source.
612 */
613 private final TypeVariableSource typeVariableSource;
614
615 /**
616 * A token representing the type variable in its detached state.
617 */
618 private final List<? extends TypeVariableToken> detachedTypeVariables;
619
620 /**
621 * A visitor for attaching the type variable's bounds.
622 */
623 private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
624
625 /**
626 * Creates a new list of attached type variables representing a list of type variable tokens.
627 *
628 * @param typeVariableSource The type variable's source.
629 * @param detachedTypeVariables A token representing the type variable in its detached state.
630 * @param visitor A visitor for attaching the type variable's bounds.
631 */
632 public OfTypeVariables(TypeVariableSource typeVariableSource,
633 List<? extends TypeVariableToken> detachedTypeVariables,
634 TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
635 this.typeVariableSource = typeVariableSource;
636 this.detachedTypeVariables = detachedTypeVariables;
637 this.visitor = visitor;
638 }
639
640 /**
641 * {@inheritDoc}
642 */
643 public TypeDescription.Generic get(int index) {
644 return new AttachedTypeVariable(typeVariableSource, detachedTypeVariables.get(index), visitor);
645 }
646
647 /**
648 * {@inheritDoc}
649 */
650 public int size() {
651 return detachedTypeVariables.size();
652 }
653
654 /**
655 * A wrapper for representing a type variable in its attached state.
656 */
657 protected static class AttachedTypeVariable extends TypeDescription.Generic.OfTypeVariable {
658
659 /**
660 * The type variable's source.
661 */
662 private final TypeVariableSource typeVariableSource;
663
664 /**
665 * A token representing the type variable in its detached state.
666 */
667 private final TypeVariableToken typeVariableToken;
668
669 /**
670 * A visitor for attaching the type variable's bounds.
671 */
672 private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
673
674 /**
675 * Creates a new attached type variable.
676 *
677 * @param typeVariableSource The type variable's source.
678 * @param typeVariableToken A token representing the type variable in its detached state.
679 * @param visitor A visitor for attaching the type variable's bounds.
680 */
681 protected AttachedTypeVariable(TypeVariableSource typeVariableSource,
682 TypeVariableToken typeVariableToken,
683 TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
684 this.typeVariableSource = typeVariableSource;
685 this.typeVariableToken = typeVariableToken;
686 this.visitor = visitor;
687 }
688
689 /**
690 * {@inheritDoc}
691 */
692 public Generic getUpperBounds() {
693 return typeVariableToken.getBounds().accept(visitor);
694 }
695
696 /**
697 * {@inheritDoc}
698 */
699 public TypeVariableSource getTypeVariableSource() {
700 return typeVariableSource;
701 }
702
703 /**
704 * {@inheritDoc}
705 */
706 public String getSymbol() {
707 return typeVariableToken.getSymbol();
708 }
709
710 /**
711 * {@inheritDoc}
712 */
713 public AnnotationList getDeclaredAnnotations() {
714 return typeVariableToken.getAnnotations();
715 }
716 }
717 }
718 }
719
720 /**
721 * A lazy projection of a type's generic interface types.
722 */
723 class OfLoadedInterfaceTypes extends AbstractBase {
724
725 /**
726 * The type of which the interface types are represented by this list.
727 */
728 private final Class<?> type;
729
730 /**
731 * Creates a lazy projection of interface types.
732 *
733 * @param type The type of which the interface types are represented by this list.
734 */
735 public OfLoadedInterfaceTypes(Class<?> type) {
736 this.type = type;
737 }
738
739 /**
740 * {@inheritDoc}
741 */
742 public TypeDescription.Generic get(int index) {
743 return new OfLoadedInterfaceTypes.TypeProjection(type, index, type.getInterfaces());
744 }
745
746 /**
747 * {@inheritDoc}
748 */
749 public int size() {
750 return type.getInterfaces().length;
751 }
752
753 /**
754 * {@inheritDoc}
755 */
756 public TypeList asErasures() {
757 return new TypeList.ForLoadedTypes(type.getInterfaces());
758 }
759
760 /**
761 * A type projection of an interface type.
762 */
763 private static class TypeProjection extends TypeDescription.Generic.LazyProjection.WithLazyNavigation.OfAnnotatedElement {
764
765 /**
766 * The type of which an interface type is represented.
767 */
768 private final Class<?> type;
769
770 /**
771 * The index of the generic interface type that is represented.
772 */
773 private final int index;
774
775 /**
776 * The erasures of the represented type's interface types.
777 */
778 private final Class<?>[] erasure;
779
780 /**
781 * Creates a new lazy type projection of a generic interface type.
782 *
783 * @param type The type of which an interface type is represented.
784 * @param index The index of the generic interface type that is represented.
785 * @param erasure The erasures of the represented type's interface types.
786 */
787 private TypeProjection(Class<?> type, int index, Class<?>[] erasure) {
788 this.type = type;
789 this.index = index;
790 this.erasure = erasure;
791 }
792
793 @Override
794 @CachedReturnPlugin.Enhance("resolved")
795 protected TypeDescription.Generic resolve() {
796 java.lang.reflect.Type[] type = this.type.getGenericInterfaces();
797 return erasure.length == type.length
798 ? Sort.describe(type[index], getAnnotationReader())
799 : asRawType();
800 }
801
802 /**
803 * {@inheritDoc}
804 */
805 public TypeDescription asErasure() {
806 return TypeDescription.ForLoadedType.of(erasure[index]);
807 }
808
809 @Override
810 protected AnnotationReader getAnnotationReader() {
811 return AnnotationReader.DISPATCHER.resolveInterfaceType(type, index);
812 }
813 }
814 }
815
816 /**
817 * A lazy projection of a constructor's exception types.
818 */
819 class OfConstructorExceptionTypes extends AbstractBase {
820
821 /**
822 * The constructor of which the exception types are represented.
823 */
824 private final Constructor<?> constructor;
825
826 /**
827 * Creates a new lazy projection of a constructor's exception types.
828 *
829 * @param constructor The constructor of which the exception types are represented.
830 */
831 public OfConstructorExceptionTypes(Constructor<?> constructor) {
832 this.constructor = constructor;
833 }
834
835 /**
836 * {@inheritDoc}
837 */
838 public TypeDescription.Generic get(int index) {
839 return new OfConstructorExceptionTypes.TypeProjection(constructor, index, constructor.getExceptionTypes());
840 }
841
842 /**
843 * {@inheritDoc}
844 */
845 public int size() {
846 return constructor.getExceptionTypes().length;
847 }
848
849 /**
850 * {@inheritDoc}
851 */
852 public TypeList asErasures() {
853 return new TypeList.ForLoadedTypes(constructor.getExceptionTypes());
854 }
855
856 /**
857 * A projection of a specific exception type.
858 */
859 private static class TypeProjection extends TypeDescription.Generic.LazyProjection.WithEagerNavigation.OfAnnotatedElement {
860
861 /**
862 * The constructor of which the exception types are represented.
863 */
864 private final Constructor<?> constructor;
865
866 /**
867 * The index of the exception type.
868 */
869 private final int index;
870
871 /**
872 * The erasures of the represented constructor's exception types.
873 */
874 private final Class<?>[] erasure;
875
876 /**
877 * Creates a lazy type projection of a constructor's exception type.
878 *
879 * @param constructor The constructor of which the exception types are represented.
880 * @param index The index of the exception type.
881 * @param erasure The erasures of the represented constructor's exception types.
882 */
883 private TypeProjection(Constructor<?> constructor, int index, Class<?>[] erasure) {
884 this.constructor = constructor;
885 this.index = index;
886 this.erasure = erasure;
887 }
888
889 @Override
890 @CachedReturnPlugin.Enhance("resolved")
891 protected TypeDescription.Generic resolve() {
892 java.lang.reflect.Type[] type = constructor.getGenericExceptionTypes();
893 return erasure.length == type.length
894 ? Sort.describe(type[index], getAnnotationReader())
895 : asRawType();
896 }
897
898 /**
899 * {@inheritDoc}
900 */
901 public TypeDescription asErasure() {
902 return TypeDescription.ForLoadedType.of(erasure[index]);
903 }
904
905 @Override
906 protected AnnotationReader getAnnotationReader() {
907 return AnnotationReader.DISPATCHER.resolveExceptionType(constructor, index);
908 }
909 }
910 }
911
912 /**
913 * A lazy projection of a method's exception types.
914 */
915 class OfMethodExceptionTypes extends AbstractBase {
916
917 /**
918 * The method of which the exception types are represented.
919 */
920 private final Method method;
921
922 /**
923 * Creates a new lazy projection of a constructor's exception types.
924 *
925 * @param method The method of which the exception types are represented.
926 */
927 public OfMethodExceptionTypes(Method method) {
928 this.method = method;
929 }
930
931 /**
932 * {@inheritDoc}
933 */
934 public TypeDescription.Generic get(int index) {
935 return new OfMethodExceptionTypes.TypeProjection(method, index, method.getExceptionTypes());
936 }
937
938 /**
939 * {@inheritDoc}
940 */
941 public int size() {
942 return method.getExceptionTypes().length;
943 }
944
945 /**
946 * {@inheritDoc}
947 */
948 public TypeList asErasures() {
949 return new TypeList.ForLoadedTypes(method.getExceptionTypes());
950 }
951
952 /**
953 * A projection of a specific exception type.
954 */
955 private static class TypeProjection extends TypeDescription.Generic.LazyProjection.WithEagerNavigation.OfAnnotatedElement {
956
957 /**
958 * The method of which the exception types are represented.
959 */
960 private final Method method;
961
962 /**
963 * The index of the exception type.
964 */
965 private final int index;
966
967 /**
968 * The erasures of the represented type's interface type.
969 */
970 private final Class<?>[] erasure;
971
972 /**
973 * Creates a lazy type projection of a constructor's exception type.
974 *
975 * @param method The method of which the exception types are represented.
976 * @param index The index of the exception type.
977 * @param erasure The erasures of the represented type's interface type.
978 */
979 public TypeProjection(Method method, int index, Class<?>[] erasure) {
980 this.method = method;
981 this.index = index;
982 this.erasure = erasure;
983 }
984
985 @Override
986 @CachedReturnPlugin.Enhance("resolved")
987 protected TypeDescription.Generic resolve() {
988 java.lang.reflect.Type[] type = method.getGenericExceptionTypes();
989 return erasure.length == type.length
990 ? Sort.describe(type[index], getAnnotationReader())
991 : asRawType();
992 }
993
994 /**
995 * {@inheritDoc}
996 */
997 public TypeDescription asErasure() {
998 return TypeDescription.ForLoadedType.of(erasure[index]);
999 }
1000
1001 @Override
1002 protected AnnotationReader getAnnotationReader() {
1003 return AnnotationReader.DISPATCHER.resolveExceptionType(method, index);
1004 }
1005 }
1006 }
1007
1008 /**
1009 * An empty list of generic types.
1010 */
1011 class Empty extends FilterableList.Empty<TypeDescription.Generic, Generic> implements Generic {
1012
1013 /**
1014 * {@inheritDoc}
1015 */
1016 public TypeList asErasures() {
1017 return new TypeList.Empty();
1018 }
1019
1020 /**
1021 * {@inheritDoc}
1022 */
1023 public Generic asRawTypes() {
1024 return this;
1025 }
1026
1027 /**
1028 * {@inheritDoc}
1029 */
1030 public Generic accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
1031 return new Generic.Empty();
1032 }
1033
1034 /**
1035 * {@inheritDoc}
1036 */
1037 public ByteCodeElement.Token.TokenList<TypeVariableToken> asTokenList(ElementMatcher<? super TypeDescription> matcher) {
1038 return new ByteCodeElement.Token.TokenList<TypeVariableToken>();
1039 }
1040
1041 /**
1042 * {@inheritDoc}
1043 */
1044 public int getStackSize() {
1045 return 0;
1046 }
1047 }
1048 }
1049 }
1050