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

raphw / byte-buddy / #801

27 Oct 2025 09:37AM UTC coverage: 84.715% (-0.4%) from 85.118%
#801

push

raphw
Fix imports.

29586 of 34924 relevant lines covered (84.72%)

0.85 hits per line

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

88.93
/byte-buddy-dep/src/main/java/net/bytebuddy/description/method/MethodDescription.java
1
/*
2
 * Copyright 2014 - Present Rafael Winterhalter
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.bytebuddy.description.method;
17

18
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19
import net.bytebuddy.build.AccessControllerPlugin;
20
import net.bytebuddy.build.CachedReturnPlugin;
21
import net.bytebuddy.description.ByteCodeElement;
22
import net.bytebuddy.description.DeclaredByType;
23
import net.bytebuddy.description.ModifierReviewable;
24
import net.bytebuddy.description.TypeVariableSource;
25
import net.bytebuddy.description.annotation.AnnotationDescription;
26
import net.bytebuddy.description.annotation.AnnotationList;
27
import net.bytebuddy.description.annotation.AnnotationValue;
28
import net.bytebuddy.description.enumeration.EnumerationDescription;
29
import net.bytebuddy.description.modifier.ModifierContributor;
30
import net.bytebuddy.description.modifier.Visibility;
31
import net.bytebuddy.description.type.TypeDefinition;
32
import net.bytebuddy.description.type.TypeDescription;
33
import net.bytebuddy.description.type.TypeList;
34
import net.bytebuddy.description.type.TypeVariableToken;
35
import net.bytebuddy.matcher.ElementMatcher;
36
import net.bytebuddy.matcher.ElementMatchers;
37
import net.bytebuddy.utility.JavaType;
38
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
39
import net.bytebuddy.utility.nullability.AlwaysNull;
40
import net.bytebuddy.utility.nullability.MaybeNull;
41
import org.objectweb.asm.Opcodes;
42
import org.objectweb.asm.Type;
43
import org.objectweb.asm.signature.SignatureWriter;
44

45
import javax.annotation.Nonnull;
46
import java.lang.annotation.Annotation;
47
import java.lang.reflect.AnnotatedElement;
48
import java.lang.reflect.Constructor;
49
import java.lang.reflect.GenericSignatureFormatError;
50
import java.lang.reflect.Method;
51
import java.lang.reflect.Modifier;
52
import java.security.PrivilegedAction;
53
import java.util.ArrayList;
54
import java.util.Arrays;
55
import java.util.Collections;
56
import java.util.Iterator;
57
import java.util.List;
58

59
import static net.bytebuddy.matcher.ElementMatchers.not;
60
import static net.bytebuddy.matcher.ElementMatchers.ofSort;
61

62
/**
63
 * Implementations of this interface describe a Java method, i.e. a method or a constructor. Implementations of this
64
 * interface must provide meaningful {@code equal(Object)} and {@code hashCode()} implementations.
65
 */
66
public interface MethodDescription extends TypeVariableSource,
67
        ModifierReviewable.ForMethodDescription,
68
        DeclaredByType.WithMandatoryDeclaration,
69
        ByteCodeElement.Member,
