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.method;
17
18 import net.bytebuddy.build.CachedReturnPlugin;
19 import net.bytebuddy.description.ByteCodeElement;
20 import net.bytebuddy.description.ModifierReviewable;
21 import net.bytebuddy.description.NamedElement;
22 import net.bytebuddy.description.TypeVariableSource;
23 import net.bytebuddy.description.annotation.AnnotationDescription;
24 import net.bytebuddy.description.annotation.AnnotationList;
25 import net.bytebuddy.description.annotation.AnnotationValue;
26 import net.bytebuddy.description.enumeration.EnumerationDescription;
27 import net.bytebuddy.description.modifier.ModifierContributor;
28 import net.bytebuddy.description.modifier.Visibility;
29 import net.bytebuddy.description.type.TypeDefinition;
30 import net.bytebuddy.description.type.TypeDescription;
31 import net.bytebuddy.description.type.TypeList;
32 import net.bytebuddy.description.type.TypeVariableToken;
33 import net.bytebuddy.matcher.ElementMatcher;
34 import net.bytebuddy.matcher.ElementMatchers;
35 import net.bytebuddy.utility.JavaType;
36 import net.bytebuddy.jar.asm.Opcodes;
37 import net.bytebuddy.jar.asm.Type;
38 import net.bytebuddy.jar.asm.signature.SignatureWriter;
39
40 import java.lang.annotation.Annotation;
41 import java.lang.reflect.Constructor;
42 import java.lang.reflect.GenericSignatureFormatError;
43 import java.lang.reflect.Method;
44 import java.lang.reflect.Modifier;
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.Iterator;
48 import java.util.List;
49
50 import static net.bytebuddy.matcher.ElementMatchers.not;
51 import static net.bytebuddy.matcher.ElementMatchers.ofSort;
52
53 /**
54  * Implementations of this interface describe a Java method, i.e. a method or a constructor. Implementations of this
55  * interface must provide meaningful {@code equal(Object)} and {@code hashCode()} implementations.
56  */