70
        ByteCodeElement.TypeDependant<MethodDescription.InDefinedShape, MethodDescription.Token> {
71

72
    /**
73
     * The internal name of a Java constructor.
74
     */
75
    String CONSTRUCTOR_INTERNAL_NAME = "<init>";
76

77
    /**
78
     * The internal name of a Java static initializer.
79
     */
80
    String TYPE_INITIALIZER_INTERNAL_NAME = "<clinit>";
81

82
    /**
83
     * The type initializer of any representation of a type initializer.
84
     */
85
    int TYPE_INITIALIZER_MODIFIER = Opcodes.ACC_STATIC;
86

87
    /**
88
     * Represents any undefined property of a type description that is instead represented as {@code null} in order
89
     * to resemble the Java reflection API which returns {@code null} and is intuitive to many Java developers.
90
     */
91
    @AlwaysNull
92
    InDefinedShape UNDEFINED = null;
1✔
93

94
    /**
95
     * {@inheritDoc}
96
     */
97
    @Nonnull
98
    TypeDefinition getDeclaringType();
99

100
    /**
101
     * Returns the return type of the described method.
102
     *
103
     * @return The return type of the described method.
104
     */
105
    TypeDescription.Generic getReturnType();
106

107
    /**
108
     * Returns a list of this method's parameters.
109
     *
110
     * @return A list of this method's parameters.
111
     */
112
    ParameterList<?> getParameters();
113

114
    /**
115
     * Returns the exception types of the described method.
116
     *
117
     * @return The exception types of the described method.
118
     */
119
    TypeList.Generic getExceptionTypes();
120

121
    /**
122
     * Returns this method's actual modifiers as it is present in a class file, i.e. includes a flag if this method
123
     * is marked {@link Deprecated}.
124
     *
125
     * @return The method's actual modifiers.
126
     */
127
    int getActualModifiers();
128

129
    /**
130
     * Returns this method's actual modifiers as it is present in a class file, i.e. includes a flag if this method
131
     * is marked {@link Deprecated} and adjusts the modifiers for being abstract or not.
132
     *
133
     * @param manifest {@code true} if the method should be treated as non-abstract.
134
     * @return The method's actual modifiers.
135
     */
136
    int getActualModifiers(boolean manifest);
137

138
    /**
139
     * Returns this method's actual modifiers as it is present in a class file, i.e. includes a flag if this method
140
     * is marked {@link Deprecated} and adjusts the modifiers for being abstract or not. Additionally, this method
141
     * resolves a required minimal visibility.
142
     *
143
     * @param manifest   {@code true} if the method should be treated as non-abstract.
144
     * @param visibility The minimal visibility to enforce for this method.
145
     * @return The method's actual modifiers.
146
     */
147
    int getActualModifiers(boolean manifest, Visibility visibility);
148

149
    /**
150
     * Checks if this method description represents a constructor.
151
     *
152
     * @return {@code true} if this method description represents a constructor.
153
     */
154
    boolean isConstructor();
155

156
    /**
157
     * Checks if this method description represents a method, i.e. not a constructor or a type initializer.
158
     *
159
     * @return {@code true} if this method description represents a Java method.
160
     */
161
    boolean isMethod();
162

163
    /**
164
     * Checks if this method is a type initializer.
165
     *
166
     * @return {@code true} if this method description represents a type initializer.
167
     */
168
    boolean isTypeInitializer();
169

170
    /**
171
     * Verifies if a method description represents a given loaded method.
172
     *
173
     * @param method The method to be checked.
174
     * @return {@code true} if this method description represents the given loaded method.
175
     */
176
    boolean represents(Method method);
177

178
    /**
179
     * Verifies if a method description represents a given loaded constructor.
180
     *
181
     * @param constructor The constructor to be checked.
182
     * @return {@code true} if this method description represents the given loaded constructor.
183
     */
184
    boolean represents(Constructor<?> constructor);
185

186
    /**
187
     * Verifies if this method describes a virtual method, i.e. a method that is inherited by a sub type of this type.
188
     *
189
     * @return {@code true} if this method is virtual.
190
     */
191
    boolean isVirtual();
192

193
    /**
194
     * Returns the size of the local variable array that is required for this method, i.e. the size of all parameters
195
     * if they were loaded on the stack including a reference to {@code this} if this method represented a non-static
196
     * method.
197
     *
198
     * @return The size of this method on the operand stack.
199
     */
200
    int getStackSize();
201

202
    /**
203
     * Checks if this method represents a default (defender) method.
204
     *
205
     * @return {@code true} if this method is a default method.
206
     */
207
    boolean isDefaultMethod();
208

209
    /**
210
     * Checks if this method can be called using the {@code INVOKESPECIAL} for a given type.
211
     *
212
     * @param typeDescription The type o
213
     * @return {@code true} if this method can be called using the {@code INVOKESPECIAL} instruction
214
     * using the given type.
215
     */
216
    boolean isSpecializableFor(TypeDescription typeDescription);
217

218
    /**
219
     * Returns the method's default annotation value or {@code null} if no default value is defined for this method.
220
     *
221
     * @return The method's default annotation value or {@code null} if no default value is defined for this method.
222
     */
223
    @MaybeNull
224
    AnnotationValue<?, ?> getDefaultValue();
225

226
    /**
227
     * Returns the default value but casts it to the given type. If the type differs from the value, a
228
     * {@link java.lang.ClassCastException} is thrown.
229
     *
230
     * @param type The type to cast the default value to.
231
     * @param <T>  The type to cast the default value to.
232
     * @return The casted default value.
233
     */
234
    @MaybeNull
235
    <T> T getDefaultValue(Class<T> type);
236

237
    /**
238
     * Asserts if this method is invokable on an instance of the given type, i.e. the method is an instance method or
239
     * a constructor and the method is visible to the type and can be invoked on the given instance.
240
     *
241
     * @param typeDescription The type to check.
242
     * @return {@code true} if this method is invokable on an instance of the given type.
243
     */
244
    boolean isInvokableOn(TypeDescription typeDescription);
245

246
    /**
247
     * Checks if this method is a valid bootstrap method for an invokedynamic call.
248
     *
249
     * @return {@code true} if this method is a valid bootstrap method for an invokedynamic call.
250
     */
251
    boolean isInvokeBootstrap();
252

253
    /**
254
     * Checks if this method is a valid bootstrap method for an invokedynamic call.
255
     *
256
     * @param arguments The types of the explicit arguments that are supplied to the bootstrap method.
257
     * @return {@code true} if this method is a valid bootstrap method for an <i>invokedynamic</i> call.
258
     */
259
    boolean isInvokeBootstrap(List<? extends TypeDefinition> arguments);
260

261
    /**
262
     * Checks if this method is a valid bootstrap method for an constantdynamic call.
263
     *
264
     * @return {@code true} if this method is a valid bootstrap method for an constantdynamic call.
265
     */
266
    boolean isConstantBootstrap();
267

268
    /**
269
     * Checks if this method is a valid bootstrap method for a constantdynamic call.
270
     *
271
     * @param arguments The types of the explicit arguments that are supplied to the bootstrap method.
272
     * @return {@code true} if this method is a valid bootstrap method for an <i>constantdynamic</i> call.
273
     */
274
    boolean isConstantBootstrap(List<? extends TypeDefinition> arguments);
275

276
    /**
277
     * Checks if this method is capable of defining a default annotation value.
278
     *
279
     * @return {@code true} if it is possible to define a default annotation value for this method.
280
     */
281
    boolean isDefaultValue();
282

283
    /**
284
     * Checks if the given value can describe a default annotation value for this method.
285
     *
286
     * @param annotationValue The value that describes the default annotation value for this method.
287
     * @return {@code true} if the given value can describe a default annotation value for this method.
288
     */
289
    boolean isDefaultValue(AnnotationValue<?, ?> annotationValue);
290

291
    /**
292
     * Returns this methods receiver type. A receiver type is undefined for {@code static} methods
293
     * where {@code null} is returned. Other than a receiver type that is provided by the Java reflection
294
     * API, Byte Buddy is capable of extracting annotations on type parameters of receiver types when
295
     * directly accessing a class file. Therefore, a receiver type might be parameterized.
296
     *
297
     * @return This method's (annotated) receiver type.
298
     */
299
    @MaybeNull
300
    TypeDescription.Generic getReceiverType();
301

302
    /**
303
     * Returns a signature token representing this method.
304
     *
305
     * @return A signature token representing this method.
306
     */
307
    SignatureToken asSignatureToken();
308

309
    /**
310
     * Returns a type token that represents this method's raw return and parameter types.
311
     *
312
     * @return A type token that represents this method's raw return and parameter types.
313
     */
314
    TypeToken asTypeToken();
315

316
    /**
317
     * Validates that the supplied type token can implement a bridge method to this method.
318
     *
319
     * @param typeToken A type token representing a potential bridge method to this method.
320
     * @return {@code true} if the supplied type token can represent a bridge method to this method.
321
     */
322
    boolean isBridgeCompatible(TypeToken typeToken);
323

324
    /**
325
     * Represents a method description in its generic shape, i.e. in the shape it is defined by a generic or raw type.
326
     */
327
    interface InGenericShape extends MethodDescription {
328

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

335
        /**
336
         * {@inheritDoc}
337
         */
338
        ParameterList<ParameterDescription.InGenericShape> getParameters();
339
    }
340

341
    /**
342
     * Represents a method in its defined shape, i.e. in the form it is defined by a class without its type variables being resolved.
343
     */
344
    interface InDefinedShape extends MethodDescription {
345

346
        /**
347
         * {@inheritDoc}
348
         */
349
        @Nonnull
350
        TypeDescription getDeclaringType();
351

352
        /**
353
         * {@inheritDoc}
354
         */
355
        ParameterList<ParameterDescription.InDefinedShape> getParameters();
356

357
        /**
358
         * An abstract base implementation of a method description in its defined shape.
359
         */
360
        abstract class AbstractBase extends MethodDescription.AbstractBase implements InDefinedShape {
1✔
361

362
            /**
363
             * {@inheritDoc}
364
             */
365
            public InDefinedShape asDefined() {
366
                return this;
1✔
367
            }
368

369
            /**
370
             * {@inheritDoc}
371
             */
372
            @MaybeNull
373
            public TypeDescription.Generic getReceiverType() {
374
                if (isStatic()) {
1✔
375
                    return TypeDescription.Generic.UNDEFINED;
1✔
376
                } else if (isConstructor()) {
1✔
377
                    TypeDescription declaringType = getDeclaringType(), enclosingDeclaringType = getDeclaringType().getEnclosingType();
1✔
378
                    if (enclosingDeclaringType == null) {
1✔
379
                        return TypeDescription.Generic.OfParameterizedType.ForGenerifiedErasure.of(declaringType);
1✔
380
                    } else {
381
                        return declaringType.isStatic()
1✔
382
                                ? enclosingDeclaringType.asGenericType()
1✔
383
                                : TypeDescription.Generic.OfParameterizedType.ForGenerifiedErasure.of(enclosingDeclaringType);
×
384
                    }
385
                } else {
386
                    return TypeDescription.Generic.OfParameterizedType.ForGenerifiedErasure.of(getDeclaringType());
1✔
387
                }
388
            }
389

390
            /**
391
             * A base implementation for a loaded instance representation for a {@code java.lang.reflect.Executable}.
392
             *
393
             * @param <T> The type of the executable.
394
             */
395
            protected abstract static class ForLoadedExecutable<T extends AnnotatedElement> extends InDefinedShape.AbstractBase {
396

397
                /**
398
                 * A dispatcher for interacting with {@code java.lang.reflect.Executable}.
399
                 */
400
                protected static final Executable EXECUTABLE = doPrivileged(JavaDispatcher.of(Executable.class));
1✔
401

402
                /**
403
                 * The represented {@code java.lang.reflect.Executable}.
404
                 */
405
                protected final T executable;
406

407
                /**
408
                 * Creates a new method description for a loaded executable.
409
                 *
410
                 * @param executable The represented {@code java.lang.reflect.Executable}.
411
                 */
412
                protected ForLoadedExecutable(T executable) {
1✔
413
                    this.executable = executable;
1✔
414
                }
1✔
415

416
                /**
417
                 * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
418
                 *
419
                 * @param action The action to execute from a privileged context.
420
                 * @param <T>    The type of the action's resolved value.
421
                 * @return The action's resolved value.
422
                 */
423
                @AccessControllerPlugin.Enhance
424
                private static <T> T doPrivileged(PrivilegedAction<T> action) {
425
                    return action.run();
×
426
                }
427

428
                /**
429
                 * {@inheritDoc}
430
                 */
431
                public TypeDescription.Generic getReceiverType() {
432
                    AnnotatedElement element = EXECUTABLE.getAnnotatedReceiverType(executable);
1✔
433
                    return element == null
1✔
434
                            ? super.getReceiverType()
1✔
435
                            : TypeDefinition.Sort.describeAnnotated(element);
1✔
436
                }
437
            }
438

439
            /**
440
             * A proxy type for invoking methods of {@code java.lang.reflect.Executable}.
441
             */
442
            @JavaDispatcher.Proxied("java.lang.reflect.Executable")
443
            protected interface Executable {
444

445
                /**
446
                 * Returns the annotated receiver type.
447
                 *
448
                 * @param value The {@code java.lang.reflect.Executable} to resolve.
449
                 * @return An instance of {@code java.lang.reflect.AnnotatedType} that represents the receiver of the supplied executable.
450
                 */
451
                @MaybeNull
452
                @JavaDispatcher.Defaults
453
                AnnotatedElement getAnnotatedReceiverType(Object value);
454
            }
455
        }
456
    }
457

458
    /**
459
     * An abstract base implementation of a method description.
460
     */
461
    abstract class AbstractBase extends TypeVariableSource.AbstractBase implements MethodDescription {
1✔
462

463
        /**
464
         * A merger of all method modifiers that are visible in the Java source code.
465
         */
466
        private static final int SOURCE_MODIFIERS = Modifier.PUBLIC
467
                | Modifier.PROTECTED
468
                | Modifier.PRIVATE
469
                | Modifier.ABSTRACT
470
                | Modifier.STATIC
471
                | Modifier.FINAL
472
                | Modifier.SYNCHRONIZED
473
                | Modifier.NATIVE;
474

475
        /**
476
         * {@inheritDoc}
477
         */
478
        public int getStackSize() {
479
            return getParameters().asTypeList().getStackSize() + (isStatic() ? 0 : 1);
1✔
480
        }
481

482
        /**
483
         * {@inheritDoc}
484
         */
485
        public boolean isMethod() {
486
            return !isConstructor() && !isTypeInitializer();
1✔
487
        }
488

489
        /**
490
         * {@inheritDoc}
491
         */
492
        public boolean isConstructor() {
493
            return CONSTRUCTOR_INTERNAL_NAME.equals(getInternalName());
1✔
494
        }
495

496
        /**
497
         * {@inheritDoc}
498
         */
499
        public boolean isTypeInitializer() {
500
            return TYPE_INITIALIZER_INTERNAL_NAME.equals(getInternalName());
1✔
501
        }
502

503
        /**
504
         * {@inheritDoc}
505
         */
506
        public boolean represents(Method method) {
507
            return equals(new ForLoadedMethod(method));
1✔
508
        }
509

510
        /**
511
         * {@inheritDoc}
512
         */
513
        public boolean represents(Constructor<?> constructor) {
514
            return equals(new ForLoadedConstructor(constructor));
1✔
515
        }
516

517
        /**
518
         * {@inheritDoc}
519
         */
520
        public String getName() {
521
            return isMethod()
1✔
522
                    ? getInternalName()
1✔
523
                    : getDeclaringType().asErasure().getName();
1✔
524
        }
525

526
        /**
527
         * {@inheritDoc}
528
         */
529
        public String getActualName() {
530
            return isMethod()
1✔
531
                    ? getName()
1✔
532
                    : EMPTY_NAME;
533
        }
534

535
        /**
536
         * {@inheritDoc}
537
         */
538
        public String getDescriptor() {
539
            StringBuilder descriptor = new StringBuilder().append('(');
1✔
540
            for (TypeDescription parameterType : getParameters().asTypeList().asErasures()) {
1✔
541
                descriptor.append(parameterType.getDescriptor());
1✔
542
            }
1✔
543
            return descriptor.append(')').append(getReturnType().asErasure().getDescriptor()).toString();
1✔
544
        }
545

546
        /**
547
         * {@inheritDoc}
548
         */
549
        @MaybeNull
550
        public String getGenericSignature() {
551
            try {
552
                SignatureWriter signatureWriter = new SignatureWriter();
1✔
553
                boolean generic = false;
1✔
554
                for (TypeDescription.Generic typeVariable : getTypeVariables()) {
1✔
555
                    signatureWriter.visitFormalTypeParameter(typeVariable.getSymbol());
1✔
556
                    boolean classBound = true;
1✔
557
                    for (TypeDescription.Generic upperBound : typeVariable.getUpperBounds()) {
1✔
558
                        upperBound.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(classBound
1✔
559
                                ? signatureWriter.visitClassBound()
1✔
560
                                : signatureWriter.visitInterfaceBound()));
1✔
561
                        classBound = false;
1✔
562
                    }
1✔
563
                    generic = true;
1✔
564
                }
1✔
565
                for (TypeDescription.Generic parameterType : getParameters().asTypeList()) {
1✔
566
                    parameterType.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(signatureWriter.visitParameterType()));
1✔
567
                    generic = generic || !parameterType.getSort().isNonGeneric();
1✔
568
                }
1✔
569
                TypeDescription.Generic returnType = getReturnType();
1✔
570
                returnType.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(signatureWriter.visitReturnType()));
1✔
571
                generic = generic || !returnType.getSort().isNonGeneric();
1✔
572
                TypeList.Generic exceptionTypes = getExceptionTypes();
1✔
573
                if (!exceptionTypes.filter(not(ofSort(TypeDefinition.Sort.NON_GENERIC))).isEmpty()) {
1✔
574
                    for (TypeDescription.Generic exceptionType : exceptionTypes) {
1✔
575
                        exceptionType.accept(new TypeDescription.Generic.Visitor.ForSignatureVisitor(signatureWriter.visitExceptionType()));
1✔
576
                        generic = generic || !exceptionType.getSort().isNonGeneric();
1✔
577
                    }
1✔
578
                }
579
                return generic
1✔
580
                        ? signatureWriter.toString()
1✔
581
                        : NON_GENERIC_SIGNATURE;
582
            } catch (GenericSignatureFormatError ignored) {
×
583
                return NON_GENERIC_SIGNATURE;
×
584
            }