57 public interface MethodDescription extends TypeVariableSource,
58         ModifierReviewable.ForMethodDescription,
59         NamedElement.WithGenericName,
60         ByteCodeElement,
61         ByteCodeElement.TypeDependant<MethodDescription.InDefinedShape, MethodDescription.Token> {
62
63     /**
64      * The internal name of a Java constructor.
65      */

66     String CONSTRUCTOR_INTERNAL_NAME = "<init>";
67
68     /**
69      * The internal name of a Java static initializer.
70      */

71     String TYPE_INITIALIZER_INTERNAL_NAME = "<clinit>";
72
73     /**
74      * The type initializer of any representation of a type initializer.
75      */

76     int TYPE_INITIALIZER_MODIFIER = Opcodes.ACC_STATIC;
77
78     /**
79      * Represents any undefined property of a type description that is instead represented as {@code null} in order
80      * to resemble the Java reflection API which returns {@code null} and is intuitive to many Java developers.
81      */

82     InDefinedShape UNDEFINED = null;
83
84     /**
85      * Returns the return type of the described method.
86      *
87      * @return The return type of the described method.
88      */

89     TypeDescription.Generic getReturnType();
90
91     /**
92      * Returns a list of this method's parameters.
93      *
94      * @return A list of this method's parameters.
95      */

96     ParameterList<?> getParameters();
97
98     /**
99      * Returns the exception types of the described method.
100      *
101      * @return The exception types of the described method.
102      */

103     TypeList.Generic getExceptionTypes();
104
105     /**
106      * Returns this method's actual modifiers as it is present in a class file, i.e. includes a flag if this method
107      * is marked {@link Deprecated}.
108      *
109      * @return The method's actual modifiers.
110      */

111     int getActualModifiers();
112
113     /**
114      * Returns this method's actual modifiers as it is present in a class file, i.e. includes a flag if this method
115      * is marked {@link Deprecated} and adjusts the modifiers for being abstract or not.
116      *
117      * @param manifest {@code trueif the method should be treated as non-abstract.
118      * @return The method's actual modifiers.
119      */

120     int getActualModifiers(boolean manifest);
121
122     /**
123      * Returns this method's actual modifiers as it is present in a class file, i.e. includes a flag if this method
124      * is marked {@link Deprecated} and adjusts the modifiers for being abstract or not. Additionally, this method
125      * resolves a required minimal visibility.
126      *
127      * @param manifest   {@code trueif the method should be treated as non-abstract.
128      * @param visibility The minimal visibility to enforce for this method.
129      * @return The method's actual modifiers.
130      */

131     int getActualModifiers(boolean manifest, Visibility visibility);
132
133     /**
134      * Checks if this method description represents a constructor.
135      *
136      * @return {@code trueif this method description represents a constructor.
137      */

138     boolean isConstructor();
139
140     /**
141      * Checks if this method description represents a method, i.e. not a constructor or a type initializer.
142      *
143      * @return {@code trueif this method description represents a Java method.
144      */

145     boolean isMethod();
146
147     /**
148      * Checks if this method is a type initializer.
149      *
150      * @return {@code trueif this method description represents a type initializer.
151      */

152     boolean isTypeInitializer();
153
154     /**
155      * Verifies if a method description represents a given loaded method.
156      *
157      * @param method The method to be checked.
158      * @return {@code trueif this method description represents the given loaded method.
159      */

160     boolean represents(Method method);
161
162     /**
163      * Verifies if a method description represents a given loaded constructor.
164      *
165      * @param constructor The constructor to be checked.
166      * @return {@code trueif this method description represents the given loaded constructor.
167      */

168     boolean represents(Constructor<?> constructor);
169
170     /**
171      * Verifies if this method describes a virtual method, i.e. a method that is inherited by a sub type of this type.
172      *
173      * @return {@code trueif this method is virtual.
174      */

175     boolean isVirtual();
176
177     /**
178      * Returns the size of the local variable array that is required for this method, i.e. the size of all parameters
179      * if they were loaded on the stack including a reference to {@code thisif this method represented a non-static
180      * method.
181      *
182      * @return The size of this method on the operand stack.
183      */

184     int getStackSize();
185
186     /**
187      * Checks if this method represents a default (defender) method.
188      *
189      * @return {@code trueif this method is a default method.
190      */

191     boolean isDefaultMethod();
192
193     /**
194      * Checks if this method can be called using the {@code INVOKESPECIAL} for a given type.
195      *
196      * @param typeDescription The type o
197      * @return {@code trueif this method can be called using the {@code INVOKESPECIAL} instruction
198      * using the given type.
199      */

200     boolean isSpecializableFor(TypeDescription typeDescription);
201
202     /**
203      * Returns the method's default annotation value or {@code nullif no default value is defined for this method.
204      *
205      * @return The method's default annotation value or {@code nullif no default value is defined for this method.
206      */

207     AnnotationValue<?, ?> getDefaultValue();
208
209     /**
210      * Returns the default value but casts it to the given type. If the type differs from the value, a
211      * {@link java.lang.ClassCastException} is thrown.
212      *
213      * @param type The type to cast the default value to.
214      * @param <T>  The type to cast the default value to.
215      * @return The casted default value.
216      */

217     <T> T getDefaultValue(Class<T> type);
218
219     /**
220      * Asserts if this method is invokable on an instance of the given type, i.e. the method is an instance method or
221      * a constructor and the method is visible to the type and can be invoked on the given instance.
222      *
223      * @param typeDescription The type to check.
224      * @return {@code trueif this method is invokable on an instance of the given type.
225      */

226     boolean isInvokableOn(TypeDescription typeDescription);
227
228     /**
229      * Checks if this method is a valid bootstrap method for an invokedynamic call.
230      *
231      * @return {@code trueif this method is a valid bootstrap method for an invokedynamic call.
232      */

233     boolean isInvokeBootstrap();
234
235     /**
236      * Checks if this method is a valid bootstrap method for an invokedynamic call.
237      *
238      * @param arguments The types of the explicit arguments that are supplied to the bootstrap method.
239      * @return {@code trueif this method is a valid bootstrap method for an <i>invokedynamic</i> call.
240      */

241     boolean isInvokeBootstrap(List<? extends TypeDefinition> arguments);
242
243     /**
244      * Checks if this method is a valid bootstrap method for an constantdynamic call.
245      *
246      * @return {@code trueif this method is a valid bootstrap method for an constantdynamic call.
247      */

248     boolean isConstantBootstrap();
249
250     /**
251      * Checks if this method is a valid bootstrap method for an constantdynamic call.
252      *
253      * @param arguments The types of the explicit arguments that are supplied to the bootstrap method.
254      * @return {@code trueif this method is a valid bootstrap method for an <i>constantdynamic</i> call.
255      */

256     boolean isConstantBootstrap(List<? extends TypeDefinition> arguments);
257
258     /**
259      * Checks if this method is capable of defining a default annotation value.
260      *
261      * @return {@code trueif it is possible to define a default annotation value for this method.
262      */

263     boolean isDefaultValue();
264
265     /**
266      * Checks if the given value can describe a default annotation value for this method.
267      *
268      * @param annotationValue The value that describes the default annotation value for this method.
269      * @return {@code trueif the given value can describe a default annotation value for this method.
270      */

271     boolean isDefaultValue(AnnotationValue<?, ?> annotationValue);
272
273     /**
274      * Returns this methods receiver type. A receiver type is undefined for {@code static} methods
275      * where {@code null} is returned. Other than a receiver type that is provided by the Java reflection
276      * API, Byte Buddy is capable of extracting annotations on type parameters of receiver types when
277      * directly accessing a class file. Therefore, a receiver type might be parameterized.
278      *
279      * @return This method's (annotated) receiver type.
280      */

281     TypeDescription.Generic getReceiverType();
282
283     /**
284      * Returns a signature token representing this method.
285      *
286      * @return A signature token representing this method.
287      */

288     SignatureToken asSignatureToken();
289
290     /**
291      * Returns a type token that represents this method's raw return and parameter types.
292      *
293      * @return A type token that represents this method's raw return and parameter types.
294      */

295     TypeToken asTypeToken();
296
297     /**
298      * Validates that the supplied type token can implement a bridge method to this method.
299      *
300      * @param typeToken A type token representing a potential bridge method to this method.
301      * @return {@code trueif the supplied type token can represent a bridge method to this method.
302      */

303     boolean isBridgeCompatible(TypeToken typeToken);
304
305     /**
306      * Represents a method description in its generic shape, i.e. in the shape it is defined by a generic or raw type.
307      */

308     interface InGenericShape extends MethodDescription {
309
310         /**
311          * {@inheritDoc}
312          */

313         TypeDescription.Generic getDeclaringType();
314
315         /**
316          * {@inheritDoc}
317          */

318         ParameterList<ParameterDescription.InGenericShape> getParameters();
319     }
320
321     /**
322      * Represents a method in its defined shape, i.e. in the form it is defined by a class without its type variables being resolved.
323      */

324     interface InDefinedShape extends MethodDescription {
325
326         /**
327          * {@inheritDoc}
328          */

329         TypeDescription getDeclaringType();
330
331         /**
332          * {@inheritDoc}
333          */

334         ParameterList<ParameterDescription.InDefinedShape> getParameters();
335
336         /**
337          * An abstract base implementation of a method description in its defined shape.
338          */

339         abstract class AbstractBase extends MethodDescription.AbstractBase implements InDefinedShape {
340
341             /**
342              * {@inheritDoc}
343              */

344             public InDefinedShape asDefined() {
345                 return this;
346             }
347
348             /**
349              * {@inheritDoc}
350              */

351             public TypeDescription.Generic getReceiverType() {
352                 if (isStatic()) {
353                     return TypeDescription.Generic.UNDEFINED;
354                 } else if (isConstructor()) {
355                     TypeDescription declaringType = getDeclaringType(), enclosingDeclaringType = getDeclaringType().getEnclosingType();
356                     if (enclosingDeclaringType == null) {
357                         return TypeDescription.Generic.OfParameterizedType.ForGenerifiedErasure.of(declaringType);
358                     } else {
359                         return declaringType.isStatic()
360                                 ? enclosingDeclaringType.asGenericType()
361                                 : TypeDescription.Generic.OfParameterizedType.ForGenerifiedErasure.of(enclosingDeclaringType);
362                     }
363                 } else {
364                     return TypeDescription.Generic.OfParameterizedType.ForGenerifiedErasure.of(getDeclaringType());
365                 }
366             }
367         }
368     }
369
370     /**
371      * An abstract base implementation of a method description.
372      */

373     abstract class AbstractBase extends TypeVariableSource.AbstractBase implements MethodDescription {
374
375         /**
376          * A merger of all method modifiers that are visible in the Java source code.
377          */

378         private static final int SOURCE_MODIFIERS = Modifier.PUBLIC
379                 | Modifier.PROTECTED
380                 | Modifier.PRIVATE
381                 | Modifier.ABSTRACT
382                 | Modifier.STATIC
383                 | Modifier.FINAL
384                 | Modifier.SYNCHRONIZED
385                 | Modifier.NATIVE;
386
387         /**
388          * {@inheritDoc}
389          */

390         public int getStackSize() {
391             return getParameters().asTypeList().getStackSize() + (isStatic() ? 0 : 1);
392         }
393
394         /**
395          * {@inheritDoc}
396          */

397         public boolean isMethod() {
398             return !isConstructor() && !isTypeInitializer();
399         }
400
401         /**
402          * {@inheritDoc}
403          */

404         public boolean isConstructor() {
405             return CONSTRUCTOR_INTERNAL_NAME.equals(getInternalName());
406         }
407
408         /**
409          * {@inheritDoc}
410          */

411         public boolean isTypeInitializer() {
412             return TYPE_INITIALIZER_INTERNAL_NAME.equals(getInternalName());
413         }
414
415         /**
416          * {@inheritDoc}
417          */

418         public boolean represents(Method method) {
419             return equals(new ForLoadedMethod(method));
420         }
421
422         /**
423          * {@inheritDoc}
424          */

425         public boolean represents(Constructor<?> constructor) {
426             return equals(new ForLoadedConstructor(constructor));
427         }
428
429         /**
430          * {@inheritDoc}
431          */

432         public String getName() {
433             return isMethod()
434                     ? getInternalName()
435                     : getDeclaringType().asErasure().getName();
436         }
437
438         /**
439          * {@inheritDoc}
440          */

441         public String getActualName() {
442             return isMethod()
443                     ? getName()
444                     : EMPTY_NAME;
445         }
446
447         /**
448          * {@inheritDoc}
449          */

450         public String getDescriptor() {
451             StringBuilder descriptor = new StringBuilder().append('(');
452             for (TypeDescription parameterType : getParameters().asTypeList().asErasures()) {
453                 descriptor.append(parameterType.getDescriptor());
454             }
455             return descriptor.append(')').append(getReturnType().asErasure().getDescriptor()).toString();
456         }
457
458         /**
459          * {@inheritDoc}
460          */

461         public String getGenericSignature() {
462             try {
463                 SignatureWriter signatureWriter = new SignatureWriter();
464                 boolean generic = false;
465                 for (TypeDescription.Generic typeVariable : getTypeVariables()) {
466                     signatureWriter.visitFormalTypeParameter(typeVariable.getSymbol());
467                     boolean classBound = true;
468                     for (TypeDescription.Generic upperBound : typeVariable.getUpperBounds()) {
469                         upperBound.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(classBound
470                                 ? signatureWriter.visitClassBound()
471                                 : signatureWriter.visitInterfaceBound()));
472                         classBound = false;
473                     }
474                     generic = true;
475                 }
476                 for (TypeDescription.Generic parameterType : getParameters().asTypeList()) {
477                     parameterType.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(signatureWriter.visitParameterType()));
478                     generic = generic || !parameterType.getSort().isNonGeneric();
479                 }
480                 TypeDescription.Generic returnType = getReturnType();
481                 returnType.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(signatureWriter.visitReturnType()));
482                 generic = generic || !returnType.getSort().isNonGeneric();
483                 TypeList.Generic exceptionTypes = getExceptionTypes();
484                 if (!exceptionTypes.filter(not(ofSort(TypeDefinition.Sort.NON_GENERIC))).isEmpty()) {
485                     for (TypeDescription.Generic exceptionType : exceptionTypes) {
486                         exceptionType.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(signatureWriter.visitExceptionType()));
487                         generic = generic || !exceptionType.getSort().isNonGeneric();
488                     }
489                 }
490                 return generic
491                         ? signatureWriter.toString()
492                         : NON_GENERIC_SIGNATURE;
493             } catch (GenericSignatureFormatError ignored) {
494                 return NON_GENERIC_SIGNATURE;
495             }
496         }
497
498         /**
499          * {@inheritDoc}
500          */

501         public int getActualModifiers() {
502             return getModifiers() | (getDeclaredAnnotations().isAnnotationPresent(Deprecated.class)
503                     ? Opcodes.ACC_DEPRECATED
504                     : EMPTY_MASK);
505         }
506
507         /**
508          * {@inheritDoc}
509          */

510         public int getActualModifiers(boolean manifest) {
511             return manifest
512                     ? getActualModifiers() & ~(Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)
513                     : getActualModifiers() & ~Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT;
514         }
515
516         /**
517          * {@inheritDoc}
518          */

519         public int getActualModifiers(boolean manifest, Visibility visibility) {
520             return ModifierContributor.Resolver.of(Collections.singleton(getVisibility().expandTo(visibility))).resolve(getActualModifiers(manifest));
521         }
522
523         /**
524          * {@inheritDoc}
525          */

526         public boolean isVisibleTo(TypeDescription typeDescription) {
527             return (isVirtual() || getDeclaringType().asErasure().isVisibleTo(typeDescription))
528                     && (isPublic()
529                     || typeDescription.equals(getDeclaringType().asErasure())
530                     || isProtected() && getDeclaringType().asErasure().isAssignableFrom(typeDescription)
531                     || !isPrivate() && typeDescription.isSamePackage(getDeclaringType().asErasure())
532                     || isPrivate() && typeDescription.isNestMateOf(getDeclaringType().asErasure()));
533         }
534
535         /**
536          * {@inheritDoc}
537          */

538         public boolean isAccessibleTo(TypeDescription typeDescription) {
539             return (isVirtual() || getDeclaringType().asErasure().isVisibleTo(typeDescription))
540                     && (isPublic()
541                     || typeDescription.equals(getDeclaringType().asErasure())
542                     || !isPrivate() && typeDescription.isSamePackage(getDeclaringType().asErasure()))
543                     || isPrivate() && typeDescription.isNestMateOf(getDeclaringType().asErasure());
544         }
545
546         /**
547          * {@inheritDoc}
548          */

549         public boolean isVirtual() {
550             return !(isConstructor() || isPrivate() || isStatic() || isTypeInitializer());
551         }
552
553         /**
554          * {@inheritDoc}
555          */

556         public boolean isDefaultMethod() {
557             return !isAbstract() && !isBridge() && getDeclaringType().isInterface();
558         }
559
560         /**
561          * {@inheritDoc}
562          */

563         public boolean isSpecializableFor(TypeDescription targetType) {
564             if (isStatic()) { // Static private methods are never specializable, check static property first
565                 return false;
566             } else if (isPrivate() || isConstructor()) {
567                 return getDeclaringType().equals(targetType);
568             } else {
569                 return !isAbstract() && getDeclaringType().asErasure().isAssignableFrom(targetType);
570             }
571         }
572
573         /**
574          * {@inheritDoc}
575          */

576         public <T> T getDefaultValue(Class<T> type) {
577             return type.cast(getDefaultValue());
578         }
579
580         /**
581          * {@inheritDoc}
582          */

583         public boolean isInvokableOn(TypeDescription typeDescription) {
584             return !isStatic()
585                     && !isTypeInitializer()
586                     && isVisibleTo(typeDescription)
587                     && (isVirtual()
588                     ? getDeclaringType().asErasure().isAssignableFrom(typeDescription)
589                     : getDeclaringType().asErasure().equals(typeDescription));
590         }
591
592         /**
593          * Checks if this method is a bootstrap method while expecting the supplied type as a type representation.
594          *
595          * @param selfType The type of the bootstrap method's type representation.
596          * @return {@code trueif this method is a bootstrap method assuming the supplied type representation.
597          */

598         private boolean isBootstrap(TypeDescription selfType) {
599             TypeList parameterTypes = getParameters().asTypeList().asErasures();
600             switch (parameterTypes.size()) {
601                 case 0:
602                     return false;
603                 case 1:
604                     return parameterTypes.getOnly().represents(Object[].class);
605                 case 2:
606                     return JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().isAssignableTo(parameterTypes.get(0))
607                             && parameterTypes.get(1).represents(Object[].class);
608                 case 3:
609                     return JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().isAssignableTo(parameterTypes.get(0))
610                             && (parameterTypes.get(1).represents(Object.class) || parameterTypes.get(1).represents(String.class))
611                             && (parameterTypes.get(2).represents(Object[].class) || parameterTypes.get(2).isAssignableFrom(selfType));
612                 default:
613                     return JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().isAssignableTo(parameterTypes.get(0))
614                             && (parameterTypes.get(1).represents(Object.class) || parameterTypes.get(1).represents(String.class))
615                             && parameterTypes.get(2).isAssignableFrom(selfType);
616             }
617         }
618
619         /**
620          * Checks if this method is a bootstrap method given the supplied arguments. This method does not implement a full check but assumes that
621          * {@link MethodDescription.AbstractBase#isBootstrap(TypeDescription)} is invoked, as well.
622          *
623          * @param types The types of the explicit arguments that are supplied to the bootstrap method.
624          * @return {@code trueif this method is a bootstrap method for the supplied arguments.
625          */

626         private boolean isBootstrap(List<? extends TypeDefinition> types) {
627             TypeList targets = getParameters().asTypeList().asErasures();
628             if (targets.size() < 4) {
629                 return types.isEmpty() || targets.get(targets.size() - 1).represents(Object[].class);
630             } else {
631                 Iterator<TypeDescription> iterator = targets.subList(3, targets.size()).iterator();
632                 for (TypeDefinition type : types) {
633                     if (!iterator.hasNext()) {
634                         return false;
635                     }
636                     TypeDescription target = iterator.next();
637                     if (!iterator.hasNext() && target.represents(Object[].class)) {
638                         return true;
639                     } else if (!type.asErasure().isAssignableTo(target)) {
640                         return false;
641                     }
642                 }
643                 if (iterator.hasNext()) {
644                     return iterator.next().represents(Object[].class) && !iterator.hasNext();
645                 } else {
646                     return true;
647                 }
648             }
649         }
650
651         /**
652          * {@inheritDoc}
653          */

654         public boolean isInvokeBootstrap() {
655             TypeDescription returnType = getReturnType().asErasure();
656             if ((isMethod() && (!isStatic()
657                     || !(JavaType.CALL_SITE.getTypeStub().isAssignableFrom(returnType) || JavaType.CALL_SITE.getTypeStub().isAssignableTo(returnType))))
658                     || (isConstructor() && !JavaType.CALL_SITE.getTypeStub().isAssignableFrom(getDeclaringType().asErasure()))) {
659                 return false;
660             }
661             return isBootstrap(JavaType.METHOD_TYPE.getTypeStub());
662         }
663
664         /**
665          * {@inheritDoc}
666          */

667         public boolean isInvokeBootstrap(List<? extends TypeDefinition> arguments) {
668             return isInvokeBootstrap() && isBootstrap(arguments);
669         }
670
671         /**
672          * {@inheritDoc}
673          */

674         public boolean isConstantBootstrap() {
675             return isBootstrap(TypeDescription.CLASS);
676         }
677
678         /**
679          * {@inheritDoc}
680          */

681         public boolean isConstantBootstrap(List<? extends TypeDefinition> arguments) {
682             return isConstantBootstrap() && isBootstrap(arguments);
683         }
684
685         /**
686          * {@inheritDoc}
687          */

688         public boolean isDefaultValue() {
689             return !isConstructor()
690                     && !isStatic()
691                     && getReturnType().asErasure().isAnnotationReturnType()
692                     && getParameters().isEmpty();
693         }
694
695         /**
696          * {@inheritDoc}
697          */

698         public boolean isDefaultValue(AnnotationValue<?, ?> annotationValue) {
699             if (!isDefaultValue()) {
700                 return false;
701             }
702             TypeDescription returnType = getReturnType().asErasure();
703             Object value = annotationValue.resolve();
704             return (returnType.represents(boolean.class) && value instanceof Boolean)
705                     || (returnType.represents(byte.class) && value instanceof Byte)
706                     || (returnType.represents(char.class) && value instanceof Character)
707                     || (returnType.represents(short.class) && value instanceof Short)
708                     || (returnType.represents(int.class) && value instanceof Integer)
709                     || (returnType.represents(long.class) && value instanceof Long)
710                     || (returnType.represents(float.class) && value instanceof Float)
711                     || (returnType.represents(double.class) && value instanceof Double)
712                     || (returnType.represents(String.class) && value instanceof String)
713                     || (returnType.isAssignableTo(Enum.class) && value instanceof EnumerationDescription && isEnumerationType(returnType, (EnumerationDescription) value))
714                     || (returnType.isAssignableTo(Annotation.class) && value instanceof AnnotationDescription && isAnnotationType(returnType, (AnnotationDescription) value))
715                     || (returnType.represents(Class.class) && value instanceof TypeDescription)
716                     || (returnType.represents(boolean[].class) && value instanceof boolean[])
717                     || (returnType.represents(byte[].class) && value instanceof byte[])
718                     || (returnType.represents(char[].class) && value instanceof char[])
719                     || (returnType.represents(short[].class) && value instanceof short[])
720                     || (returnType.represents(int[].class) && value instanceof int[])
721                     || (returnType.represents(long[].class) && value instanceof long[])
722                     || (returnType.represents(float[].class) && value instanceof float[])
723                     || (returnType.represents(double[].class) && value instanceof double[])
724                     || (returnType.represents(String[].class) && value instanceof String[])
725                     || (returnType.isAssignableTo(Enum[].class) && value instanceof EnumerationDescription[] && isEnumerationType(returnType.getComponentType(), (EnumerationDescription[]) value))
726                     || (returnType.isAssignableTo(Annotation[].class) && value instanceof AnnotationDescription[] && isAnnotationType(returnType.getComponentType(), (AnnotationDescription[]) value))
727                     || (returnType.represents(Class[].class) && value instanceof TypeDescription[]);
728         }
729
730         /**
731          * Checks if the supplied enumeration descriptions describe the correct enumeration type.
732          *
733          * @param enumerationType        The enumeration type to check for.
734          * @param enumerationDescription The enumeration descriptions to check.
735          * @return {@code trueif all enumeration descriptions represent the enumeration type in question.
736          */