585
        }
586

587
        /**
588
         * {@inheritDoc}
589
         */
590
        public int getActualModifiers() {
591
            return getModifiers() | (getDeclaredAnnotations().isAnnotationPresent(Deprecated.class)
1✔
592
                    ? Opcodes.ACC_DEPRECATED
593
                    : EMPTY_MASK);
594
        }
595

596
        /**
597
         * {@inheritDoc}
598
         */
599
        public int getActualModifiers(boolean manifest) {
600
            int modifiers = getActualModifiers();
1✔
601
            if (manifest) {
1✔
602
                return modifiers & ~(Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE);
1✔
603
            } else if ((modifiers & (Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT)) == 0) {
1✔
604
                return modifiers | Opcodes.ACC_ABSTRACT;
1✔
605
            } else {
606
                return modifiers;
1✔
607
            }
608
        }
609

610
        /**
611
         * {@inheritDoc}
612
         */
613
        public int getActualModifiers(boolean manifest, Visibility visibility) {
614
            return ModifierContributor.Resolver.of(Collections.singleton(getVisibility().expandTo(visibility))).resolve(getActualModifiers(manifest));
1✔
615
        }
616

617
        /**
618
         * {@inheritDoc}
619
         */
620
        public boolean isVisibleTo(TypeDescription typeDescription) {
621
            return getDeclaringType().asErasure().equals(typeDescription)
1✔
622
                    || isPublic() && getDeclaringType().isPublic()
1✔
623
                    || (isPublic() || isProtected()) && getDeclaringType().asErasure().isAssignableFrom(typeDescription)
1✔
624
                    || !isPrivate() && getDeclaringType().asErasure().isSamePackage(typeDescription)
1✔
625
                    || isPrivate() && getDeclaringType().asErasure().isNestMateOf(typeDescription);
1✔
626
        }
627

628
        /**
629
         * {@inheritDoc}
630
         */
631
        public boolean isAccessibleTo(TypeDescription typeDescription) {
632
            return getDeclaringType().asErasure().equals(typeDescription)
1✔
633
                    || isPublic() && getDeclaringType().isPublic()
1✔
634
                    || !isPrivate() && getDeclaringType().asErasure().isSamePackage(typeDescription)
1✔
635
                    || isPrivate() && getDeclaringType().asErasure().isNestMateOf(typeDescription);
1✔
636
        }
637

638
        /**
639
         * {@inheritDoc}
640
         */
641
        public boolean isVirtual() {
642
            return !(isConstructor() || isPrivate() || isStatic() || isTypeInitializer());
1✔
643
        }
644

645
        /**
646
         * {@inheritDoc}
647
         */
648
        public boolean isDefaultMethod() {
649
            return !isAbstract() && !isBridge() && getDeclaringType().isInterface();
1✔
650
        }
651

652
        /**
653
         * {@inheritDoc}
654
         */
655
        public boolean isSpecializableFor(TypeDescription targetType) {
656
            if (isStatic()) { // Static private methods are never specializable, check static property first
1✔
657
                return false;
1✔
658
            } else if (isPrivate() || isConstructor()) {
1✔
659
                return getDeclaringType().equals(targetType);
1✔
660
            } else {
661
                return !isAbstract() && getDeclaringType().asErasure().isAssignableFrom(targetType);
1✔
662
            }
663
        }
664

665
        /**
666
         * {@inheritDoc}
667
         */
668
        @MaybeNull
669
        public <T> T getDefaultValue(Class<T> type) {
670
            return type.cast(getDefaultValue());
×
671
        }
672

673
        /**
674
         * {@inheritDoc}
675
         */
676
        public boolean isInvokableOn(TypeDescription typeDescription) {
677
            return !isStatic()
1✔
678
                    && !isTypeInitializer()
1✔
679
                    && isVisibleTo(typeDescription)
1✔
680
                    && (isVirtual()
1✔
681
                    ? getDeclaringType().asErasure().isAssignableFrom(typeDescription)
1✔
682
                    : getDeclaringType().asErasure().equals(typeDescription));
1✔
683
        }
684

685
        /**
686
         * Checks if this method is a bootstrap method while expecting the supplied type as a type representation.
687
         *
688
         * @param bootstrapped The type of the bootstrap method's type representation.
689
         * @return {@code true} if this method is a bootstrap method assuming the supplied type representation.
690
         */
691
        @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming component type for array type.")
692
        private boolean isBootstrap(TypeDescription bootstrapped) {
693
            TypeList parameterTypes = getParameters().asTypeList().asErasures();
1✔
694
            switch (parameterTypes.size()) {
1✔
695
                case 0:
696
                    return false;
1✔
697
                case 1:
698
                    return parameterTypes.getOnly().represents(Object[].class);
1✔
699
                case 2:
700
                    return JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().isAssignableTo(parameterTypes.get(0))
1✔
701
                            && parameterTypes.get(1).represents(Object[].class);
1✔
702
                case 3:
703
                    return JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().isAssignableTo(parameterTypes.get(0))
1✔
704
                            && (parameterTypes.get(1).represents(Object.class) || parameterTypes.get(1).represents(String.class))
1✔
705
                            && (parameterTypes.get(2).isArray() && parameterTypes.get(2).getComponentType().isAssignableFrom(bootstrapped) || parameterTypes.get(2).isAssignableFrom(bootstrapped));
1✔
706
                default:
707
                    return JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().isAssignableTo(parameterTypes.get(0))
1✔
708
                            && (parameterTypes.get(1).represents(Object.class) || parameterTypes.get(1).represents(String.class))
1✔
709
                            && parameterTypes.get(2).isAssignableFrom(bootstrapped);
1✔
710
            }
711
        }
712

713
        /**
714
         * Checks if this method is a bootstrap method given the supplied arguments. This method does not implement a full check but assumes that
715
         * {@link MethodDescription.AbstractBase#isBootstrap(TypeDescription)} is invoked, as well.
716
         *
717
         * @param arguments The types of the explicit arguments that are supplied to the bootstrap method.
718
         * @return {@code true} if this method is a bootstrap method for the supplied arguments.
719
         */
720
        @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming component type for array type.")
721
        private boolean isBootstrapping(List<? extends TypeDefinition> arguments) {
722
            TypeList targets = getParameters().asTypeList().asErasures();
1✔
723
            if (targets.size() < 4) {
1✔
724
                if (arguments.isEmpty()) {
1✔
725
                    return true;
1✔
726
                } else if (targets.get(targets.size() - 1).isArray()) {
×
727
                    for (TypeDefinition argument : arguments) {
×
728
                        if (!argument.asErasure().isAssignableTo(targets.get(targets.size() - 1).getComponentType())) {
×
729
                            return false;
×
730
                        }
731
                    }
×
732
                    return true;
×
733
                } else {
734
                    return false;
×
735
                }
736
            } else {
737
                Iterator<TypeDescription> iterator = targets.subList(3, targets.size()).iterator();
1✔
738
                for (TypeDefinition type : arguments) {
1✔
739
                    if (!iterator.hasNext()) {
1✔
740
                        return false;
×
741
                    }
742
                    TypeDescription target = iterator.next();
1✔
743
                    if (!iterator.hasNext() && target.isArray()) {
1✔
744
                        return true;
×
745
                    } else if (!type.asErasure().isAssignableTo(target)) {
1✔
746
                        return false;
×
747
                    }
748
                }
1✔
749
                if (iterator.hasNext()) {
1✔
750
                    return iterator.next().isArray() && !iterator.hasNext();
1✔
751
                } else {
752
                    return true;
1✔
753
                }
754
            }
755
        }
756

757
        /**
758
         * {@inheritDoc}
759
         */
760
        public boolean isInvokeBootstrap() {
761
            TypeDescription returnType = getReturnType().asErasure();
1✔
762
            if ((isMethod() && (!isStatic()
1✔
763
                    || !(JavaType.CALL_SITE.getTypeStub().isAssignableFrom(returnType) || JavaType.CALL_SITE.getTypeStub().isAssignableTo(returnType))))
1✔
764
                    || (isConstructor() && !JavaType.CALL_SITE.getTypeStub().isAssignableFrom(getDeclaringType().asErasure()))) {
1✔
765
                return false;
×
766
            }
767
            return isBootstrap(JavaType.METHOD_TYPE.getTypeStub());
1✔
768
        }
769

770
        /**
771
         * {@inheritDoc}
772
         */
773
        public boolean isInvokeBootstrap(List<? extends TypeDefinition> arguments) {
774
            return isInvokeBootstrap() && isBootstrapping(arguments);
1✔
775
        }
776

777
        /**
778
         * {@inheritDoc}
779
         */
780
        public boolean isConstantBootstrap() {
781
            return isBootstrap(TypeDescription.ForLoadedType.of(Class.class));
1✔
782
        }
783

784
        /**
785
         * {@inheritDoc}
786
         */
787
        public boolean isConstantBootstrap(List<? extends TypeDefinition> arguments) {
788
            return isConstantBootstrap() && isBootstrapping(arguments);
1✔
789
        }
790

791
        /**
792
         * {@inheritDoc}
793
         */
794
        public boolean isDefaultValue() {
795
            return !isConstructor()
1✔
796
                    && !isStatic()
1✔
797
                    && getReturnType().asErasure().isAnnotationReturnType()
1✔
798
                    && getParameters().isEmpty();
1✔
799
        }
800

801
        /**
802
         * {@inheritDoc}
803
         */
804
        @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming component type for array type.")
805
        public boolean isDefaultValue(AnnotationValue<?, ?> annotationValue) {
806
            if (!isDefaultValue()) {
1✔
807
                return false;
1✔
808
            }
809
            TypeDescription returnType = getReturnType().asErasure();
1✔
810
            Object value = annotationValue.resolve();
1✔
811
            return (returnType.represents(boolean.class) && value instanceof Boolean)
1✔
812
                    || (returnType.represents(byte.class) && value instanceof Byte)
1✔
813
                    || (returnType.represents(char.class) && value instanceof Character)
1✔
814
                    || (returnType.represents(short.class) && value instanceof Short)
1✔
815
                    || (returnType.represents(int.class) && value instanceof Integer)
1✔
816
                    || (returnType.represents(long.class) && value instanceof Long)
1✔
817
                    || (returnType.represents(float.class) && value instanceof Float)
1✔
818
                    || (returnType.represents(double.class) && value instanceof Double)
1✔
819
                    || (returnType.represents(String.class) && value instanceof String)
1✔
820
                    || (returnType.isAssignableTo(Enum.class) && value instanceof EnumerationDescription && isEnumerationType(returnType, (EnumerationDescription) value))
1✔
821
                    || (returnType.isAssignableTo(Annotation.class) && value instanceof AnnotationDescription && isAnnotationType(returnType, (AnnotationDescription) value))
1✔
822
                    || (returnType.represents(Class.class) && value instanceof TypeDescription)
1✔
823
                    || (returnType.represents(boolean[].class) && value instanceof boolean[])
1✔
824
                    || (returnType.represents(byte[].class) && value instanceof byte[])
1✔
825
                    || (returnType.represents(char[].class) && value instanceof char[])
1✔
826
                    || (returnType.represents(short[].class) && value instanceof short[])
1✔
827
                    || (returnType.represents(int[].class) && value instanceof int[])
1✔
828
                    || (returnType.represents(long[].class) && value instanceof long[])
1✔
829
                    || (returnType.represents(float[].class) && value instanceof float[])
1✔
830
                    || (returnType.represents(double[].class) && value instanceof double[])
1✔
831
                    || (returnType.represents(String[].class) && value instanceof String[])
1✔
832
                    || (returnType.isAssignableTo(Enum[].class) && value instanceof EnumerationDescription[] && isEnumerationType(returnType.getComponentType(), (EnumerationDescription[]) value))
1✔
833
                    || (returnType.isAssignableTo(Annotation[].class) && value instanceof AnnotationDescription[] && isAnnotationType(returnType.getComponentType(), (AnnotationDescription[]) value))
1✔
834
                    || (returnType.represents(Class[].class) && value instanceof TypeDescription[]);
1✔
835
        }
836

837
        /**
838
         * Checks if the supplied enumeration descriptions describe the correct enumeration type.
839
         *
840
         * @param enumerationType        The enumeration type to check for.
841
         * @param enumerationDescription The enumeration descriptions to check.
842
         * @return {@code true} if all enumeration descriptions represent the enumeration type in question.
843
         */
844
        private static boolean isEnumerationType(TypeDescription enumerationType, EnumerationDescription... enumerationDescription) {
845
            for (EnumerationDescription anEnumerationDescription : enumerationDescription) {
1✔
846
                if (!anEnumerationDescription.getEnumerationType().equals(enumerationType)) {
1✔
847
                    return false;
1✔
848
                }
849
            }
850
            return true;
1✔
851
        }
852

853
        /**
854
         * Checks if the supplied enumeration descriptions describe the correct annotation type.
855
         *
856
         * @param annotationType        The annotation type to check for.
857
         * @param annotationDescription The annotation descriptions to check.
858
         * @return {@code true} if all annotation descriptions represent the annotation type in question.
859
         */
860
        private static boolean isAnnotationType(TypeDescription annotationType, AnnotationDescription... annotationDescription) {
861
            for (AnnotationDescription anAnnotationDescription : annotationDescription) {
1✔
862
                if (!anAnnotationDescription.getAnnotationType().equals(annotationType)) {
1✔
863
                    return false;
1✔
864
                }
865
            }
866
            return true;
1✔
867
        }
868

869
        /**
870
         * {@inheritDoc}
871
         */
872
        @MaybeNull
873
        public TypeVariableSource getEnclosingSource() {
874
            return isStatic()
1✔
875
                    ? TypeVariableSource.UNDEFINED
876
                    : getDeclaringType().asErasure();
1✔
877
        }
878

879
        /**
880
         * {@inheritDoc}
881
         */
882
        public boolean isInferrable() {
883
            return true;
×
884
        }
885

886
        /**
887
         * {@inheritDoc}
888
         */
889
        public <T> T accept(TypeVariableSource.Visitor<T> visitor) {
890
            return visitor.onMethod(this.asDefined());
1✔
891
        }
892

893
        /**
894
         * {@inheritDoc}
895
         */
896
        public boolean isGenerified() {
897
            return !getTypeVariables().isEmpty();
1✔
898
        }
899

900
        /**
901
         * {@inheritDoc}
902
         */
903
        public MethodDescription.Token asToken(ElementMatcher<? super TypeDescription> matcher) {
904
            TypeDescription.Generic receiverType = getReceiverType();
1✔
905
            return new MethodDescription.Token(getInternalName(),
1✔
906
                    getModifiers(),
1✔
907
                    getTypeVariables().asTokenList(matcher),
1✔
908
                    getReturnType().accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)),
1✔
909
                    getParameters().asTokenList(matcher),
1✔
910
                    getExceptionTypes().accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)),
1✔
911
                    getDeclaredAnnotations(),
1✔
912
                    getDefaultValue(),
1✔
913
                    receiverType == null
914
                            ? TypeDescription.Generic.UNDEFINED
915
                            : receiverType.accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)));
1✔
916
        }
917

918
        /**
919
         * {@inheritDoc}
920
         */
921
        public SignatureToken asSignatureToken() {
922
            return new SignatureToken(getInternalName(), getReturnType().asErasure(), getParameters().asTypeList().asErasures());
1✔
923
        }
924

925
        /**
926
         * {@inheritDoc}
927
         */
928
        public TypeToken asTypeToken() {
929
            return new TypeToken(getReturnType().asErasure(), getParameters().asTypeList().asErasures());
1✔
930
        }
931

932
        /**
933
         * {@inheritDoc}
934
         */
935
        public boolean isBridgeCompatible(TypeToken typeToken) {
936
            List<TypeDescription> types = getParameters().asTypeList().asErasures(), bridgeTypes = typeToken.getParameterTypes();
1✔
937
            if (types.size() != bridgeTypes.size()) {
1✔
938
                return false;
1✔
939
            }
940
            for (int index = 0; index < types.size(); index++) {
1✔
941
                if (!types.get(index).equals(bridgeTypes.get(index)) && (types.get(index).isPrimitive() || bridgeTypes.get(index).isPrimitive())) {
1✔
942
                    return false;
1✔
943
                }
944
            }
945
            TypeDescription returnType = getReturnType().asErasure(), bridgeReturnType = typeToken.getReturnType();
1✔
946
            return returnType.equals(bridgeReturnType) || (!returnType.isPrimitive() && !bridgeReturnType.isPrimitive());
1✔
947
        }
948

949
        @Override
950
        @CachedReturnPlugin.Enhance("hashCode")
951
        public int hashCode() {
952
            int hashCode = 17 + getDeclaringType().hashCode();
1✔
953
            hashCode = 31 * hashCode + getInternalName().hashCode();
1✔
954
            hashCode = 31 * hashCode + getReturnType().asErasure().hashCode();
1✔
955
            return 31 * hashCode + getParameters().asTypeList().asErasures().hashCode();
1✔
956
        }
957

958
        @Override
959
        public boolean equals(@MaybeNull Object other) {
960
            if (this == other) {
1✔
961
                return true;
1✔
962
            } else if (!(other instanceof MethodDescription)) {
1✔
963
                return false;
1✔
964
            }
965
            MethodDescription methodDescription = (MethodDescription) other;
1✔
966
            return getInternalName().equals(methodDescription.getInternalName())
1✔
967
                    && getDeclaringType().equals(methodDescription.getDeclaringType())
1✔
968
                    && getReturnType().asErasure().equals(methodDescription.getReturnType().asErasure())
1✔
969
                    && getParameters().asTypeList().asErasures().equals(methodDescription.getParameters().asTypeList().asErasures());
1✔
970
        }
971

972
        /**
973
         * {@inheritDoc}
974
         */
975
        public String toGenericString() {
976
            StringBuilder stringBuilder = new StringBuilder();
1✔
977
            int modifiers = getModifiers() & SOURCE_MODIFIERS;
1✔
978
            if (modifiers != EMPTY_MASK) {
1✔
979
                stringBuilder.append(Modifier.toString(modifiers)).append(' ');
×
980
            }
981
            if (isMethod()) {
1✔
982
                stringBuilder.append(getReturnType().getActualName()).append(' ');
1✔
983
                stringBuilder.append(getDeclaringType().asErasure().getActualName()).append('.');
1✔
984
            }
985
            stringBuilder.append(getName()).append('(');
1✔
986
            boolean first = true;
1✔
987
            for (TypeDescription.Generic typeDescription : getParameters().asTypeList()) {
1✔
988
                if (!first) {
1✔
989
                    stringBuilder.append(',');
×
990
                } else {
991
                    first = false;
1✔
992
                }
993
                stringBuilder.append(typeDescription.getActualName());
1✔
994
            }
1✔
995
            stringBuilder.append(')');
1✔
996
            TypeList.Generic exceptionTypes = getExceptionTypes();
1✔
997
            if (!exceptionTypes.isEmpty()) {
1✔
998
                stringBuilder.append(" throws ");
1✔
999
                first = true;
1✔
1000
                for (TypeDescription.Generic typeDescription : exceptionTypes) {
1✔
1001
                    if (!first) {
1✔
1002
                        stringBuilder.append(',');
×
1003
                    } else {
1004
                        first = false;
1✔
1005
                    }
1006
                    stringBuilder.append(typeDescription.getActualName());
1✔
1007
                }
1✔
1008
            }
1009
            return stringBuilder.toString();
1✔
1010
        }
1011

1012
        @Override
1013
        public String toString() {
1014
            StringBuilder stringBuilder = new StringBuilder();
1✔
1015
            int modifiers = getModifiers() & SOURCE_MODIFIERS;
1✔
1016
            if (modifiers != EMPTY_MASK) {
1✔
1017
                stringBuilder.append(Modifier.toString(modifiers)).append(' ');
1✔
1018
            }
1019
            if (isMethod()) {
1✔
1020
                stringBuilder.append(getReturnType().asErasure().getActualName()).append(' ');
1✔
1021
                stringBuilder.append(getDeclaringType().asErasure().getActualName()).append('.');
1✔
1022
            }
1023
            stringBuilder.append(getName()).append('(');
1✔
1024
            boolean first = true;
1✔
1025
            for (TypeDescription typeDescription : getParameters().asTypeList().asErasures()) {
1✔
1026
                if (!first) {
1✔
1027
                    stringBuilder.append(',');
1✔
1028
                } else {
1029
                    first = false;
1✔
1030
                }
1031
                stringBuilder.append(typeDescription.getActualName());
1✔
1032
            }
1✔
1033
            stringBuilder.append(')');
1✔
1034
            TypeList exceptionTypes = getExceptionTypes().asErasures();
1✔
1035
            if (!exceptionTypes.isEmpty()) {
1✔
1036
                stringBuilder.append(" throws ");
1✔
1037
                first = true;
1✔
1038
                for (TypeDescription typeDescription : exceptionTypes) {
1✔
1039
                    if (!first) {
1✔
1040
                        stringBuilder.append(',');
1✔
1041
                    } else {
1042
                        first = false;
1✔
1043
                    }
1044
                    stringBuilder.append(typeDescription.getActualName());
1✔
1045
                }
1✔
1046
            }
1047
            return stringBuilder.toString();
1✔
1048
        }