737         private static boolean isEnumerationType(TypeDescription enumerationType, EnumerationDescription... enumerationDescription) {
738             for (EnumerationDescription anEnumerationDescription : enumerationDescription) {
739                 if (!anEnumerationDescription.getEnumerationType().equals(enumerationType)) {
740                     return false;
741                 }
742             }
743             return true;
744         }
745
746         /**
747          * Checks if the supplied enumeration descriptions describe the correct annotation type.
748          *
749          * @param annotationType        The annotation type to check for.
750          * @param annotationDescription The annotation descriptions to check.
751          * @return {@code trueif all annotation descriptions represent the annotation type in question.
752          */

753         private static boolean isAnnotationType(TypeDescription annotationType, AnnotationDescription... annotationDescription) {
754             for (AnnotationDescription anAnnotationDescription : annotationDescription) {
755                 if (!anAnnotationDescription.getAnnotationType().equals(annotationType)) {
756                     return false;
757                 }
758             }
759             return true;
760         }
761
762         /**
763          * {@inheritDoc}
764          */

765         public TypeVariableSource getEnclosingSource() {
766             return isStatic()
767                     ? TypeVariableSource.UNDEFINED
768                     : getDeclaringType().asErasure();
769         }
770
771         /**
772          * {@inheritDoc}
773          */

774         public boolean isInferrable() {
775             return true;
776         }
777
778         /**
779          * {@inheritDoc}
780          */

781         public <T> T accept(TypeVariableSource.Visitor<T> visitor) {
782             return visitor.onMethod(this.asDefined());
783         }
784
785         /**
786          * {@inheritDoc}
787          */

788         public boolean isGenerified() {
789             return !getTypeVariables().isEmpty();
790         }
791
792         /**
793          * {@inheritDoc}
794          */

795         public MethodDescription.Token asToken(ElementMatcher<? super TypeDescription> matcher) {
796             TypeDescription.Generic receiverType = getReceiverType();
797             return new MethodDescription.Token(getInternalName(),
798                     getModifiers(),
799                     getTypeVariables().asTokenList(matcher),
800                     getReturnType().accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)),
801                     getParameters().asTokenList(matcher),
802                     getExceptionTypes().accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)),
803                     getDeclaredAnnotations(),
804                     getDefaultValue(),
805                     receiverType == null
806                             ? TypeDescription.Generic.UNDEFINED
807                             : receiverType.accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)));
808         }
809
810         /**
811          * {@inheritDoc}
812          */

813         public SignatureToken asSignatureToken() {
814             return new SignatureToken(getInternalName(), getReturnType().asErasure(), getParameters().asTypeList().asErasures());
815         }
816
817         /**
818          * {@inheritDoc}
819          */

820         public TypeToken asTypeToken() {
821             return new TypeToken(getReturnType().asErasure(), getParameters().asTypeList().asErasures());
822         }
823
824         /**
825          * {@inheritDoc}
826          */

827         public boolean isBridgeCompatible(TypeToken typeToken) {
828             List<TypeDescription> types = getParameters().asTypeList().asErasures(), bridgeTypes = typeToken.getParameterTypes();
829             if (types.size() != bridgeTypes.size()) {
830                 return false;
831             }
832             for (int index = 0; index < types.size(); index++) {
833                 if (!types.get(index).equals(bridgeTypes.get(index)) && (types.get(index).isPrimitive() || bridgeTypes.get(index).isPrimitive())) {
834                     return false;
835                 }
836             }
837             TypeDescription returnType = getReturnType().asErasure(), bridgeReturnType = typeToken.getReturnType();
838             return returnType.equals(bridgeReturnType) || (!returnType.isPrimitive() && !bridgeReturnType.isPrimitive());
839         }
840
841         @Override
842         @CachedReturnPlugin.Enhance
843         public int hashCode() {
844             int hashCode = 17 + getDeclaringType().hashCode();
845             hashCode = 31 * hashCode + getInternalName().hashCode();
846             hashCode = 31 * hashCode + getReturnType().asErasure().hashCode();
847             return 31 * hashCode + getParameters().asTypeList().asErasures().hashCode();
848         }
849
850         @Override
851         public boolean equals(Object other) {
852             if (this == other) {
853                 return true;
854             } else if (!(other instanceof MethodDescription)) {
855                 return false;
856             }
857             MethodDescription methodDescription = (MethodDescription) other;
858             return getInternalName().equals(methodDescription.getInternalName())
859                     && getDeclaringType().equals(methodDescription.getDeclaringType())
860                     && getReturnType().asErasure().equals(methodDescription.getReturnType().asErasure())
861                     && getParameters().asTypeList().asErasures().equals(methodDescription.getParameters().asTypeList().asErasures());
862         }
863
864         /**
865          * {@inheritDoc}
866          */

867         public String toGenericString() {
868             StringBuilder stringBuilder = new StringBuilder();
869             int modifiers = getModifiers() & SOURCE_MODIFIERS;
870             if (modifiers != EMPTY_MASK) {
871                 stringBuilder.append(Modifier.toString(modifiers)).append(' ');
872             }
873             if (isMethod()) {
874                 stringBuilder.append(getReturnType().getActualName()).append(' ');
875                 stringBuilder.append(getDeclaringType().asErasure().getActualName()).append('.');
876             }
877             stringBuilder.append(getName()).append('(');
878             boolean first = true;
879             for (TypeDescription.Generic typeDescription : getParameters().asTypeList()) {
880                 if (!first) {
881                     stringBuilder.append(',');
882                 } else {
883                     first = false;
884                 }
885                 stringBuilder.append(typeDescription.getActualName());
886             }
887             stringBuilder.append(')');
888             TypeList.Generic exceptionTypes = getExceptionTypes();
889             if (!exceptionTypes.isEmpty()) {
890                 stringBuilder.append(throws ");
891                 first = true;
892                 for (TypeDescription.Generic typeDescription : exceptionTypes) {
893                     if (!first) {
894                         stringBuilder.append(',');
895                     } else {
896                         first = false;
897                     }
898                     stringBuilder.append(typeDescription.getActualName());
899                 }
900             }
901             return stringBuilder.toString();
902         }
903
904         @Override
905         public String toString() {
906             StringBuilder stringBuilder = new StringBuilder();
907             int modifiers = getModifiers() & SOURCE_MODIFIERS;
908             if (modifiers != EMPTY_MASK) {
909                 stringBuilder.append(Modifier.toString(modifiers)).append(' ');
910             }
911             if (isMethod()) {
912                 stringBuilder.append(getReturnType().asErasure().getActualName()).append(' ');
913                 stringBuilder.append(getDeclaringType().asErasure().getActualName()).append('.');
914             }
915             stringBuilder.append(getName()).append('(');
916             boolean first = true;
917             for (TypeDescription typeDescription : getParameters().asTypeList().asErasures()) {
918                 if (!first) {
919                     stringBuilder.append(',');
920                 } else {
921                     first = false;
922                 }
923                 stringBuilder.append(typeDescription.getActualName());
924             }
925             stringBuilder.append(')');
926             TypeList exceptionTypes = getExceptionTypes().asErasures();
927             if (!exceptionTypes.isEmpty()) {
928                 stringBuilder.append(throws ");
929                 first = true;
930                 for (TypeDescription typeDescription : exceptionTypes) {
931                     if (!first) {
932                         stringBuilder.append(',');
933                     } else {
934                         first = false;
935                     }
936                     stringBuilder.append(typeDescription.getActualName());
937                 }
938             }
939             return stringBuilder.toString();
940         }
941     }
942
943     /**
944      * An implementation of a method description for a loaded constructor.
945      */

946     class ForLoadedConstructor extends InDefinedShape.AbstractBase implements ParameterDescription.ForLoadedParameter.ParameterAnnotationSource {
947
948         /**
949          * The loaded constructor that is represented by this instance.
950          */

951         private final Constructor<?> constructor;
952
953         /**
954          * Creates a new immutable method description for a loaded constructor.
955          *
956          * @param constructor The loaded constructor to be represented by this method description.
957          */

958         public ForLoadedConstructor(Constructor<?> constructor) {
959             this.constructor = constructor;
960         }
961
962         /**
963          * {@inheritDoc}
964          */

965         public TypeDescription getDeclaringType() {
966             return TypeDescription.ForLoadedType.of(constructor.getDeclaringClass());
967         }
968
969         /**
970          * {@inheritDoc}
971          */

972         public TypeDescription.Generic getReturnType() {
973             return TypeDescription.Generic.VOID;
974         }
975
976         /**
977          * {@inheritDoc}
978          */

979         @CachedReturnPlugin.Enhance("parameters")
980         public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
981             return ParameterList.ForLoadedExecutable.of(constructor, this);
982         }
983
984         /**
985          * {@inheritDoc}
986          */

987         public TypeList.Generic getExceptionTypes() {
988             return new TypeList.Generic.OfConstructorExceptionTypes(constructor);
989         }
990
991         /**
992          * {@inheritDoc}
993          */

994         public boolean isConstructor() {
995             return true;
996         }
997
998         /**
999          * {@inheritDoc}
1000          */

1001         public boolean isTypeInitializer() {
1002             return false;
1003         }
1004
1005         /**
1006          * {@inheritDoc}
1007          */

1008         public boolean represents(Method method) {
1009             return false;
1010         }
1011
1012         /**
1013          * {@inheritDoc}
1014          */

1015         public boolean represents(Constructor<?> constructor) {
1016             return this.constructor.equals(constructor) || equals(new MethodDescription.ForLoadedConstructor(constructor));
1017         }
1018
1019         /**
1020          * {@inheritDoc}
1021          */

1022         public String getName() {
1023             return constructor.getName();
1024         }
1025
1026         /**
1027          * {@inheritDoc}
1028          */

1029         public int getModifiers() {
1030             return constructor.getModifiers();
1031         }
1032
1033         /**
1034          * {@inheritDoc}
1035          */

1036         public boolean isSynthetic() {
1037             return constructor.isSynthetic();
1038         }
1039
1040         /**
1041          * {@inheritDoc}
1042          */

1043         public String getInternalName() {
1044             return CONSTRUCTOR_INTERNAL_NAME;
1045         }
1046
1047         /**
1048          * {@inheritDoc}
1049          */

1050         public String getDescriptor() {
1051             return Type.getConstructorDescriptor(constructor);
1052         }
1053
1054         /**
1055          * {@inheritDoc}
1056          */

1057         public AnnotationValue<?, ?> getDefaultValue() {
1058             return AnnotationValue.UNDEFINED;
1059         }
1060
1061         /**
1062          * {@inheritDoc}
1063          */

1064         @CachedReturnPlugin.Enhance("declaredAnnotations")
1065         public AnnotationList getDeclaredAnnotations() {
1066             return new AnnotationList.ForLoadedAnnotations(constructor.getDeclaredAnnotations());
1067         }
1068
1069         /**
1070          * {@inheritDoc}
1071          */

1072         public TypeList.Generic getTypeVariables() {
1073             return TypeList.Generic.ForLoadedTypes.OfTypeVariables.of(constructor);
1074         }
1075
1076         /**
1077          * {@inheritDoc}
1078          */

1079         public TypeDescription.Generic getReceiverType() {
1080             TypeDescription.Generic receiverType = TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveReceiverType(constructor);
1081             return receiverType == null
1082                     ? super.getReceiverType()
1083                     : receiverType;
1084         }
1085
1086         /**
1087          * {@inheritDoc}
1088          */

1089         @CachedReturnPlugin.Enhance("parameterAnnotations")
1090         public Annotation[][] getParameterAnnotations() {
1091             return constructor.getParameterAnnotations();
1092         }
1093     }
1094
1095     /**
1096      * An implementation of a method description for a loaded method.
1097      */