1049

1050
        @Override
1051
        protected String toSafeString() {
1052
            StringBuilder stringBuilder = new StringBuilder();
×
1053
            int modifiers = getModifiers() & SOURCE_MODIFIERS;
×
1054
            if (modifiers != EMPTY_MASK) {
×
1055
                stringBuilder.append(Modifier.toString(modifiers)).append(' ');
×
1056
            }
1057
            if (isMethod()) {
×
1058
                stringBuilder.append('?').append(' ');
×
1059
                stringBuilder.append(getDeclaringType().asErasure().getActualName()).append('.');
×
1060
            }
1061
            return stringBuilder.append(getName()).append("(?)").toString();
×
1062
        }
1063
    }
1064

1065
    /**
1066
     * An implementation of a method description for a loaded constructor.
1067
     */
1068
    class ForLoadedConstructor extends InDefinedShape.AbstractBase.ForLoadedExecutable<Constructor<?>> implements ParameterDescription.ForLoadedParameter.ParameterAnnotationSource {
1069

1070
        /**
1071
         * Creates a new immutable method description for a loaded constructor.
1072
         *
1073
         * @param constructor The loaded constructor to be represented by this method description.
1074
         */
1075
        public ForLoadedConstructor(Constructor<?> constructor) {
1076
            super(constructor);
1✔
1077
        }
1✔
1078

1079
        /**
1080
         * {@inheritDoc}
1081
         */
1082
        @Nonnull
1083
        public TypeDescription getDeclaringType() {
1084
            return TypeDescription.ForLoadedType.of(executable.getDeclaringClass());
1✔
1085
        }
1086

1087
        /**
1088
         * {@inheritDoc}
1089
         */
1090
        public TypeDescription.Generic getReturnType() {
1091
            return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(void.class);
1✔
1092
        }
1093

1094
        /**
1095
         * {@inheritDoc}
1096
         */
1097
        @CachedReturnPlugin.Enhance("parameters")
1098
        public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1099
            return ParameterList.ForLoadedExecutable.of(executable, this);
1✔
1100
        }
1101

1102
        /**
1103
         * {@inheritDoc}
1104
         */
1105
        public TypeList.Generic getExceptionTypes() {
1106
            return new TypeList.Generic.OfConstructorExceptionTypes(executable);
1✔
1107
        }
1108

1109
        /**
1110
         * {@inheritDoc}
1111
         */
1112
        public boolean isConstructor() {
1113
            return true;
1✔
1114
        }
1115

1116
        /**
1117
         * {@inheritDoc}
1118
         */
1119
        public boolean isTypeInitializer() {
1120
            return false;
1✔
1121
        }
1122

1123
        /**
1124
         * {@inheritDoc}
1125
         */
1126
        public boolean represents(Method method) {
1127
            return false;
1✔
1128
        }
1129

1130
        /**
1131
         * {@inheritDoc}
1132
         */
1133
        public boolean represents(Constructor<?> constructor) {
1134
            return executable.equals(constructor) || equals(new MethodDescription.ForLoadedConstructor(constructor));
1✔
1135
        }
1136

1137
        /**
1138
         * {@inheritDoc}
1139
         */
1140
        public String getName() {
1141
            return executable.getName();
1✔
1142
        }
1143

1144
        /**
1145
         * {@inheritDoc}
1146
         */
1147
        public int getModifiers() {
1148
            return executable.getModifiers();
1✔
1149
        }
1150

1151
        /**
1152
         * {@inheritDoc}
1153
         */
1154
        public boolean isSynthetic() {
1155
            return executable.isSynthetic();
1✔
1156
        }
1157

1158
        /**
1159
         * {@inheritDoc}
1160
         */
1161
        public String getInternalName() {
1162
            return CONSTRUCTOR_INTERNAL_NAME;
1✔
1163
        }
1164

1165
        /**
1166
         * {@inheritDoc}
1167
         */
1168
        public String getDescriptor() {
1169
            return Type.getConstructorDescriptor(executable);
1✔
1170
        }
1171

1172
        /**
1173
         * {@inheritDoc}
1174
         */
1175
        @AlwaysNull
1176
        public AnnotationValue<?, ?> getDefaultValue() {
1177
            return AnnotationValue.UNDEFINED;
1✔
1178
        }
1179

1180
        /**
1181
         * {@inheritDoc}
1182
         */
1183
        @CachedReturnPlugin.Enhance("declaredAnnotations")
1184
        public AnnotationList getDeclaredAnnotations() {
1185
            return new AnnotationList.ForLoadedAnnotations(executable.getDeclaredAnnotations());
1✔
1186
        }
1187

1188
        /**
1189
         * {@inheritDoc}
1190
         */
1191
        public TypeList.Generic getTypeVariables() {
1192
            return TypeList.Generic.ForLoadedTypes.OfTypeVariables.of(executable);
1✔
1193
        }
1194

1195
        /**
1196
         * {@inheritDoc}
1197
         */
1198
        @CachedReturnPlugin.Enhance("parameterAnnotations")
1199
        public Annotation[][] getParameterAnnotations() {
1200
            return executable.getParameterAnnotations();
1✔
1201
        }
1202
    }
1203

1204
    /**
1205
     * An implementation of a method description for a loaded method.
1206
     */
1207
    class ForLoadedMethod extends InDefinedShape.AbstractBase.ForLoadedExecutable<Method> implements ParameterDescription.ForLoadedParameter.ParameterAnnotationSource {
1208

1209
        /**
1210
         * Creates a new immutable method description for a loaded method.
1211
         *
1212
         * @param method The loaded method to be represented by this method description.
1213
         */
1214
        public ForLoadedMethod(Method method) {
1215
            super(method);
1✔
1216
        }
1✔
1217

1218
        /**
1219
         * {@inheritDoc}
1220
         */
1221
        @Nonnull
1222
        public TypeDescription getDeclaringType() {
1223
            return TypeDescription.ForLoadedType.of(executable.getDeclaringClass());
1✔
1224
        }
1225

1226
        /**
1227
         * {@inheritDoc}
1228
         */
1229
        public TypeDescription.Generic getReturnType() {
1230
            if (TypeDescription.AbstractBase.RAW_TYPES) {
1✔
1231
                return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(executable.getReturnType());
×
1232
            }
1233
            return new TypeDescription.Generic.LazyProjection.ForLoadedReturnType(executable);
1✔
1234
        }
1235

1236
        /**
1237
         * {@inheritDoc}
1238
         */
1239
        @CachedReturnPlugin.Enhance("parameters")
1240
        public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1241
            return ParameterList.ForLoadedExecutable.of(executable, this);
1✔
1242
        }
1243

1244
        /**
1245
         * {@inheritDoc}
1246
         */
1247
        public TypeList.Generic getExceptionTypes() {
1248
            if (TypeDescription.AbstractBase.RAW_TYPES) {
1✔
1249
                return new TypeList.Generic.ForLoadedTypes(executable.getExceptionTypes());
×
1250
            }
1251
            return new TypeList.Generic.OfMethodExceptionTypes(executable);
1✔
1252
        }
1253

1254
        /**
1255
         * {@inheritDoc}
1256
         */
1257
        public boolean isConstructor() {
1258
            return false;
1✔
1259
        }
1260

1261
        /**
1262
         * {@inheritDoc}
1263
         */
1264
        public boolean isTypeInitializer() {
1265
            return false;
1✔
1266
        }
1267

1268
        /**
1269
         * {@inheritDoc}
1270
         */
1271
        public boolean isBridge() {
1272
            return executable.isBridge();
1✔
1273
        }
1274

1275
        /**
1276
         * {@inheritDoc}
1277
         */
1278
        public boolean represents(Method method) {
1279
            return executable.equals(method) || equals(new MethodDescription.ForLoadedMethod(method));
1✔
1280
        }
1281

1282
        /**
1283
         * {@inheritDoc}
1284
         */
1285
        public boolean represents(Constructor<?> constructor) {
1286
            return false;
1✔
1287
        }
1288

1289
        /**
1290
         * {@inheritDoc}
1291
         */
1292
        public String getName() {
1293
            return executable.getName();
1✔
1294
        }
1295

1296
        /**
1297
         * {@inheritDoc}
1298
         */
1299
        public int getModifiers() {
1300
            return executable.getModifiers();
1✔
1301
        }
1302

1303
        /**
1304
         * {@inheritDoc}
1305
         */
1306
        public boolean isSynthetic() {
1307
            return executable.isSynthetic();
1✔
1308
        }
1309

1310
        /**
1311
         * {@inheritDoc}
1312
         */
1313
        public String getInternalName() {
1314
            return executable.getName();
1✔
1315
        }
1316

1317
        /**
1318
         * {@inheritDoc}
1319
         */
1320
        public String getDescriptor() {
1321
            return Type.getMethodDescriptor(executable);
1✔
1322
        }
1323

1324
        /**
1325
         * Returns the loaded method that is represented by this method description.
1326
         *
1327
         * @return The loaded method that is represented by this method description.
1328
         */
1329
        public Method getLoadedMethod() {
1330
            return executable;
1✔
1331
        }
1332

1333
        /**
1334
         * {@inheritDoc}
1335
         */
1336
        @CachedReturnPlugin.Enhance("declaredAnnotations")
1337
        public AnnotationList getDeclaredAnnotations() {
1338
            return new AnnotationList.ForLoadedAnnotations(executable.getDeclaredAnnotations());
1✔
1339
        }
1340

1341
        /**
1342
         * {@inheritDoc}
1343
         */
1344
        @MaybeNull
1345
        public AnnotationValue<?, ?> getDefaultValue() {
1346
            Object value = executable.getDefaultValue();
1✔
1347
            return value == null
1✔
1348
                    ? AnnotationValue.UNDEFINED
1349
                    : AnnotationDescription.ForLoadedAnnotation.asValue(value, executable.getReturnType());
1✔
1350
        }
1351

1352
        /**
1353
         * {@inheritDoc}
1354
         */
1355
        public TypeList.Generic getTypeVariables() {
1356
            if (TypeDescription.AbstractBase.RAW_TYPES) {
1✔
1357
                return new TypeList.Generic.Empty();
×
1358
            }
1359
            return TypeList.Generic.ForLoadedTypes.OfTypeVariables.of(executable);
1✔
1360
        }
1361

1362
        /**
1363
         * {@inheritDoc}
1364
         */
1365
        @CachedReturnPlugin.Enhance("parameterAnnotations")
1366
        public Annotation[][] getParameterAnnotations() {
1367
            return executable.getParameterAnnotations();
1✔
1368
        }
1369
    }
1370

1371
    /**
1372
     * A latent method description describes a method that is not attached to a declaring
1373
     * {@link TypeDescription}.
1374
     */
1375
    class Latent extends InDefinedShape.AbstractBase {
1376

1377
        /**
1378
         * The type that is declaring this method.
1379
         */
1380
        private final TypeDescription declaringType;
1381

1382
        /**
1383
         * The internal name of this method.
1384
         */
1385
        private final String internalName;
1386

1387
        /**
1388
         * The modifiers of this method.
1389
         */
1390
        private final int modifiers;
1391

1392
        /**
1393
         * A tokenized list representing the method's type variables.
1394
         */
1395
        private final List<? extends TypeVariableToken> typeVariables;
1396

1397
        /**
1398
         * The return type of this method.
1399
         */
1400
        private final TypeDescription.Generic returnType;
1401

1402
        /**
1403
         * The parameter tokens describing this method.
1404
         */
1405
        private final List<? extends ParameterDescription.Token> parameterTokens;
1406

1407
        /**
1408
         * This method's exception types.
1409
         */
1410
        private final List<? extends TypeDescription.Generic> exceptionTypes;
1411

1412
        /**
1413
         * The annotations of this method.
1414
         */
1415
        private final List<? extends AnnotationDescription> declaredAnnotations;
1416

1417
        /**
1418
         * The default value of this method or {@code null} if no default annotation value is defined.
1419
         */
1420
        @MaybeNull
1421
        private final AnnotationValue<?, ?> defaultValue;
1422

1423
        /**
1424
         * The receiver type of this method or {@code null} if the receiver type is defined implicitly.
1425
         */
1426
        @MaybeNull
1427
        private final TypeDescription.Generic receiverType;
1428

1429
        /**
1430
         * Creates a new latent method description. All provided types are attached to this instance before they are returned.
1431
         *
1432
         * @param declaringType The declaring type of the method.
1433
         * @param token         A token representing the method's shape.
1434
         */
1435
        public Latent(TypeDescription declaringType, MethodDescription.Token token) {
1436
            this(declaringType,
1✔
1437
                    token.getName(),
1✔
1438
                    token.getModifiers(),
1✔
1439
                    token.getTypeVariableTokens(),
1✔
1440
                    token.getReturnType(),
1✔
1441
                    token.getParameterTokens(),
1✔
1442
                    token.getExceptionTypes(),
1✔
1443
                    token.getAnnotations(),
1✔
1444
                    token.getDefaultValue(),
1✔
1445
                    token.getReceiverType());
1✔
1446
        }
1✔
1447

1448
        /**
1449
         * Creates a new latent method description. All provided types are attached to this instance before they are returned.
1450
         *
1451
         * @param declaringType       The type that is declaring this method.
1452
         * @param internalName        The internal name of this method.
1453
         * @param modifiers           The modifiers of this method.
1454
         * @param typeVariables       The type variables of the described method.
1455
         * @param returnType          The return type of this method.
1456
         * @param parameterTokens     The parameter tokens describing this method.
1457
         * @param exceptionTypes      This method's exception types.
1458
         * @param declaredAnnotations The annotations of this method.
1459
         * @param defaultValue        The default value of this method or {@code null} if no default annotation value is defined.
1460
         * @param receiverType        The receiver type of this method or {@code null} if the receiver type is defined implicitly.
1461
         */
1462
        public Latent(TypeDescription declaringType,
1463
                      String internalName,
1464
                      int modifiers,
1465
                      List<? extends TypeVariableToken> typeVariables,
1466
                      TypeDescription.Generic returnType,
1467
                      List<? extends ParameterDescription.Token> parameterTokens,
1468
                      List<? extends TypeDescription.Generic> exceptionTypes,
1469
                      List<? extends AnnotationDescription> declaredAnnotations,
1470
                      @MaybeNull AnnotationValue<?, ?> defaultValue,
1471
                      @MaybeNull TypeDescription.Generic receiverType) {
1✔
1472
            this.declaringType = declaringType;
1✔
1473
            this.internalName = internalName;
1✔
1474
            this.modifiers = modifiers;
1✔
1475
            this.typeVariables = typeVariables;
1✔
1476
            this.returnType = returnType;
1✔
1477
            this.parameterTokens = parameterTokens;
1✔
1478
            this.exceptionTypes = exceptionTypes;
1✔
1479
            this.declaredAnnotations = declaredAnnotations;
1✔
1480
            this.defaultValue = defaultValue;
1✔
1481
            this.receiverType = receiverType;
1✔
1482
        }
1✔
1483

1484
        /**
1485
         * {@inheritDoc}
1486
         */
1487
        public TypeList.Generic getTypeVariables() {
1488
            return TypeList.Generic.ForDetachedTypes.attachVariables(this, typeVariables);
1✔
1489
        }
1490

1491
        /**
1492
         * {@inheritDoc}
1493
         */
1494
        public TypeDescription.Generic getReturnType() {
1495
            return returnType.accept(TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
1✔
1496
        }
1497

1498
        /**
1499
         * {@inheritDoc}
1500
         */
1501
        public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1502
            return new ParameterList.ForTokens(this, parameterTokens);
1✔
1503
        }
1504

1505
        /**
1506
         * {@inheritDoc}
1507
         */
1508
        public TypeList.Generic getExceptionTypes() {
1509
            return TypeList.Generic.ForDetachedTypes.attach(this, exceptionTypes);
1✔
1510
        }
1511

1512
        /**
1513
         * {@inheritDoc}
1514
         */
1515
        public AnnotationList getDeclaredAnnotations() {
1516
            return new AnnotationList.Explicit(declaredAnnotations);
1✔
1517
        }
1518

1519
        /**
1520
         * {@inheritDoc}
1521
         */
1522
        public String getInternalName() {
1523
            return internalName;
1✔
1524
        }
1525

1526
        /**
1527
         * {@inheritDoc}
1528
         */
1529
        @Nonnull
1530
        public TypeDescription getDeclaringType() {
1531
            return declaringType;
1✔
1532
        }
1533

1534
        /**
1535
         * {@inheritDoc}
1536
         */
1537
        public int getModifiers() {
1538
            return modifiers;
1✔
1539
        }
1540

1541
        /**
1542
         * {@inheritDoc}
1543
         */
1544
        @MaybeNull
1545
        public AnnotationValue<?, ?> getDefaultValue() {
1546
            return defaultValue;
1✔
1547
        }
1548

1549
        /**
1550
         * {@inheritDoc}
1551
         */
1552
        @MaybeNull
1553
        public TypeDescription.Generic getReceiverType() {
1554
            return receiverType == null
1✔
1555
                    ? super.getReceiverType()
1✔
1556
                    : receiverType.accept(TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
1✔
1557
        }
1558

1559
        /**
1560
         * A method description that represents the type initializer.
1561
         */
1562
        public static class TypeInitializer extends InDefinedShape.AbstractBase {
1563

1564
            /**
1565
             * The type for which the type initializer should be represented.
1566
             */
1567
            private final TypeDescription typeDescription;
1568

1569
            /**
1570
             * Creates a new method description representing the type initializer.
1571
             *
1572
             * @param typeDescription The type for which the type initializer should be represented.
1573
             */
1574
            public TypeInitializer(TypeDescription typeDescription) {
1✔
1575
                this.typeDescription = typeDescription;
1✔
1576
            }
1✔
1577

1578
            /**
1579
             * {@inheritDoc}
1580
             */
1581
            public TypeDescription.Generic getReturnType() {
1582
                return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(void.class);
1✔
1583
            }
1584

1585
            /**
1586
             * {@inheritDoc}
1587
             */
1588
            public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1589
                return new ParameterList.Empty<ParameterDescription.InDefinedShape>();
1✔
1590
            }
1591

1592
            /**
1593
             * {@inheritDoc}
1594
             */
1595
            public TypeList.Generic getExceptionTypes() {
1596
                return new TypeList.Generic.Empty();
1✔
1597
            }
1598

1599
            /**
1600
             * {@inheritDoc}
1601
             */
1602
            @AlwaysNull
1603
            public AnnotationValue<?, ?> getDefaultValue() {
1604
                return AnnotationValue.UNDEFINED;
×
1605
            }
1606

1607
            /**
1608
             * {@inheritDoc}
1609
             */
1610
            public TypeList.Generic getTypeVariables() {
1611
                return new TypeList.Generic.Empty();
1✔
1612
            }
1613

1614
            /**
1615
             * {@inheritDoc}
1616
             */
1617
            public AnnotationList getDeclaredAnnotations() {
1618
                return new AnnotationList.Empty();
1✔
1619
            }
1620

1621
            /**
1622
             * {@inheritDoc}
1623
             */
1624
            @Nonnull
1625
            public TypeDescription getDeclaringType() {
1626
                return typeDescription;
1✔
1627
            }
1628

1629
            /**
1630
             * {@inheritDoc}
1631
             */
1632
            public int getModifiers() {
1633
                return TYPE_INITIALIZER_MODIFIER;
1✔
1634
            }
1635

1636
            /**
1637
             * {@inheritDoc}
1638
             */
1639
            public String getInternalName() {
1640
                return MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME;
1✔
1641
            }
1642
        }
1643
    }
1644

1645
    /**
1646
     * A method description that represents a given method but with substituted method types.
1647
     */