1098     class ForLoadedMethod extends InDefinedShape.AbstractBase implements ParameterDescription.ForLoadedParameter.ParameterAnnotationSource {
1099
1100         /**
1101          * The loaded method that is represented by this instance.
1102          */

1103         private final Method method;
1104
1105         /**
1106          * Creates a new immutable method description for a loaded method.
1107          *
1108          * @param method The loaded method to be represented by this method description.
1109          */

1110         public ForLoadedMethod(Method method) {
1111             this.method = method;
1112         }
1113
1114         /**
1115          * {@inheritDoc}
1116          */

1117         public TypeDescription getDeclaringType() {
1118             return TypeDescription.ForLoadedType.of(method.getDeclaringClass());
1119         }
1120
1121         /**
1122          * {@inheritDoc}
1123          */

1124         public TypeDescription.Generic getReturnType() {
1125             if (TypeDescription.AbstractBase.RAW_TYPES) {
1126                 return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(method.getReturnType());
1127             }
1128             return new TypeDescription.Generic.LazyProjection.ForLoadedReturnType(method);
1129         }
1130
1131         /**
1132          * {@inheritDoc}
1133          */

1134         @CachedReturnPlugin.Enhance("parameters")
1135         public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1136             return ParameterList.ForLoadedExecutable.of(method, this);
1137         }
1138
1139         /**
1140          * {@inheritDoc}
1141          */

1142         public TypeList.Generic getExceptionTypes() {
1143             if (TypeDescription.AbstractBase.RAW_TYPES) {
1144                 return new TypeList.Generic.ForLoadedTypes(method.getExceptionTypes());
1145             }
1146             return new TypeList.Generic.OfMethodExceptionTypes(method);
1147         }
1148
1149         /**
1150          * {@inheritDoc}
1151          */

1152         public boolean isConstructor() {
1153             return false;
1154         }
1155
1156         /**
1157          * {@inheritDoc}
1158          */

1159         public boolean isTypeInitializer() {
1160             return false;
1161         }
1162
1163         /**
1164          * {@inheritDoc}
1165          */

1166         public boolean isBridge() {
1167             return method.isBridge();
1168         }
1169
1170         /**
1171          * {@inheritDoc}
1172          */

1173         public boolean represents(Method method) {
1174             return this.method.equals(method) || equals(new MethodDescription.ForLoadedMethod(method));
1175         }
1176
1177         /**
1178          * {@inheritDoc}
1179          */

1180         public boolean represents(Constructor<?> constructor) {
1181             return false;
1182         }
1183
1184         /**
1185          * {@inheritDoc}
1186          */

1187         public String getName() {
1188             return method.getName();
1189         }
1190
1191         /**
1192          * {@inheritDoc}
1193          */

1194         public int getModifiers() {
1195             return method.getModifiers();
1196         }
1197
1198         /**
1199          * {@inheritDoc}
1200          */

1201         public boolean isSynthetic() {
1202             return method.isSynthetic();
1203         }
1204
1205         /**
1206          * {@inheritDoc}
1207          */

1208         public String getInternalName() {
1209             return method.getName();
1210         }
1211
1212         /**
1213          * {@inheritDoc}
1214          */

1215         public String getDescriptor() {
1216             return Type.getMethodDescriptor(method);
1217         }
1218
1219         /**
1220          * Returns the loaded method that is represented by this method description.
1221          *
1222          * @return The loaded method that is represented by this method description.
1223          */

1224         public Method getLoadedMethod() {
1225             return method;
1226         }
1227
1228         /**
1229          * {@inheritDoc}
1230          */

1231         @CachedReturnPlugin.Enhance("declaredAnnotations")
1232         public AnnotationList getDeclaredAnnotations() {
1233             return new AnnotationList.ForLoadedAnnotations(method.getDeclaredAnnotations());
1234         }
1235
1236         /**
1237          * {@inheritDoc}
1238          */

1239         public AnnotationValue<?, ?> getDefaultValue() {
1240             Object value = method.getDefaultValue();
1241             return value == null
1242                     ? AnnotationValue.UNDEFINED
1243                     : AnnotationDescription.ForLoadedAnnotation.asValue(value, method.getReturnType());
1244         }
1245
1246         /**
1247          * {@inheritDoc}
1248          */

1249         public TypeList.Generic getTypeVariables() {
1250             if (TypeDescription.AbstractBase.RAW_TYPES) {
1251                 return new TypeList.Generic.Empty();
1252             }
1253             return TypeList.Generic.ForLoadedTypes.OfTypeVariables.of(method);
1254         }
1255
1256         /**
1257          * {@inheritDoc}
1258          */

1259         public TypeDescription.Generic getReceiverType() {
1260             if (TypeDescription.AbstractBase.RAW_TYPES) {
1261                 return super.getReceiverType();
1262             }
1263             TypeDescription.Generic receiverType = TypeDescription.Generic.AnnotationReader.DISPATCHER.resolveReceiverType(method);
1264             return receiverType == null
1265                     ? super.getReceiverType()
1266                     : receiverType;
1267         }
1268
1269         /**
1270          * {@inheritDoc}
1271          */

1272         @CachedReturnPlugin.Enhance("parameterAnnotations")
1273         public Annotation[][] getParameterAnnotations() {
1274             return method.getParameterAnnotations();
1275         }
1276     }
1277
1278     /**
1279      * A latent method description describes a method that is not attached to a declaring
1280      * {@link TypeDescription}.
1281      */