1648
    class TypeSubstituting extends AbstractBase implements InGenericShape {
1649

1650
        /**
1651
         * The type that declares this type-substituted method.
1652
         */
1653
        private final TypeDescription.Generic declaringType;
1654

1655
        /**
1656
         * The represented method description.
1657
         */
1658
        private final MethodDescription methodDescription;
1659

1660
        /**
1661
         * A visitor that is applied to the method type.
1662
         */
1663
        private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
1664

1665
        /**
1666
         * Creates a method description with substituted method types.
1667
         *
1668
         * @param declaringType     The type that is declaring the substituted method.
1669
         * @param methodDescription The represented method description.
1670
         * @param visitor           A visitor that is applied to the method type.
1671
         */
1672
        public TypeSubstituting(TypeDescription.Generic declaringType,
1673
                                MethodDescription methodDescription,
1674
                                TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
1✔
1675
            this.declaringType = declaringType;
1✔
1676
            this.methodDescription = methodDescription;
1✔
1677
            this.visitor = visitor;
1✔
1678
        }
1✔
1679

1680
        /**
1681
         * {@inheritDoc}
1682
         */
1683
        public TypeDescription.Generic getReturnType() {
1684
            return methodDescription.getReturnType().accept(visitor);
1✔
1685
        }
1686

1687
        /**
1688
         * {@inheritDoc}
1689
         */
1690
        public TypeList.Generic getTypeVariables() {
1691
            return methodDescription.getTypeVariables().accept(visitor).filter(ElementMatchers.ofSort(TypeDefinition.Sort.VARIABLE));
1✔
1692
        }
1693

1694
        /**
1695
         * {@inheritDoc}
1696
         */
1697
        public ParameterList<ParameterDescription.InGenericShape> getParameters() {
1698
            return new ParameterList.TypeSubstituting(this, methodDescription.getParameters(), visitor);
1✔
1699
        }
1700

1701
        /**
1702
         * {@inheritDoc}
1703
         */
1704
        public TypeList.Generic getExceptionTypes() {
1705
            return new TypeList.Generic.ForDetachedTypes(methodDescription.getExceptionTypes(), visitor);
1✔
1706
        }
1707

1708
        /**
1709
         * {@inheritDoc}
1710
         */
1711
        @MaybeNull
1712
        public AnnotationValue<?, ?> getDefaultValue() {
1713
            return methodDescription.getDefaultValue();
1✔
1714
        }
1715

1716
        /**
1717
         * {@inheritDoc}
1718
         */
1719
        public TypeDescription.Generic getReceiverType() {
1720
            TypeDescription.Generic receiverType = methodDescription.getReceiverType();
1✔
1721
            return receiverType == null
1✔
1722
                    ? TypeDescription.Generic.UNDEFINED
1723
                    : receiverType.accept(visitor);
1✔
1724
        }
1725

1726
        /**
1727
         * {@inheritDoc}
1728
         */
1729
        public AnnotationList getDeclaredAnnotations() {
1730
            return methodDescription.getDeclaredAnnotations();
1✔
1731
        }
1732

1733
        /**
1734
         * {@inheritDoc}
1735
         */
1736
        @Nonnull
1737
        public TypeDescription.Generic getDeclaringType() {
1738
            return declaringType;
1✔
1739
        }
1740

1741
        /**
1742
         * {@inheritDoc}
1743
         */
1744
        public int getModifiers() {
1745
            return methodDescription.getModifiers();
1✔
1746
        }
1747

1748
        /**
1749
         * {@inheritDoc}
1750
         */
1751
        public String getInternalName() {
1752
            return methodDescription.getInternalName();
1✔
1753
        }
1754

1755
        /**
1756
         * {@inheritDoc}
1757
         */
1758
        public InDefinedShape asDefined() {
1759
            return methodDescription.asDefined();
1✔
1760
        }
1761

1762
        /**
1763
         * {@inheritDoc}
1764
         */
1765
        public boolean isConstructor() {
1766
            return methodDescription.isConstructor();
1✔
1767
        }
1768

1769
        /**
1770
         * {@inheritDoc}
1771
         */
1772
        public boolean isMethod() {
1773
            return methodDescription.isMethod();
1✔
1774
        }
1775

1776
        /**
1777
         * {@inheritDoc}
1778
         */
1779
        public boolean isTypeInitializer() {
1780
            return methodDescription.isTypeInitializer();
1✔
1781
        }
1782
    }
1783

1784
    /**
1785
     * A token representing a method's properties detached from a type.
1786
     */
1787
    class Token implements ByteCodeElement.Token<Token> {
1788

1789
        /**
1790
         * The internal name of the represented method.
1791
         */
1792
        private final String name;
1793

1794
        /**
1795
         * The modifiers of the represented method.
1796
         */
1797
        private final int modifiers;
1798

1799
        /**
1800
         * A list of tokens representing the method's type variables.
1801
         */
1802
        private final List<? extends TypeVariableToken> typeVariableTokens;
1803

1804
        /**
1805
         * The return type of the represented method.
1806
         */
1807
        private final TypeDescription.Generic returnType;
1808

1809
        /**
1810
         * The parameter tokens of the represented method.
1811
         */
1812
        private final List<? extends ParameterDescription.Token> parameterTokens;
1813

1814
        /**
1815
         * The exception types of the represented method.
1816
         */
1817
        private final List<? extends TypeDescription.Generic> exceptionTypes;
1818

1819
        /**
1820
         * The annotations of the represented method.
1821
         */
1822
        private final List<? extends AnnotationDescription> annotations;
1823

1824
        /**
1825
         * The default value of the represented method or {@code null} if no such value exists.
1826
         */
1827
        @MaybeNull
1828
        private final AnnotationValue<?, ?> defaultValue;
1829

1830
        /**
1831
         * The receiver type of the represented method or {@code null} if the receiver type is implicit.
1832
         */
1833
        @MaybeNull
1834
        private final TypeDescription.Generic receiverType;
1835

1836
        /**
1837
         * Creates a new method token representing a constructor without any parameters, exception types, type variables or annotations.
1838
         * All types must be represented in an detached format.
1839
         *
1840
         * @param modifiers The constructor's modifiers.
1841
         */
1842
        public Token(int modifiers) {
1843
            this(MethodDescription.CONSTRUCTOR_INTERNAL_NAME, modifiers, TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(void.class));
1✔
1844
        }
1✔
1845

1846
        /**
1847
         * Creates a new method token representing a method without any parameters, exception types, type variables or annotations.
1848
         * All types must be represented in an detached format.
1849
         *
1850
         * @param name       The name of the method.
1851
         * @param modifiers  The modifiers of the method.
1852
         * @param returnType The return type of the method.
1853
         */
1854
        public Token(String name, int modifiers, TypeDescription.Generic returnType) {
1855
            this(name, modifiers, returnType, Collections.<TypeDescription.Generic>emptyList());
1✔
1856
        }
1✔
1857

1858
        /**
1859
         * Creates a new method token with simple values. All types must be represented in an detached format.
1860
         *
1861
         * @param name           The internal name of the represented method.
1862
         * @param modifiers      The modifiers of the represented method.
1863
         * @param returnType     The return type of the represented method.
1864
         * @param parameterTypes The parameter types of this method.
1865
         */
1866
        public Token(String name, int modifiers, TypeDescription.Generic returnType, List<? extends TypeDescription.Generic> parameterTypes) {
1867
            this(name,
1✔
1868
                    modifiers,
1869
                    Collections.<TypeVariableToken>emptyList(),
1✔
1870
                    returnType,
1871
                    new ParameterDescription.Token.TypeList(parameterTypes),
1872
                    Collections.<TypeDescription.Generic>emptyList(),
1✔
1873
                    Collections.<AnnotationDescription>emptyList(),
1✔
1874
                    AnnotationValue.UNDEFINED,
1875
                    TypeDescription.Generic.UNDEFINED);
1876
        }
1✔
1877

1878
        /**
1879
         * Creates a new token for a method description. All types must be represented in an detached format.
1880
         *
1881
         * @param name               The internal name of the represented method.
1882
         * @param modifiers          The modifiers of the represented method.
1883
         * @param typeVariableTokens The type variables of the the represented method.
1884
         * @param returnType         The return type of the represented method.
1885
         * @param parameterTokens    The parameter tokens of the represented method.
1886
         * @param exceptionTypes     The exception types of the represented method.
1887
         * @param annotations        The annotations of the represented method.
1888
         * @param defaultValue       The default value of the represented method or {@code null} if no such value exists.
1889
         * @param receiverType       The receiver type of the represented method or {@code null} if the receiver type is implicit.
1890
         */
1891
        public Token(String name,
1892
                     int modifiers,
1893
                     List<? extends TypeVariableToken> typeVariableTokens,
1894
                     TypeDescription.Generic returnType,
1895
                     List<? extends ParameterDescription.Token> parameterTokens,
1896
                     List<? extends TypeDescription.Generic> exceptionTypes,
1897
                     List<? extends AnnotationDescription> annotations,
1898
                     @MaybeNull AnnotationValue<?, ?> defaultValue,
1899
                     @MaybeNull TypeDescription.Generic receiverType) {
1✔
1900
            this.name = name;
1✔
1901
            this.modifiers = modifiers;
1✔
1902
            this.typeVariableTokens = typeVariableTokens;
1✔
1903
            this.returnType = returnType;
1✔
1904
            this.parameterTokens = parameterTokens;
1✔
1905
            this.exceptionTypes = exceptionTypes;
1✔
1906
            this.annotations = annotations;
1✔
1907
            this.defaultValue = defaultValue;
1✔
1908
            this.receiverType = receiverType;
1✔
1909
        }
1✔
1910

1911
        /**
1912
         * Returns the internal name of the represented method.
1913
         *
1914
         * @return The internal name of the represented method.
1915
         */
1916
        public String getName() {
1917
            return name;
1✔
1918
        }
1919

1920
        /**
1921
         * Returns the modifiers of the represented method.
1922
         *
1923
         * @return The modifiers of the represented method.
1924
         */
1925
        public int getModifiers() {
1926
            return modifiers;
1✔
1927
        }
1928

1929
        /**
1930
         * Returns the type variables of this method token.
1931
         *
1932
         * @return A a list of tokens representing the method's type variables.
1933
         */
1934
        public TokenList<TypeVariableToken> getTypeVariableTokens() {
1935
            return new TokenList<TypeVariableToken>(typeVariableTokens);
1✔
1936
        }
1937

1938
        /**
1939
         * Returns the return type of the represented method.
1940
         *
1941
         * @return The return type of the represented method.
1942
         */
1943
        public TypeDescription.Generic getReturnType() {
1944
            return returnType;
1✔
1945
        }
1946

1947
        /**
1948
         * Returns the parameter tokens of the represented method.
1949
         *
1950
         * @return The parameter tokens of the represented method.
1951
         */
1952
        public TokenList<ParameterDescription.Token> getParameterTokens() {
1953
            return new TokenList<ParameterDescription.Token>(parameterTokens);
1✔
1954
        }
1955

1956
        /**
1957
         * Returns the exception types of the represented method.
1958
         *
1959
         * @return The exception types of the represented method.
1960
         */
1961
        public TypeList.Generic getExceptionTypes() {
1962
            return new TypeList.Generic.Explicit(exceptionTypes);
1✔
1963
        }
1964

1965
        /**
1966
         * Returns the annotations of the represented method.
1967
         *
1968
         * @return The annotations of the represented method.
1969
         */
1970
        public AnnotationList getAnnotations() {
1971
            return new AnnotationList.Explicit(annotations);
1✔
1972
        }
1973

1974
        /**
1975
         * Returns the default value of the represented method.
1976
         *
1977
         * @return The default value of the represented method or {@code null} if no such value exists.
1978
         */
1979
        @MaybeNull
1980
        public AnnotationValue<?, ?> getDefaultValue() {
1981
            return defaultValue;
1✔
1982
        }
1983

1984
        /**
1985
         * Returns the receiver type of this token or {@code null} if the receiver type is implicit.
1986
         *
1987
         * @return The receiver type of this token or {@code null} if the receiver type is implicit.
1988
         */
1989
        @MaybeNull
1990
        public TypeDescription.Generic getReceiverType() {
1991
            return receiverType;
1✔
1992
        }
1993

1994
        /**
1995
         * {@inheritDoc}
1996
         */
1997
        public Token accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
1998
            return new Token(name,
1✔
1999
                    modifiers,
2000
                    getTypeVariableTokens().accept(visitor),
1✔
2001
                    returnType.accept(visitor),
1✔
2002
                    getParameterTokens().accept(visitor),
1✔
2003
                    getExceptionTypes().accept(visitor),
1✔
2004
                    annotations,
2005
                    defaultValue,
2006
                    receiverType == null
2007
                            ? TypeDescription.Generic.UNDEFINED
2008
                            : receiverType.accept(visitor));
1✔
2009
        }