1282     class Latent extends InDefinedShape.AbstractBase {
1283
1284         /**
1285          * The type that is declaring this method.
1286          */

1287         private final TypeDescription declaringType;
1288
1289         /**
1290          * The internal name of this method.
1291          */

1292         private final String internalName;
1293
1294         /**
1295          * The modifiers of this method.
1296          */

1297         private final int modifiers;
1298
1299         /**
1300          * A tokenized list representing the method's type variables.
1301          */

1302         private final List<? extends TypeVariableToken> typeVariables;
1303
1304         /**
1305          * The return type of this method.
1306          */

1307         private final TypeDescription.Generic returnType;
1308
1309         /**
1310          * The parameter tokens describing this method.
1311          */

1312         private final List<? extends ParameterDescription.Token> parameterTokens;
1313
1314         /**
1315          * This method's exception types.
1316          */

1317         private final List<? extends TypeDescription.Generic> exceptionTypes;
1318
1319         /**
1320          * The annotations of this method.
1321          */

1322         private final List<? extends AnnotationDescription> declaredAnnotations;
1323
1324         /**
1325          * The default value of this method or {@code nullif no default annotation value is defined.
1326          */

1327         private final AnnotationValue<?, ?> defaultValue;
1328
1329         /**
1330          * The receiver type of this method or {@code nullif the receiver type is defined implicitly.
1331          */

1332         private final TypeDescription.Generic receiverType;
1333
1334         /**
1335          * Creates a new latent method description. All provided types are attached to this instance before they are returned.
1336          *
1337          * @param declaringType The declaring type of the method.
1338          * @param token         A token representing the method's shape.
1339          */

1340         public Latent(TypeDescription declaringType, MethodDescription.Token token) {
1341             this(declaringType,
1342                     token.getName(),
1343                     token.getModifiers(),
1344                     token.getTypeVariableTokens(),
1345                     token.getReturnType(),
1346                     token.getParameterTokens(),
1347                     token.getExceptionTypes(),
1348                     token.getAnnotations(),
1349                     token.getDefaultValue(),
1350                     token.getReceiverType());
1351         }
1352
1353         /**
1354          * Creates a new latent method description. All provided types are attached to this instance before they are returned.
1355          *
1356          * @param declaringType       The type that is declaring this method.
1357          * @param internalName        The internal name of this method.
1358          * @param modifiers           The modifiers of this method.
1359          * @param typeVariables       The type variables of the described method.
1360          * @param returnType          The return type of this method.
1361          * @param parameterTokens     The parameter tokens describing this method.
1362          * @param exceptionTypes      This method's exception types.
1363          * @param declaredAnnotations The annotations of this method.
1364          * @param defaultValue        The default value of this method or {@code nullif no default annotation value is defined.
1365          * @param receiverType        The receiver type of this method or {@code nullif the receiver type is defined implicitly.
1366          */

1367         public Latent(TypeDescription declaringType,
1368                       String internalName,
1369                       int modifiers,
1370                       List<? extends TypeVariableToken> typeVariables,
1371                       TypeDescription.Generic returnType,
1372                       List<? extends ParameterDescription.Token> parameterTokens,
1373                       List<? extends TypeDescription.Generic> exceptionTypes,
1374                       List<? extends AnnotationDescription> declaredAnnotations,
1375                       AnnotationValue<?, ?> defaultValue,
1376                       TypeDescription.Generic receiverType) {
1377             this.declaringType = declaringType;
1378             this.internalName = internalName;
1379             this.modifiers = modifiers;
1380             this.typeVariables = typeVariables;
1381             this.returnType = returnType;
1382             this.parameterTokens = parameterTokens;
1383             this.exceptionTypes = exceptionTypes;
1384             this.declaredAnnotations = declaredAnnotations;
1385             this.defaultValue = defaultValue;
1386             this.receiverType = receiverType;
1387         }
1388
1389         /**
1390          * {@inheritDoc}
1391          */

1392         public TypeList.Generic getTypeVariables() {
1393             return TypeList.Generic.ForDetachedTypes.attachVariables(this, typeVariables);
1394         }
1395
1396         /**
1397          * {@inheritDoc}
1398          */

1399         public TypeDescription.Generic getReturnType() {
1400             return returnType.accept(TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
1401         }
1402
1403         /**
1404          * {@inheritDoc}
1405          */

1406         public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1407             return new ParameterList.ForTokens(this, parameterTokens);
1408         }
1409
1410         /**
1411          * {@inheritDoc}
1412          */

1413         public TypeList.Generic getExceptionTypes() {
1414             return TypeList.Generic.ForDetachedTypes.attach(this, exceptionTypes);
1415         }
1416
1417         /**
1418          * {@inheritDoc}
1419          */

1420         public AnnotationList getDeclaredAnnotations() {
1421             return new AnnotationList.Explicit(declaredAnnotations);
1422         }
1423
1424         /**
1425          * {@inheritDoc}
1426          */

1427         public String getInternalName() {
1428             return internalName;
1429         }
1430
1431         /**
1432          * {@inheritDoc}
1433          */

1434         public TypeDescription getDeclaringType() {
1435             return declaringType;
1436         }
1437
1438         /**
1439          * {@inheritDoc}
1440          */

1441         public int getModifiers() {
1442             return modifiers;
1443         }
1444
1445         /**
1446          * {@inheritDoc}
1447          */

1448         public AnnotationValue<?, ?> getDefaultValue() {
1449             return defaultValue;
1450         }
1451
1452         /**
1453          * {@inheritDoc}
1454          */

1455         public TypeDescription.Generic getReceiverType() {
1456             return receiverType == null
1457                     ? super.getReceiverType()
1458                     : receiverType.accept(TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
1459         }
1460
1461         /**
1462          * A method description that represents the type initializer.
1463          */

1464         public static class TypeInitializer extends InDefinedShape.AbstractBase {
1465
1466             /**
1467              * The type for which the type initializer should be represented.
1468              */

1469             private final TypeDescription typeDescription;
1470
1471             /**
1472              * Creates a new method description representing the type initializer.
1473              *
1474              * @param typeDescription The type for which the type initializer should be represented.
1475              */

1476             public TypeInitializer(TypeDescription typeDescription) {
1477                 this.typeDescription = typeDescription;
1478             }
1479
1480             /**
1481              * {@inheritDoc}
1482              */

1483             public TypeDescription.Generic getReturnType() {
1484                 return TypeDescription.Generic.VOID;
1485             }
1486
1487             /**
1488              * {@inheritDoc}
1489              */

1490             public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1491                 return new ParameterList.Empty<ParameterDescription.InDefinedShape>();
1492             }
1493
1494             /**
1495              * {@inheritDoc}
1496              */

1497             public TypeList.Generic getExceptionTypes() {
1498                 return new TypeList.Generic.Empty();
1499             }
1500
1501             /**
1502              * {@inheritDoc}
1503              */

1504             public AnnotationValue<?, ?> getDefaultValue() {
1505                 return AnnotationValue.UNDEFINED;
1506             }
1507
1508             /**
1509              * {@inheritDoc}
1510              */

1511             public TypeList.Generic getTypeVariables() {
1512                 return new TypeList.Generic.Empty();
1513             }
1514
1515             /**
1516              * {@inheritDoc}
1517              */

1518             public AnnotationList getDeclaredAnnotations() {
1519                 return new AnnotationList.Empty();
1520             }
1521
1522             /**
1523              * {@inheritDoc}
1524              */

1525             public TypeDescription getDeclaringType() {
1526                 return typeDescription;
1527             }
1528
1529             /**
1530              * {@inheritDoc}
1531              */

1532             public int getModifiers() {
1533                 return TYPE_INITIALIZER_MODIFIER;
1534             }
1535
1536             /**
1537              * {@inheritDoc}
1538              */

1539             public String getInternalName() {
1540                 return MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME;
1541             }
1542         }
1543     }
1544
1545     /**
1546      * A method description that represents a given method but with substituted method types.
1547      */

1548     class TypeSubstituting extends AbstractBase implements InGenericShape {
1549
1550         /**
1551          * The type that declares this type-substituted method.
1552          */

1553         private final TypeDescription.Generic declaringType;
1554
1555         /**
1556          * The represented method description.
1557          */

1558         private final MethodDescription methodDescription;
1559
1560         /**
1561          * A visitor that is applied to the method type.
1562          */

1563         private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
1564
1565         /**
1566          * Creates a method description with substituted method types.
1567          *
1568          * @param declaringType     The type that is declaring the substituted method.
1569          * @param methodDescription The represented method description.
1570          * @param visitor           A visitor that is applied to the method type.
1571          */

1572         public TypeSubstituting(TypeDescription.Generic declaringType,
1573                                 MethodDescription methodDescription,
1574                                 TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
1575             this.declaringType = declaringType;
1576             this.methodDescription = methodDescription;
1577             this.visitor = visitor;
1578         }
1579
1580         /**
1581          * {@inheritDoc}
1582          */

1583         public TypeDescription.Generic getReturnType() {
1584             return methodDescription.getReturnType().accept(visitor);
1585         }
1586
1587         /**
1588          * {@inheritDoc}
1589          */

1590         public TypeList.Generic getTypeVariables() {
1591             return methodDescription.getTypeVariables().accept(visitor).filter(ElementMatchers.ofSort(TypeDefinition.Sort.VARIABLE));
1592         }
1593
1594         /**
1595          * {@inheritDoc}
1596          */

1597         public ParameterList<ParameterDescription.InGenericShape> getParameters() {
1598             return new ParameterList.TypeSubstituting(this, methodDescription.getParameters(), visitor);
1599         }
1600
1601         /**
1602          * {@inheritDoc}
1603          */

1604         public TypeList.Generic getExceptionTypes() {
1605             return new TypeList.Generic.ForDetachedTypes(methodDescription.getExceptionTypes(), visitor);
1606         }
1607
1608         /**
1609          * {@inheritDoc}
1610          */

1611         public AnnotationValue<?, ?> getDefaultValue() {
1612             return methodDescription.getDefaultValue();
1613         }
1614
1615         /**
1616          * {@inheritDoc}
1617          */

1618         public TypeDescription.Generic getReceiverType() {
1619             TypeDescription.Generic receiverType = methodDescription.getReceiverType();
1620             return receiverType == null
1621                     ? TypeDescription.Generic.UNDEFINED
1622                     : receiverType.accept(visitor);
1623         }
1624
1625         /**
1626          * {@inheritDoc}
1627          */

1628         public AnnotationList getDeclaredAnnotations() {
1629             return methodDescription.getDeclaredAnnotations();
1630         }
1631
1632         /**
1633          * {@inheritDoc}
1634          */

1635         public TypeDescription.Generic getDeclaringType() {
1636             return declaringType;
1637         }
1638
1639         /**
1640          * {@inheritDoc}
1641          */

1642         public int getModifiers() {
1643             return methodDescription.getModifiers();
1644         }
1645
1646         /**
1647          * {@inheritDoc}
1648          */

1649         public String getInternalName() {
1650             return methodDescription.getInternalName();
1651         }
1652
1653         /**
1654          * {@inheritDoc}
1655          */

1656         public InDefinedShape asDefined() {
1657             return methodDescription.asDefined();
1658         }
1659
1660         /**
1661          * {@inheritDoc}
1662          */

1663         public boolean isConstructor() {
1664             return methodDescription.isConstructor();
1665         }
1666
1667         /**
1668          * {@inheritDoc}
1669          */

1670         public boolean isMethod() {
1671             return methodDescription.isMethod();
1672         }
1673
1674         /**
1675          * {@inheritDoc}
1676          */

1677         public boolean isTypeInitializer() {
1678             return methodDescription.isTypeInitializer();
1679         }
1680     }
1681
1682     /**
1683      * A token representing a method's properties detached from a type.
1684      */

1685     class Token implements ByteCodeElement.Token<Token> {
1686
1687         /**
1688          * The internal name of the represented method.
1689          */

1690         private final String name;
1691
1692         /**
1693          * The modifiers of the represented method.
1694          */

1695         private final int modifiers;
1696
1697         /**
1698          * A list of tokens representing the method's type variables.
1699          */

1700         private final List<? extends TypeVariableToken> typeVariableTokens;
1701
1702         /**
1703          * The return type of the represented method.
1704          */

1705         private final TypeDescription.Generic returnType;
1706
1707         /**
1708          * The parameter tokens of the represented method.
1709          */

1710         private final List<? extends ParameterDescription.Token> parameterTokens;
1711
1712         /**
1713          * The exception types of the represented method.
1714          */

1715         private final List<? extends TypeDescription.Generic> exceptionTypes;
1716
1717         /**
1718          * The annotations of the represented method.
1719          */

1720         private final List<? extends AnnotationDescription> annotations;
1721
1722         /**
1723          * The default value of the represented method or {@code nullif no such value exists.
1724          */

1725         private final AnnotationValue<?, ?> defaultValue;
1726
1727         /**
1728          * The receiver type of the represented method or {@code nullif the receiver type is implicit.
1729          */

1730         private final TypeDescription.Generic receiverType;
1731
1732         /**
1733          * Creates a new method token representing a constructor without any parameters, exception types, type variables or annotations.
1734          * All types must be represented in an detached format.
1735          *
1736          * @param modifiers The constructor's modifiers.
1737          */

1738         public Token(int modifiers) {
1739             this(MethodDescription.CONSTRUCTOR_INTERNAL_NAME, modifiers, TypeDescription.Generic.VOID);
1740         }
1741
1742         /**
1743          * Creates a new method token representing a method without any parameters, exception types, type variables or annotations.
1744          * All types must be represented in an detached format.
1745          *
1746          * @param name       The name of the method.
1747          * @param modifiers  The modifiers of the method.
1748          * @param returnType The return type of the method.
1749          */

1750         public Token(String name, int modifiers, TypeDescription.Generic returnType) {
1751             this(name, modifiers, returnType, Collections.<TypeDescription.Generic>emptyList());
1752         }
1753
1754         /**
1755          * Creates a new method token with simple values. All types must be represented in an detached format.
1756          *
1757          * @param name           The internal name of the represented method.
1758          * @param modifiers      The modifiers of the represented method.
1759          * @param returnType     The return type of the represented method.
1760          * @param parameterTypes The parameter types of this method.
1761          */

1762         public Token(String name, int modifiers, TypeDescription.Generic returnType, List<? extends TypeDescription.Generic> parameterTypes) {
1763             this(name,
1764                     modifiers,
1765                     Collections.<TypeVariableToken>emptyList(),
1766                     returnType,
1767                     new ParameterDescription.Token.TypeList(parameterTypes),
1768                     Collections.<TypeDescription.Generic>emptyList(),
1769                     Collections.<AnnotationDescription>emptyList(),
1770                     AnnotationValue.UNDEFINED,
1771                     TypeDescription.Generic.UNDEFINED);
1772         }
1773
1774         /**
1775          * Creates a new token for a method description. All types must be represented in an detached format.
1776          *
1777          * @param name               The internal name of the represented method.
1778          * @param modifiers          The modifiers of the represented method.
1779          * @param typeVariableTokens The type variables of the the represented method.
1780          * @param returnType         The return type of the represented method.
1781          * @param parameterTokens    The parameter tokens of the represented method.
1782          * @param exceptionTypes     The exception types of the represented method.
1783          * @param annotations        The annotations of the represented method.
1784          * @param defaultValue       The default value of the represented method or {@code nullif no such value exists.
1785          * @param receiverType       The receiver type of the represented method or {@code nullif the receiver type is implicit.
1786          */

1787         public Token(String name,
1788                      int modifiers,
1789                      List<? extends TypeVariableToken> typeVariableTokens,
1790                      TypeDescription.Generic returnType,
1791                      List<? extends ParameterDescription.Token> parameterTokens,
1792                      List<? extends TypeDescription.Generic> exceptionTypes,
1793                      List<? extends AnnotationDescription> annotations,
1794                      AnnotationValue<?, ?> defaultValue,
1795                      TypeDescription.Generic receiverType) {
1796             this.name = name;
1797             this.modifiers = modifiers;
1798             this.typeVariableTokens = typeVariableTokens;
1799             this.returnType = returnType;
1800             this.parameterTokens = parameterTokens;
1801             this.exceptionTypes = exceptionTypes;
1802             this.annotations = annotations;
1803             this.defaultValue = defaultValue;
1804             this.receiverType = receiverType;
1805         }
1806
1807         /**
1808          * Returns the internal name of the represented method.
1809          *
1810          * @return The internal name of the represented method.
1811          */

1812         public String getName() {
1813             return name;
1814         }
1815
1816         /**
1817          * Returns the modifiers of the represented method.
1818          *
1819          * @return The modifiers of the represented method.
1820          */

1821         public int getModifiers() {
1822             return modifiers;
1823         }
1824
1825         /**
1826          * Returns the type variables of this method token.
1827          *
1828          * @return A a list of tokens representing the method's type variables.
1829          */

1830         public TokenList<TypeVariableToken> getTypeVariableTokens() {
1831             return new TokenList<TypeVariableToken>(typeVariableTokens);
1832         }
1833
1834         /**
1835          * Returns the return type of the represented method.
1836          *
1837          * @return The return type of the represented method.
1838          */

1839         public TypeDescription.Generic getReturnType() {
1840             return returnType;
1841         }
1842
1843         /**
1844          * Returns the parameter tokens of the represented method.
1845          *
1846          * @return The parameter tokens of the represented method.
1847          */

1848         public TokenList<ParameterDescription.Token> getParameterTokens() {
1849             return new TokenList<ParameterDescription.Token>(parameterTokens);
1850         }
1851
1852         /**
1853          * Returns the exception types of the represented method.
1854          *
1855          * @return The exception types of the represented method.
1856          */

1857         public TypeList.Generic getExceptionTypes() {
1858             return new TypeList.Generic.Explicit(exceptionTypes);
1859         }
1860
1861         /**
1862          * Returns the annotations of the represented method.
1863          *
1864          * @return The annotations of the represented method.
1865          */

1866         public AnnotationList getAnnotations() {
1867             return new AnnotationList.Explicit(annotations);
1868         }
1869
1870         /**
1871          * Returns the default value of the represented method.
1872          *
1873          * @return The default value of the represented method or {@code nullif no such value exists.
1874          */

1875         public AnnotationValue<?, ?> getDefaultValue() {
1876             return defaultValue;
1877         }
1878
1879         /**
1880          * Returns the receiver type of this token or {@code nullif the receiver type is implicit.
1881          *
1882          * @return The receiver type of this token or {@code nullif the receiver type is implicit.
1883          */

1884         public TypeDescription.Generic getReceiverType() {
1885             return receiverType;
1886         }
1887
1888         /**
1889          * {@inheritDoc}
1890          */

1891         public Token accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
1892             return new Token(name,
1893                     modifiers,
1894                     getTypeVariableTokens().accept(visitor),
1895                     returnType.accept(visitor),
1896                     getParameterTokens().accept(visitor),
1897                     getExceptionTypes().accept(visitor),
1898                     annotations,
1899                     defaultValue,
1900                     receiverType == null
1901                             ? TypeDescription.Generic.UNDEFINED
1902                             : receiverType.accept(visitor));
1903         }
1904
1905         /**
1906          * Creates a signature token that represents the method that is represented by this token.
1907          *
1908          * @param declaringType The declaring type of the method that this token represents.
1909          * @return A signature token representing this token.
1910          */

1911         public SignatureToken asSignatureToken(TypeDescription declaringType) {
1912             TypeDescription.Generic.Visitor<TypeDescription> visitor = new TypeDescription.Generic.Visitor.Reducing(declaringType, typeVariableTokens);
1913             List<TypeDescription> parameters = new ArrayList<TypeDescription>(parameterTokens.size());
1914             for (ParameterDescription.Token parameter : parameterTokens) {
1915                 parameters.add(parameter.getType().accept(visitor));
1916             }
1917             return new SignatureToken(name, returnType.accept(visitor), parameters);
1918         }
1919
1920         @Override
1921         @CachedReturnPlugin.Enhance
1922         public int hashCode() {
1923             int result = name.hashCode();
1924             result = 31 * result + modifiers;
1925             result = 31 * result + typeVariableTokens.hashCode();
1926             result = 31 * result + returnType.hashCode();
1927             result = 31 * result + parameterTokens.hashCode();
1928             result = 31 * result + exceptionTypes.hashCode();
1929             result = 31 * result + annotations.hashCode();
1930             result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0);
1931             result = 31 * result + (receiverType != null ? receiverType.hashCode() : 0);
1932             return result;
1933         }
1934
1935         @Override
1936         public boolean equals(Object other) {
1937             if (this == other) {
1938                 return true;
1939             } else if (other == null || getClass() != other.getClass()) {
1940                 return false;
1941             }
1942             Token token = (Token) other;
1943             return modifiers == token.modifiers
1944                     && name.equals(token.name)
1945                     && typeVariableTokens.equals(token.typeVariableTokens)
1946                     && returnType.equals(token.returnType)
1947                     && parameterTokens.equals(token.parameterTokens)
1948                     && exceptionTypes.equals(token.exceptionTypes)
1949                     && annotations.equals(token.annotations)
1950                     && (defaultValue != null ? defaultValue.equals(token.defaultValue) : token.defaultValue == null)
1951                     && (receiverType != null ? receiverType.equals(token.receiverType) : token.receiverType == null);
1952         }
1953
1954         @Override
1955         public String toString() {
1956             return "MethodDescription.Token{" +
1957                     "name='" + name + '\'' +
1958                     ", modifiers=" + modifiers +
1959                     ", typeVariableTokens=" + typeVariableTokens +
1960                     ", returnType=" + returnType +
1961                     ", parameterTokens=" + parameterTokens +
1962                     ", exceptionTypes=" + exceptionTypes +
1963                     ", annotations=" + annotations +
1964                     ", defaultValue=" + defaultValue +
1965                     ", receiverType=" + receiverType +
1966                     '}';
1967         }
1968     }
1969
1970     /**
1971      * A token representing a method's name and raw return and parameter types.
1972      */

1973     class SignatureToken {
1974
1975         /**
1976          * The internal name of the represented method.
1977          */

1978         private final String name;
1979
1980         /**
1981          * The represented method's raw return type.
1982          */

1983         private final TypeDescription returnType;
1984
1985         /**
1986          * The represented method's raw parameter types.
1987          */

1988         private final List<? extends TypeDescription> parameterTypes;
1989
1990         /**
1991          * Creates a new type token.
1992          *
1993          * @param name           The internal name of the represented method.
1994          * @param returnType     The represented method's raw return type.
1995          * @param parameterTypes The represented method's raw parameter types.
1996          */

1997         public SignatureToken(String name, TypeDescription returnType, List<? extends TypeDescription> parameterTypes) {
1998             this.name = name;
1999             this.returnType = returnType;
2000             this.parameterTypes = parameterTypes;
2001         }
2002
2003         /**
2004          * Returns the internal name of the represented method.
2005          *
2006          * @return The internal name of the represented method.
2007          */

2008         public String getName() {
2009             return name;
2010         }
2011
2012         /**
2013          * Returns this token's return type.
2014          *
2015          * @return This token's return type.
2016          */

2017         public TypeDescription getReturnType() {
2018             return returnType;
2019         }
2020
2021         /**
2022          * Returns this token's parameter types.
2023          *
2024          * @return This token's parameter types.
2025          */

2026         @SuppressWarnings("unchecked")
2027         public List<TypeDescription> getParameterTypes() {
2028             return (List<TypeDescription>) parameterTypes;
2029         }
2030
2031         /**
2032          * Returns this signature token as a type token.
2033          *
2034          * @return This signature token as a type token.
2035          */

2036         public TypeToken asTypeToken() {
2037             return new TypeToken(returnType, parameterTypes);
2038         }
2039
2040         @Override
2041         @CachedReturnPlugin.Enhance
2042         public int hashCode() {
2043             int result = name.hashCode();
2044             result = 31 * result + returnType.hashCode();
2045             result = 31 * result + parameterTypes.hashCode();
2046             return result;
2047         }
2048
2049         @Override
2050         public boolean equals(Object other) {
2051             if (this == other) {
2052                 return true;
2053             } else if (!(other instanceof SignatureToken)) {
2054                 return false;
2055             }
2056             SignatureToken signatureToken = (SignatureToken) other;
2057             return name.equals(signatureToken.name)
2058                     && returnType.equals(signatureToken.returnType)
2059                     && parameterTypes.equals(signatureToken.parameterTypes);
2060         }
2061
2062         @Override
2063         public String toString() {
2064             StringBuilder stringBuilder = new StringBuilder().append(returnType).append(' ').append(name).append('(');
2065             boolean first = true;
2066             for (TypeDescription parameterType : parameterTypes) {
2067                 if (first) {
2068                     first = false;
2069                 } else {
2070                     stringBuilder.append(',');
2071                 }
2072                 stringBuilder.append(parameterType);
2073             }
2074             return stringBuilder.append(')').toString();
2075         }
2076     }
2077
2078     /**
2079      * A token representing a method's erased return and parameter types.
2080      */

2081     class TypeToken {
2082
2083         /**
2084          * The represented method's raw return type.
2085          */

2086         private final TypeDescription returnType;
2087
2088         /**
2089          * The represented method's raw parameter types.
2090          */

2091         private final List<? extends TypeDescription> parameterTypes;
2092
2093         /**
2094          * Creates a new type token.
2095          *
2096          * @param returnType     The represented method's raw return type.
2097          * @param parameterTypes The represented method's raw parameter types.
2098          */

2099         public TypeToken(TypeDescription returnType, List<? extends TypeDescription> parameterTypes) {
2100             this.returnType = returnType;
2101             this.parameterTypes = parameterTypes;
2102         }
2103
2104         /**
2105          * Returns this token's return type.
2106          *
2107          * @return This token's return type.
2108          */

2109         public TypeDescription getReturnType() {
2110             return returnType;
2111         }
2112
2113         /**
2114          * Returns this token's parameter types.
2115          *
2116          * @return This token's parameter types.
2117          */

2118         @SuppressWarnings("unchecked")
2119         public List<TypeDescription> getParameterTypes() {
2120             return (List<TypeDescription>) parameterTypes;
2121         }
2122
2123         @Override
2124         @CachedReturnPlugin.Enhance
2125         public int hashCode() {
2126             int result = returnType.hashCode();
2127             result = 31 * result + parameterTypes.hashCode();
2128             return result;
2129         }
2130
2131         @Override
2132         public boolean equals(Object other) {
2133             if (this == other) {
2134                 return true;
2135             } else if (!(other instanceof TypeToken)) {
2136                 return false;
2137             }
2138             TypeToken typeToken = (TypeToken) other;
2139             return returnType.equals(typeToken.returnType) && parameterTypes.equals(typeToken.parameterTypes);
2140         }
2141
2142         @Override
2143         public String toString() {
2144             StringBuilder stringBuilder = new StringBuilder().append('(');
2145             for (TypeDescription parameterType : parameterTypes) {
2146                 stringBuilder.append(parameterType.getDescriptor());
2147             }
2148             return stringBuilder.append(')').append(returnType.getDescriptor()).toString();
2149         }
2150     }
2151 }
2152