2010

2011
        /**
2012
         * Creates a signature token that represents the method that is represented by this token.
2013
         *
2014
         * @param declaringType The declaring type of the method that this token represents.
2015
         * @return A signature token representing this token.
2016
         */
2017
        public SignatureToken asSignatureToken(TypeDescription declaringType) {
2018
            TypeDescription.Generic.Visitor<TypeDescription> visitor = new TypeDescription.Generic.Visitor.Reducing(declaringType, typeVariableTokens);
1✔
2019
            List<TypeDescription> parameters = new ArrayList<TypeDescription>(parameterTokens.size());
1✔
2020
            for (ParameterDescription.Token parameter : parameterTokens) {
1✔
2021
                parameters.add(parameter.getType().accept(visitor));
1✔
2022
            }
1✔
2023
            return new SignatureToken(name, returnType.accept(visitor), parameters);
1✔
2024
        }
2025

2026
        @Override
2027
        @CachedReturnPlugin.Enhance("hashCode")
2028
        public int hashCode() {
2029
            int result = name.hashCode();
×
2030
            result = 31 * result + modifiers;
×
2031
            result = 31 * result + typeVariableTokens.hashCode();
×
2032
            result = 31 * result + returnType.hashCode();
×
2033
            result = 31 * result + parameterTokens.hashCode();
×
2034
            result = 31 * result + exceptionTypes.hashCode();
×
2035
            result = 31 * result + annotations.hashCode();
×
2036
            result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0);
×
2037
            result = 31 * result + (receiverType != null ? receiverType.hashCode() : 0);
×
2038
            return result;
×
2039
        }
2040

2041
        @Override
2042
        public boolean equals(@MaybeNull Object other) {
2043
            if (this == other) {
1✔
2044
                return true;
×
2045
            } else if (other == null || getClass() != other.getClass()) {
1✔
2046
                return false;
×
2047
            }
2048
            Token token = (Token) other;
1✔
2049
            return modifiers == token.modifiers
1✔
2050
                    && name.equals(token.name)
1✔
2051
                    && typeVariableTokens.equals(token.typeVariableTokens)
1✔
2052
                    && returnType.equals(token.returnType)
1✔
2053
                    && parameterTokens.equals(token.parameterTokens)
1✔
2054
                    && exceptionTypes.equals(token.exceptionTypes)
1✔
2055
                    && annotations.equals(token.annotations)
1✔
2056
                    && (defaultValue != null ? defaultValue.equals(token.defaultValue) : token.defaultValue == null)
1✔
2057
                    && (receiverType != null ? receiverType.equals(token.receiverType) : token.receiverType == null);
1✔
2058
        }
2059

2060
        @Override
2061
        public String toString() {
2062
            return "MethodDescription.Token{" +
×
2063
                    "name='" + name + '\'' +
2064
                    ", modifiers=" + modifiers +
2065
                    ", typeVariableTokens=" + typeVariableTokens +
2066
                    ", returnType=" + returnType +
2067
                    ", parameterTokens=" + parameterTokens +
2068
                    ", exceptionTypes=" + exceptionTypes +
2069
                    ", annotations=" + annotations +
2070
                    ", defaultValue=" + defaultValue +
2071
                    ", receiverType=" + receiverType +
2072
                    '}';
2073
        }
2074
    }
2075

2076
    /**
2077
     * A token representing a method's name and raw return and parameter types.
2078
     */
2079
    class SignatureToken {
2080

2081
        /**
2082
         * The internal name of the represented method.
2083
         */
2084
        private final String name;
2085

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

2091
        /**
2092
         * The represented method's raw parameter types.
2093
         */
2094
        private final List<? extends TypeDescription> parameterTypes;
2095

2096
        /**
2097
         * Creates a new type token.
2098
         *
2099
         * @param name          The internal name of the represented method.
2100
         * @param returnType    The represented method's raw return type.
2101
         * @param parameterType The represented method's raw parameter types.
2102
         */
2103
        public SignatureToken(String name, TypeDescription returnType, TypeDescription... parameterType) {
2104
            this(name, returnType, Arrays.asList(parameterType));
1✔
2105
        }
1✔
2106

2107
        /**
2108
         * Creates a new type token.
2109
         *
2110
         * @param name           The internal name of the represented method.
2111
         * @param returnType     The represented method's raw return type.
2112
         * @param parameterTypes The represented method's raw parameter types.
2113
         */
2114
        public SignatureToken(String name, TypeDescription returnType, List<? extends TypeDescription> parameterTypes) {
1✔
2115
            this.name = name;
1✔
2116
            this.returnType = returnType;
1✔
2117
            this.parameterTypes = parameterTypes;
1✔
2118
        }
1✔
2119

2120
        /**
2121
         * Returns the internal name of the represented method.
2122
         *
2123
         * @return The internal name of the represented method.
2124
         */
2125
        public String getName() {
2126
            return name;
1✔
2127
        }
2128

2129
        /**
2130
         * Returns this token's return type.
2131
         *
2132
         * @return This token's return type.
2133
         */
2134
        public TypeDescription getReturnType() {
2135
            return returnType;
1✔
2136
        }
2137

2138
        /**
2139
         * Returns this token's parameter types.
2140
         *
2141
         * @return This token's parameter types.
2142
         */
2143
        @SuppressWarnings("unchecked")
2144
        public List<TypeDescription> getParameterTypes() {
2145
            return (List<TypeDescription>) parameterTypes;
1✔
2146
        }
2147

2148
        /**
2149
         * Returns this signature token as a type token.
2150
         *
2151
         * @return This signature token as a type token.
2152
         */
2153
        public TypeToken asTypeToken() {
2154
            return new TypeToken(returnType, parameterTypes);
1✔
2155
        }
2156

2157
        /**
2158
         * Returns a method descriptor for this token.
2159
         *
2160
         * @return A method descriptor for this token.
2161
         */
2162
        public String getDescriptor() {
2163
            StringBuilder stringBuilder = new StringBuilder().append('(');
1✔
2164
            for (TypeDescription typeDescription : parameterTypes) {
1✔
2165
                stringBuilder.append(typeDescription.getDescriptor());
1✔
2166
            }
1✔
2167
            return stringBuilder.append(')').append(returnType.getDescriptor()).toString();
1✔
2168
        }
2169

2170
        @Override
2171
        @CachedReturnPlugin.Enhance("hashCode")
2172
        public int hashCode() {
2173
            int result = name.hashCode();
1✔
2174
            result = 31 * result + returnType.hashCode();
1✔
2175
            result = 31 * result + parameterTypes.hashCode();
1✔
2176
            return result;
1✔
2177
        }
2178

2179
        @Override
2180
        public boolean equals(@MaybeNull Object other) {
2181
            if (this == other) {
1✔
2182
                return true;
×
2183
            } else if (!(other instanceof SignatureToken)) {
1✔
2184
                return false;
×
2185
            }
2186
            SignatureToken signatureToken = (SignatureToken) other;
1✔
2187
            return name.equals(signatureToken.name)
1✔
2188
                    && returnType.equals(signatureToken.returnType)
1✔
2189
                    && parameterTypes.equals(signatureToken.parameterTypes);
1✔
2190
        }
2191

2192
        @Override
2193
        public String toString() {
2194
            StringBuilder stringBuilder = new StringBuilder().append(returnType).append(' ').append(name).append('(');
×
2195
            boolean first = true;
×
2196
            for (TypeDescription parameterType : parameterTypes) {
×
2197
                if (first) {
×
2198
                    first = false;
×
2199
                } else {
2200
                    stringBuilder.append(',');
×
2201
                }
2202
                stringBuilder.append(parameterType);
×
2203
            }
×
2204
            return stringBuilder.append(')').toString();
×
2205
        }
2206
    }
2207

2208
    /**
2209
     * A token representing a method's erased return and parameter types.
2210
     */
2211
    class TypeToken {
2212

2213
        /**
2214
         * The represented method's raw return type.
2215
         */
2216
        private final TypeDescription returnType;
2217

2218
        /**
2219
         * The represented method's raw parameter types.
2220
         */
2221
        private final List<? extends TypeDescription> parameterTypes;
2222

2223
        /**
2224
         * Creates a new type token.
2225
         *
2226
         * @param returnType     The represented method's raw return type.
2227
         * @param parameterTypes The represented method's raw parameter types.
2228
         */
2229
        public TypeToken(TypeDescription returnType, List<? extends TypeDescription> parameterTypes) {
1✔
2230
            this.returnType = returnType;
1✔
2231
            this.parameterTypes = parameterTypes;
1✔
2232
        }
1✔
2233

2234
        /**
2235
         * Returns this token's return type.
2236
         *
2237
         * @return This token's return type.
2238
         */
2239
        public TypeDescription getReturnType() {
2240
            return returnType;
1✔
2241
        }
2242

2243
        /**
2244
         * Returns this token's parameter types.
2245
         *
2246
         * @return This token's parameter types.
2247
         */
2248
        @SuppressWarnings("unchecked")
2249
        public List<TypeDescription> getParameterTypes() {
2250
            return (List<TypeDescription>) parameterTypes;
1✔
2251
        }
2252

2253
        @Override
2254
        @CachedReturnPlugin.Enhance("hashCode")
2255
        public int hashCode() {
2256
            int result = returnType.hashCode();
1✔
2257
            result = 31 * result + parameterTypes.hashCode();
1✔
2258
            return result;
1✔
2259
        }
2260

2261
        @Override
2262
        public boolean equals(@MaybeNull Object other) {
2263
            if (this == other) {
1✔
2264
                return true;
×
2265
            } else if (!(other instanceof TypeToken)) {
1✔
2266
                return false;
×
2267
            }
2268
            TypeToken typeToken = (TypeToken) other;
1✔
2269
            return returnType.equals(typeToken.returnType) && parameterTypes.equals(typeToken.parameterTypes);
1✔
2270
        }
2271

2272
        @Override
2273
        public String toString() {
2274
            StringBuilder stringBuilder = new StringBuilder().append('(');
1✔
2275
            for (TypeDescription parameterType : parameterTypes) {
1✔
2276
                stringBuilder.append(parameterType.getDescriptor());
1✔
2277
            }
1✔
2278
            return stringBuilder.append(')').append(returnType.getDescriptor()).toString();
1✔
2279
        }
2280
    }
2281
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc