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

raphw / byte-buddy / #832

03 Dec 2025 03:45PM UTC coverage: 82.982% (-0.03%) from 83.01%
#832

push

raphw
Remove unused import.

29613 of 35686 relevant lines covered (82.98%)

0.83 hits per line

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

67.16
/byte-buddy-dep/src/main/java/net/bytebuddy/description/method/ParameterDescription.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.build.HashCodeAndEqualsPlugin;
22
import net.bytebuddy.description.ByteCodeElement;
23
import net.bytebuddy.description.ModifierReviewable;
24
import net.bytebuddy.description.NamedElement;
25
import net.bytebuddy.description.annotation.AnnotationDescription;
26
import net.bytebuddy.description.annotation.AnnotationList;
27
import net.bytebuddy.description.annotation.AnnotationSource;
28
import net.bytebuddy.description.type.TypeDefinition;
29
import net.bytebuddy.description.type.TypeDescription;
30
import net.bytebuddy.description.type.TypeList;
31
import net.bytebuddy.implementation.bytecode.StackSize;
32
import net.bytebuddy.matcher.ElementMatcher;
33
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
34
import net.bytebuddy.utility.nullability.AlwaysNull;
35
import net.bytebuddy.utility.nullability.MaybeNull;
36

37
import java.lang.annotation.Annotation;
38
import java.lang.reflect.AccessibleObject;
39
import java.lang.reflect.Constructor;
40
import java.lang.reflect.Method;
41
import java.lang.reflect.Modifier;
42
import java.security.PrivilegedAction;
43
import java.util.AbstractList;
44
import java.util.Collections;
45
import java.util.List;
46

47
/**
48
 * Description of the parameter of a Java method or constructor.
49
 */
50
public interface ParameterDescription extends AnnotationSource,
51
        NamedElement.WithRuntimeName,
52
        NamedElement.WithOptionalName,
53
        ModifierReviewable.ForParameterDescription,
54
        ByteCodeElement.TypeDependant<ParameterDescription.InDefinedShape, ParameterDescription.Token> {
55

56
    /**
57
     * The prefix for names of an unnamed parameter.
58
     */
59
    String NAME_PREFIX = "arg";
60

61
    /**
62
     * Returns the type of this parameter.
63
     *
64
     * @return The type of this parameter.
65
     */
66
    TypeDescription.Generic getType();
67

68
    /**
69
     * Returns the method that declares this parameter.
70
     *
71
     * @return The method that declares this parameter.
72
     */
73
    MethodDescription getDeclaringMethod();
74

75
    /**
76
     * Returns this parameter's index.
77
     *
78
     * @return The index of this parameter.
79
     */
80
    int getIndex();
81

82
    /**
83
     * Checks if this parameter has an explicit modifier. A parameter without a modifier is simply treated as
84
     * if it had a modifier of zero.
85
     *
86
     * @return {@code true} if this parameter defines explicit modifiers.
87
     */
88
    boolean hasModifiers();
89

90
    /**
91
     * Returns the offset to the parameter value within the local method variable.
92
     *
93
     * @return The offset of this parameter's value.
94
     */
95
    int getOffset();
96

97
    /**
98
     * Represents a parameter description in its generic shape, i.e. in the shape it is defined by a generic or raw type.
99
     */
100
    interface InGenericShape extends ParameterDescription {
101

102
        /**
103
         * {@inheritDoc}
104
         */
105
        MethodDescription.InGenericShape getDeclaringMethod();
106
    }
107

108
    /**
109
     * Represents a parameter in its defined shape, i.e. in the form it is defined by a class without its type variables being resolved.
110
     */
111
    interface InDefinedShape extends ParameterDescription {
112

113
        /**
114
         * {@inheritDoc}
115
         */
116
        MethodDescription.InDefinedShape getDeclaringMethod();
117

118
        /**
119
         * An abstract base implementation of a parameter description in its defined shape.
120
         */
121
        abstract class AbstractBase extends ParameterDescription.AbstractBase implements InDefinedShape {
1✔
122

123
            /**
124
             * {@inheritDoc}
125
             */
126
            public InDefinedShape asDefined() {
127
                return this;
1✔
128
            }
129
        }
130
    }
131

132
    /**
133
     * A base implementation of a method parameter description.
134
     */
135
    abstract class AbstractBase extends ModifierReviewable.AbstractBase implements ParameterDescription {
1✔
136

137
        /**
138
         * {@inheritDoc}
139
         */
140
        public String getName() {
141
            return NAME_PREFIX.concat(String.valueOf(getIndex()));
1✔
142
        }
143

144
        /**
145
         * {@inheritDoc}
146
         */
147
        public String getInternalName() {
148
            return getName();
×
149
        }
150

151
        /**
152
         * {@inheritDoc}
153
         */
154
        public String getActualName() {
155
            return isNamed()
×
156
                    ? getName()
×
157
                    : EMPTY_NAME;
158
        }
159

160
        /**
161
         * {@inheritDoc}
162
         */
163
        public int getModifiers() {
164
            return EMPTY_MASK;
1✔
165
        }
166

167
        /**
168
         * {@inheritDoc}
169
         */
170
        @CachedReturnPlugin.Enhance("offset")
171
        public int getOffset() {
172
            TypeList parameterType = getDeclaringMethod().getParameters().asTypeList().asErasures();
1✔
173
            int offset = getDeclaringMethod().isStatic()
1✔
174
                    ? StackSize.ZERO.getSize()
1✔
175
                    : StackSize.SINGLE.getSize();
1✔
176
            for (int i = 0; i < getIndex(); i++) {
1✔
177
                offset += parameterType.get(i).getStackSize().getSize();
1✔
178
            }
179
            return offset;
1✔
180
        }
181

182
        /**
183
         * {@inheritDoc}
184
         */
185
        public Token asToken(ElementMatcher<? super TypeDescription> matcher) {
186
            return new Token(getType().accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)),
1✔
187
                    getDeclaredAnnotations(),
1✔
188
                    isNamed()
1✔
189
                            ? getName()
1✔
190
                            : Token.NO_NAME,
191
                    hasModifiers()
1✔
192
                            ? (Integer) getModifiers()
1✔
193
                            : Token.NO_MODIFIERS);
194
        }
195

196
        @Override
197
        @CachedReturnPlugin.Enhance("hashCode")
198
        public int hashCode() {
199
            return getDeclaringMethod().hashCode() ^ getIndex();
1✔
200
        }
201

202
        @Override
203
        public boolean equals(@MaybeNull Object other) {
204
            if (this == other) {
1✔
205
                return true;
1✔
206
            } else if (!(other instanceof ParameterDescription)) {
1✔
207
                return false;
1✔
208
            }
209
            ParameterDescription parameterDescription = (ParameterDescription) other;
1✔
210
            return getDeclaringMethod().equals(parameterDescription.getDeclaringMethod()) && getIndex() == parameterDescription.getIndex();
1✔
211
        }
212

213
        @Override
214
        public String toString() {
215
            StringBuilder stringBuilder = new StringBuilder(Modifier.toString(getModifiers()));
1✔
216
            if (getModifiers() != EMPTY_MASK) {
1✔
217
                stringBuilder.append(' ');
1✔
218
            }
219
            stringBuilder.append(isVarArgs()
1✔
220
                    ? getType().asErasure().getName().replaceFirst("\\[]$", "...")
1✔
221
                    : getType().asErasure().getName());
1✔
222
            return stringBuilder.append(' ').append(getName()).toString();
1✔
223
        }
224
    }
225

226
    /**
227
     * Description of a loaded parameter with support for the information exposed by {@code java.lang.reflect.Parameter}.
228
     *
229
     * @param <T> The type of the {@code java.lang.reflect.Executable} that this list represents.
230
     */
231
    abstract class ForLoadedParameter<T extends AccessibleObject> extends InDefinedShape.AbstractBase {
232

233
        /**
234
         * The name of the {@code java.lang.reflect.MalformedParametersException}. Due to compiler bugs, parameter
235
         * declarations might not always be legal, and by checking for this exception, one can trigger a fallback
236
         * behaviour.
237
         */
238
        private static final String MALFORMED_PARAMETERS_EXCEPTION = "java.lang.reflect.MalformedParametersException";
239

240
        /**
241
         * A dispatcher for reading properties from {@code java.lang.reflect.Parameter} instances.
242
         */
243
        private static final Parameter PARAMETER = doPrivileged(JavaDispatcher.of(Parameter.class));
1✔
244

245
        /**
246
         * The {@code java.lang.reflect.Executable} for which the parameter types are described.
247
         */
248
        protected final T executable;
249

250
        /**
251
         * The parameter's index.
252
         */
253
        protected final int index;
254

255
        /**
256
         * The parameter annotation source to query.
257
         */
258
        protected final ParameterAnnotationSource parameterAnnotationSource;
259

260
        /**
261
         * Creates a new description for a loaded parameter.
262
         *
263
         * @param executable                The {@code java.lang.reflect.Executable} for which the parameter types are described.
264
         * @param index                     The parameter's index.
265
         * @param parameterAnnotationSource The parameter annotation source to query.
266
         */
267
        protected ForLoadedParameter(T executable, int index, ParameterAnnotationSource parameterAnnotationSource) {
1✔
268
            this.executable = executable;
1✔
269
            this.index = index;
1✔
270
            this.parameterAnnotationSource = parameterAnnotationSource;
1✔
271
        }
1✔
272

273
        /**
274
         * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
275
         *
276
         * @param action The action to execute from a privileged context.
277
         * @param <T>    The type of the action's resolved value.
278
         * @return The action's resolved value.
279
         */
280
        @AccessControllerPlugin.Enhance
281
        private static <T> T doPrivileged(PrivilegedAction<T> action) {
282
            return action.run();
×
283
        }
284

285
        /**
286
         * {@inheritDoc}
287
         */
288
        public String getName() {
289
            try {
290
                return PARAMETER.getName(ParameterList.ForLoadedExecutable.EXECUTABLE.getParameters(executable)[index]);
1✔
291
            } catch (RuntimeException exception) {
×
292
                if (exception.getClass().getName().equals(MALFORMED_PARAMETERS_EXCEPTION)) {
×
293
                    return super.getName();
×
294
                }
295
                throw exception;
×
296
            }
297
        }
298

299
        /**
300
         * {@inheritDoc}
301
         */
302
        public int getIndex() {
303
            return index;
1✔
304
        }
305

306
        /**
307
         * {@inheritDoc}
308
         */
309
        public boolean isNamed() {
310
            try {
311
                return PARAMETER.isNamePresent(ParameterList.ForLoadedExecutable.EXECUTABLE.getParameters(executable)[index]);
1✔
312
            } catch (RuntimeException exception) {
×
313
                if (exception.getClass().getName().equals(MALFORMED_PARAMETERS_EXCEPTION)) {
×
314
                    return false;
×
315
                }
316
                throw exception;
×
317
            }
318
        }
319

320
        /**
321
         * {@inheritDoc}
322
         */
323
        public int getModifiers() {
324
            try {
325
                return PARAMETER.getModifiers(ParameterList.ForLoadedExecutable.EXECUTABLE.getParameters(executable)[index]);
1✔
326
            } catch (RuntimeException exception) {
×
327
                if (exception.getClass().getName().equals(MALFORMED_PARAMETERS_EXCEPTION)) {
×
328
                    return super.getModifiers();
×
329
                }
330
                throw exception;
×
331
            }
332
        }
333

334
        /**
335
         * {@inheritDoc}
336
         */
337
        public boolean hasModifiers() {
338
            // Rational: If a parameter is not named despite the information being attached,
339
            // it is synthetic, i.e. it has non-default modifiers.
340
            return isNamed() || getModifiers() != EMPTY_MASK;
1✔
341
        }
342

343
        /**
344
         * A source for querying parameter annotations.
345
         */
346
        public interface ParameterAnnotationSource {
347

348
            /**
349
             * Returns the parameter annotations represented by this source.
350
             *
351
             * @return The parameter annotations as an array indexed by parameter index.
352
             */
353
            Annotation[][] getParameterAnnotations();
354

355
            /**
356
             * A source for a loaded constructor.
357
             */
358
            @HashCodeAndEqualsPlugin.Enhance
359
            class ForLoadedConstructor implements ParameterAnnotationSource {
360

361
                /**
362
                 * The constructor to query for annotations.
363
                 */
364
                private final Constructor<?> constructor;
365

366
                /**
367
                 * Creates a new parameter annotation source for a constructor.
368
                 *
369
                 * @param constructor The constructor to query for annotations.
370
                 */
371
                public ForLoadedConstructor(Constructor<?> constructor) {
×
372
                    this.constructor = constructor;
×
373
                }
×
374

375
                /**
376
                 * {@inheritDoc}
377
                 */
378
                public Annotation[][] getParameterAnnotations() {
379
                    return constructor.getParameterAnnotations();
×
380
                }
381
            }
382

383
            /**
384
             * A source for a loaded method.
385
             */
386
            @HashCodeAndEqualsPlugin.Enhance
387
            class ForLoadedMethod implements ParameterAnnotationSource {
388

389
                /**
390
                 * The method to query for annotations.
391
                 */
392
                private final Method method;
393

394
                /**
395
                 * Creates a new parameter annpotation source for a method.
396
                 *
397
                 * @param method The method to query for annotations.
398
                 */
399
                public ForLoadedMethod(Method method) {
×
400
                    this.method = method;
×
401
                }
×
402

403
                /**
404
                 * {@inheritDoc}
405
                 */
406
                public Annotation[][] getParameterAnnotations() {
407
                    return method.getParameterAnnotations();
×
408
                }
409
            }
410
        }
411

412
        /**
413
         * A proxy for a {@code java.lang.reflect.Parameter}.
414
         */
415
        @JavaDispatcher.Proxied("java.lang.reflect.Parameter")
416
        protected interface Parameter {
417

418
            /**
419
             * Returns the given parameter's modifiers.
420
             *
421
             * @param value The parameter to introspect.
422
             * @return The parameter's modifiers.
423
             */
424
            int getModifiers(Object value);
425

426
            /**
427
             * Returns {@code true} if the given parameter has an explicit name.
428
             *
429
             * @param value The parameter to introspect.
430
             * @return {@code true} if the given parameter has an explicit name.
431
             */
432
            boolean isNamePresent(Object value);
433

434
            /**
435
             * Returns the given parameter's implicit or explicit name.
436
             *
437
             * @param value The parameter to introspect.
438
             * @return The parameter's name.
439
             */
440
            String getName(Object value);
441
        }
442

443
        /**
444
         * A description of a loaded {@link Method} parameter for a modern VM.
445
         */
446
        protected static class OfMethod extends ForLoadedParameter<Method> {
447

448
            /**
449
             * Creates a new description for a loaded method.
450
             *
451
             * @param method                    The method for which a parameter is represented.
452
             * @param index                     The index of the parameter.
453
             * @param parameterAnnotationSource The parameter annotation source to query.
454
             */
455
            protected OfMethod(Method method, int index, ParameterAnnotationSource parameterAnnotationSource) {
456
                super(method, index, parameterAnnotationSource);
1✔
457
            }
1✔
458

459
            /**
460
             * {@inheritDoc}
461
             */
462
            @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs.")
463
            public MethodDescription.InDefinedShape getDeclaringMethod() {
464
                return new MethodDescription.ForLoadedMethod(executable);
1✔
465
            }
466

467
            /**
468
             * {@inheritDoc}
469
             */
470
            @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs.")
471
            public TypeDescription.Generic getType() {
472
                if (TypeDescription.AbstractBase.RAW_TYPES) {
1✔
473
                    return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(executable.getParameterTypes()[index]);
×
474
                }
475
                return new TypeDescription.Generic.LazyProjection.OfMethodParameter(executable, index, executable.getParameterTypes());
1✔
476
            }
477

478
            /**
479
             * {@inheritDoc}
480
             */
481
            @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs.")
482
            public AnnotationList getDeclaredAnnotations() {
483
                return new AnnotationList.ForLoadedAnnotations(parameterAnnotationSource.getParameterAnnotations()[index]);
1✔
484
            }
485
        }
486

487
        /**
488
         * A description of a loaded {@link Constructor} parameter for a modern VM.
489
         */
490
        protected static class OfConstructor extends ForLoadedParameter<Constructor<?>> {
491

492
            /**
493
             * Creates a new description for a loaded constructor.
494
             *
495
             * @param constructor               The constructor for which a parameter is represented.
496
             * @param index                     The index of the parameter.
497
             * @param parameterAnnotationSource The parameter annotation source to query.
498
             */
499
            protected OfConstructor(Constructor<?> constructor, int index, ParameterAnnotationSource parameterAnnotationSource) {
500
                super(constructor, index, parameterAnnotationSource);
1✔
501
            }
1✔
502

503
            /**
504
             * {@inheritDoc}
505
             */
506
            @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs.")
507
            public MethodDescription.InDefinedShape getDeclaringMethod() {
508
                return new MethodDescription.ForLoadedConstructor(executable);
1✔
509
            }
510

511
            /**
512
             * {@inheritDoc}
513
             */
514
            @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs.")
515
            public TypeDescription.Generic getType() {
516
                if (TypeDescription.AbstractBase.RAW_TYPES) {
1✔
517
                    return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(executable.getParameterTypes()[index]);
×
518
                }
519
                return new TypeDescription.Generic.LazyProjection.OfConstructorParameter(executable, index, executable.getParameterTypes());
1✔
520
            }
521

522
            /**
523
             * {@inheritDoc}
524
             */
525
            @SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs")
526
            public AnnotationList getDeclaredAnnotations() {
527
                Annotation[][] annotation = parameterAnnotationSource.getParameterAnnotations();
1✔
528
                MethodDescription.InDefinedShape declaringMethod = getDeclaringMethod();
1✔
529
                if (annotation.length != declaringMethod.getParameters().size() && declaringMethod.getDeclaringType().isInnerClass()) {
1✔
530
                    return index == 0
1✔
531
                            ? new AnnotationList.Empty()
532
                            : new AnnotationList.ForLoadedAnnotations(annotation[index - 1]);
533
                } else {
534
                    return new AnnotationList.ForLoadedAnnotations(annotation[index]);
1✔
535
                }
536
            }
537
        }
538

539
        /**
540
         * Description of a loaded method's parameter on a virtual machine where {@code java.lang.reflect.Parameter}
541
         * is not available.
542
         */
543
        protected static class OfLegacyVmMethod extends InDefinedShape.AbstractBase {
544

545
            /**
546
             * The method that declares this parameter.
547
             */
548
            private final Method method;
549

550
            /**
551
             * The index of this parameter.
552
             */
553
            private final int index;
554

555
            /**
556
             * The type erasures of the represented method.
557
             */
558
            private final Class<?>[] parameterType;
559

560
            /**
561
             * The parameter annotation source to query.
562
             */
563
            private final ParameterAnnotationSource parameterAnnotationSource;
564

565
            /**
566
             * Creates a legacy representation of a method's parameter.
567
             *
568
             * @param method                    The method that declares this parameter.
569
             * @param index                     The index of this parameter.
570
             * @param parameterType             The type erasures of the represented method.
571
             * @param parameterAnnotationSource The parameter annotation source to query.
572
             */
573
            protected OfLegacyVmMethod(Method method, int index, Class<?>[] parameterType, ParameterAnnotationSource parameterAnnotationSource) {
×
574
                this.method = method;
×
575
                this.index = index;
×
576
                this.parameterType = parameterType;
×
577
                this.parameterAnnotationSource = parameterAnnotationSource;
×
578
            }
×
579

580
            /**
581
             * {@inheritDoc}
582
             */
583
            public TypeDescription.Generic getType() {
584
                if (TypeDescription.AbstractBase.RAW_TYPES) {
×
585
                    return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(parameterType[index]);
×
586
                }
587
                return new TypeDescription.Generic.LazyProjection.OfMethodParameter(method, index, parameterType);
×
588
            }
589

590
            /**
591
             * {@inheritDoc}
592
             */
593
            public MethodDescription.InDefinedShape getDeclaringMethod() {
594
                return new MethodDescription.ForLoadedMethod(method);
×
595
            }
596

597
            /**
598
             * {@inheritDoc}
599
             */
600
            public int getIndex() {
601
                return index;
×
602
            }
603

604
            /**
605
             * {@inheritDoc}
606
             */
607
            public boolean isNamed() {
608
                return false;
×
609
            }
610

611
            /**
612
             * {@inheritDoc}
613
             */
614
            public boolean hasModifiers() {
615
                return false;
×
616
            }
617

618
            /**
619
             * {@inheritDoc}
620
             */
621
            public AnnotationList getDeclaredAnnotations() {
622
                return new AnnotationList.ForLoadedAnnotations(parameterAnnotationSource.getParameterAnnotations()[index]);
×
623
            }
624
        }
625

626
        /**
627
         * Description of a loaded constructor's parameter on a virtual machine where {@code java.lang.reflect.Parameter}
628
         * is not available.
629
         */
630
        protected static class OfLegacyVmConstructor extends InDefinedShape.AbstractBase {
631

632
            /**
633
             * The method that declares this parameter.
634
             */
635
            private final Constructor<?> constructor;
636

637
            /**
638
             * The index of this parameter.
639
             */
640
            private final int index;
641

642
            /**
643
             * The type erasures of the represented method.
644
             */
645
            private final Class<?>[] parameterType;
646

647
            /**
648
             * The parameter annotation source to query.
649
             */
650
            private final ParameterAnnotationSource parameterAnnotationSource;
651

652
            /**
653
             * Creates a legacy representation of a method's parameter.
654
             *
655
             * @param constructor               The constructor that declares this parameter.
656
             * @param index                     The index of this parameter.
657
             * @param parameterType             The type erasures of the represented method.
658
             * @param parameterAnnotationSource The parameter annotation source to query.
659
             */
660
            protected OfLegacyVmConstructor(Constructor<?> constructor, int index, Class<?>[] parameterType, ParameterAnnotationSource parameterAnnotationSource) {
×
661
                this.constructor = constructor;
×
662
                this.index = index;
×
663
                this.parameterType = parameterType;
×
664
                this.parameterAnnotationSource = parameterAnnotationSource;
×
665
            }
×
666

667
            /**
668
             * {@inheritDoc}
669
             */
670
            public TypeDescription.Generic getType() {
671
                if (TypeDescription.AbstractBase.RAW_TYPES) {
×
672
                    return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(parameterType[index]);
×
673
                }
674
                return new TypeDescription.Generic.LazyProjection.OfConstructorParameter(constructor, index, parameterType);
×
675
            }
676

677
            /**
678
             * {@inheritDoc}
679
             */
680
            public MethodDescription.InDefinedShape getDeclaringMethod() {
681
                return new MethodDescription.ForLoadedConstructor(constructor);
×
682
            }
683

684
            /**
685
             * {@inheritDoc}
686
             */
687
            public int getIndex() {
688
                return index;
×
689
            }
690

691
            /**
692
             * {@inheritDoc}
693
             */
694
            public boolean isNamed() {
695
                return false;
×
696
            }
697

698
            /**
699
             * {@inheritDoc}
700
             */
701
            public boolean hasModifiers() {
702
                return false;
×
703
            }
704

705
            /**
706
             * {@inheritDoc}
707
             */
708
            public AnnotationList getDeclaredAnnotations() {
709
                MethodDescription.InDefinedShape declaringMethod = getDeclaringMethod();
×
710
                Annotation[][] parameterAnnotation = parameterAnnotationSource.getParameterAnnotations();
×
711
                if (parameterAnnotation.length != declaringMethod.getParameters().size() && declaringMethod.getDeclaringType().isInnerClass()) {
×
712
                    return index == 0
×
713
                            ? new AnnotationList.Empty()
714
                            : new AnnotationList.ForLoadedAnnotations(parameterAnnotation[index - 1]);
715
                } else {
716
                    return new AnnotationList.ForLoadedAnnotations(parameterAnnotation[index]);
×
717
                }
718
            }
719
        }
720
    }
721

722
    /**
723
     * A latent description of a parameter that is not attached to a method or constructor.
724
     */
725
    class Latent extends InDefinedShape.AbstractBase {
726

727
        /**
728
         * The method that is declaring the parameter.
729
         */
730
        private final MethodDescription.InDefinedShape declaringMethod;
731

732
        /**
733
         * The type of the parameter.
734
         */
735
        private final TypeDescription.Generic parameterType;
736

737
        /**
738
         * The annotations of the parameter.
739
         */
740
        private final List<? extends AnnotationDescription> declaredAnnotations;
741

742
        /**
743
         * The name of the parameter or {@code null} if no name is explicitly defined.
744
         */
745
        @MaybeNull
746
        private final String name;
747

748
        /**
749
         * The modifiers of the parameter or {@code null} if no modifiers are explicitly defined.
750
         */
751
        @MaybeNull
752
        private final Integer modifiers;
753

754
        /**
755
         * The index of the parameter.
756
         */
757
        private final int index;
758

759
        /**
760
         * The parameter's offset in the local method variables array.
761
         */
762
        private final int offset;
763

764
        /**
765
         * Creates a latent parameter description. All provided types are attached to this instance before they are returned.
766
         *
767
         * @param declaringMethod The method that is declaring the parameter.
768
         * @param token           The token describing the shape of the parameter.
769
         * @param index           The index of the parameter.
770
         * @param offset          The parameter's offset in the local method variables array.
771
         */
772
        public Latent(MethodDescription.InDefinedShape declaringMethod, Token token, int index, int offset) {
773
            this(declaringMethod,
1✔
774
                    token.getType(),
1✔
775
                    token.getAnnotations(),
1✔
776
                    token.getName(),
1✔
777
                    token.getModifiers(),
1✔
778
                    index,
779
                    offset);
780
        }
1✔
781

782
        /**
783
         * Creates a new latent parameter descriptions for a parameter without explicit meta data or annotations.
784
         *
785
         * @param declaringMethod The method declaring this parameter.
786
         * @param parameterType   The type of the parameter.
787
         * @param index           The index of the parameter.
788
         * @param offset          The offset of the parameter.
789
         */
790
        public Latent(MethodDescription.InDefinedShape declaringMethod,
791
                      TypeDescription.Generic parameterType,
792
                      int index,
793
                      int offset) {
794
            this(declaringMethod,
1✔
795
                    parameterType,
796
                    Collections.<AnnotationDescription>emptyList(),
1✔
797
                    Token.NO_NAME,
798
                    Token.NO_MODIFIERS,
799
                    index,
800
                    offset);
801
        }
1✔
802

803
        /**
804
         * Creates a latent parameter description. All provided types are attached to this instance before they are returned.
805
         *
806
         * @param declaringMethod     The method that is declaring the parameter.
807
         * @param parameterType       The parameter's type.
808
         * @param declaredAnnotations The annotations of the parameter.
809
         * @param name                The name of the parameter or {@code null} if no name is explicitly defined.
810
         * @param modifiers           The modifiers of the parameter or {@code null} if no modifiers are explicitly defined.
811
         * @param index               The index of the parameter.
812
         * @param offset              The parameter's offset in the local method variables array.
813
         */
814
        public Latent(MethodDescription.InDefinedShape declaringMethod,
815
                      TypeDescription.Generic parameterType,
816
                      List<? extends AnnotationDescription> declaredAnnotations,
817
                      @MaybeNull String name,
818
                      @MaybeNull Integer modifiers,
819
                      int index,
820
                      int offset) {
1✔
821
            this.declaringMethod = declaringMethod;
1✔
822
            this.parameterType = parameterType;
1✔
823
            this.declaredAnnotations = declaredAnnotations;
1✔
824
            this.name = name;
1✔
825
            this.modifiers = modifiers;
1✔
826
            this.index = index;
1✔
827
            this.offset = offset;
1✔
828
        }
1✔
829

830
        /**
831
         * {@inheritDoc}
832
         */
833
        public TypeDescription.Generic getType() {
834
            return parameterType.accept(TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
1✔
835
        }
836

837
        /**
838
         * {@inheritDoc}
839
         */
840
        public MethodDescription.InDefinedShape getDeclaringMethod() {
841
            return declaringMethod;
1✔
842
        }
843

844
        /**
845
         * {@inheritDoc}
846
         */
847
        public int getIndex() {
848
            return index;
1✔
849
        }
850

851
        /**
852
         * {@inheritDoc}
853
         */
854
        public int getOffset() {
855
            return offset;
1✔
856
        }
857

858
        /**
859
         * {@inheritDoc}
860
         */
861
        public boolean isNamed() {
862
            return name != null;
1✔
863
        }
864

865
        /**
866
         * {@inheritDoc}
867
         */
868
        public boolean hasModifiers() {
869
            return modifiers != null;
1✔
870
        }
871

872
        /**
873
         * {@inheritDoc}
874
         */
875
        public String getName() {
876
            return name == null
1✔
877
                    ? super.getName()
1✔
878
                    : name;
879
        }
880

881
        /**
882
         * {@inheritDoc}
883
         */
884
        public int getModifiers() {
885
            return modifiers == null
1✔
886
                    ? super.getModifiers()
1✔
887
                    : modifiers;
1✔
888
        }
889

890
        /**
891
         * {@inheritDoc}
892
         */
893
        public AnnotationList getDeclaredAnnotations() {
894
            return new AnnotationList.Explicit(declaredAnnotations);
1✔
895
        }
896
    }
897

898
    /**
899
     * <p>
900
     * A parameter description that represents a given parameter but with a substituted parameter type.
901
     * </p>
902
     * <p>
903
     * <b>Note</b>: The supplied visitor must assure to not substitute
904
     * </p>
905
     */
906
    class TypeSubstituting extends AbstractBase implements InGenericShape {
907

908
        /**
909
         * The method that declares this type-substituted parameter.
910
         */
911
        private final MethodDescription.InGenericShape declaringMethod;
912

913
        /**
914
         * The represented parameter.
915
         */
916
        private final ParameterDescription parameterDescription;
917

918
        /**
919
         * A visitor that is applied to the parameter type.
920
         */
921
        private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
922

923
        /**
924
         * Creates a new type substituting parameter.
925
         *
926
         * @param declaringMethod      The method that declares this type-substituted parameter.
927
         * @param parameterDescription The represented parameter.
928
         * @param visitor              A visitor that is applied to the parameter type.
929
         */
930
        public TypeSubstituting(MethodDescription.InGenericShape declaringMethod,
931
                                ParameterDescription parameterDescription,
932
                                TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
1✔
933
            this.declaringMethod = declaringMethod;
1✔
934
            this.parameterDescription = parameterDescription;
1✔
935
            this.visitor = visitor;
1✔
936
        }
1✔
937

938
        /**
939
         * {@inheritDoc}
940
         */
941
        public TypeDescription.Generic getType() {
942
            return parameterDescription.getType().accept(visitor);
1✔
943
        }
944

945
        /**
946
         * {@inheritDoc}
947
         */
948
        public MethodDescription.InGenericShape getDeclaringMethod() {
949
            return declaringMethod;
1✔
950
        }
951

952
        /**
953
         * {@inheritDoc}
954
         */
955
        public int getIndex() {
956
            return parameterDescription.getIndex();
1✔
957
        }
958

959
        /**
960
         * {@inheritDoc}
961
         */
962
        public boolean isNamed() {
963
            return parameterDescription.isNamed();
1✔
964
        }
965

966
        /**
967
         * {@inheritDoc}
968
         */
969
        public boolean hasModifiers() {
970
            return parameterDescription.hasModifiers();
1✔
971
        }
972

973
        /**
974
         * {@inheritDoc}
975
         */
976
        public int getOffset() {
977
            return parameterDescription.getOffset();
1✔
978
        }
979

980
        /**
981
         * {@inheritDoc}
982
         */
983
        public String getName() {
984
            return parameterDescription.getName();
1✔
985
        }
986

987
        /**
988
         * {@inheritDoc}
989
         */
990
        public int getModifiers() {
991
            return parameterDescription.getModifiers();
1✔
992
        }
993

994
        /**
995
         * {@inheritDoc}
996
         */
997
        public AnnotationList getDeclaredAnnotations() {
998
            return parameterDescription.getDeclaredAnnotations();
1✔
999
        }
1000

1001
        /**
1002
         * {@inheritDoc}
1003
         */
1004
        public InDefinedShape asDefined() {
1005
            return parameterDescription.asDefined();
1✔
1006
        }
1007
    }
1008

1009
    /**
1010
     * A token representing a parameter's properties detached from a type.
1011
     */
1012
    class Token implements ByteCodeElement.Token<Token> {
1013

1014
        /**
1015
         * Indicator for a method parameter without an explicit name.
1016
         */
1017
        @AlwaysNull
1018
        public static final String NO_NAME = null;
1✔
1019

1020
        /**
1021
         * Indicator for a method parameter without explicit modifiers.
1022
         */
1023
        @AlwaysNull
1024
        public static final Integer NO_MODIFIERS = null;
1✔
1025

1026
        /**
1027
         * The type of the represented parameter.
1028
         */
1029
        private final TypeDescription.Generic type;
1030

1031
        /**
1032
         * A list of parameter annotations.
1033
         */
1034
        private final List<? extends AnnotationDescription> annotations;
1035

1036
        /**
1037
         * The name of the parameter or {@code null} if no explicit name is defined.
1038
         */
1039
        @MaybeNull
1040
        private final String name;
1041

1042
        /**
1043
         * The modifiers of the parameter or {@code null} if no explicit modifiers is defined.
1044
         */
1045
        @MaybeNull
1046
        private final Integer modifiers;
1047

1048
        /**
1049
         * Creates a new parameter token without an explicit name, an explicit modifier or annotations.
1050
         * The parameter type must be represented in its detached format.
1051
         *
1052
         * @param type The type of the represented parameter.
1053
         */
1054
        public Token(TypeDescription.Generic type) {
1055
            this(type, Collections.<AnnotationDescription>emptyList());
1✔
1056
        }
1✔
1057

1058
        /**
1059
         * Creates a new parameter token without an explicit name or an explicit modifier. The parameter type must be represented in its detached format.
1060
         *
1061
         * @param type        The type of the represented parameter.
1062
         * @param annotations The annotations of the parameter.
1063
         */
1064
        public Token(TypeDescription.Generic type, List<? extends AnnotationDescription> annotations) {
1065
            this(type, annotations, NO_NAME, NO_MODIFIERS);
1✔
1066
        }
1✔
1067

1068
        /**
1069
         * Creates a parameter token without annotations. The parameter type must be represented in its detached format.
1070
         *
1071
         * @param type      The type of the represented parameter.
1072
         * @param name      The name of the parameter or {@code null} if no explicit name is defined.
1073
         * @param modifiers The modifiers of the parameter or {@code null} if no explicit modifiers is defined.
1074
         */
1075
        public Token(TypeDescription.Generic type, @MaybeNull String name, @MaybeNull Integer modifiers) {
1076
            this(type, Collections.<AnnotationDescription>emptyList(), name, modifiers);
1✔
1077
        }
1✔
1078

1079
        /**
1080
         * Creates a new parameter token. The parameter type must be represented in its detached format.
1081
         *
1082
         * @param type        The type of the represented parameter.
1083
         * @param annotations The annotations of the parameter.
1084
         * @param name        The name of the parameter or {@code null} if no explicit name is defined.
1085
         * @param modifiers   The modifiers of the parameter or {@code null} if no explicit modifiers is defined.
1086
         */
1087
        public Token(TypeDescription.Generic type,
1088
                     List<? extends AnnotationDescription> annotations,
1089
                     @MaybeNull String name,
1090
                     @MaybeNull Integer modifiers) {
1✔
1091
            this.type = type;
1✔
1092
            this.annotations = annotations;
1✔
1093
            this.name = name;
1✔
1094
            this.modifiers = modifiers;
1✔
1095
        }
1✔
1096

1097
        /**
1098
         * Returns the type of the represented method parameter.
1099
         *
1100
         * @return The type of the represented method parameter.
1101
         */
1102
        public TypeDescription.Generic getType() {
1103
            return type;
1✔
1104
        }
1105

1106
        /**
1107
         * Returns the annotations of the represented method parameter.
1108
         *
1109
         * @return The annotations of the represented method parameter.
1110
         */
1111
        public AnnotationList getAnnotations() {
1112
            return new AnnotationList.Explicit(annotations);
1✔
1113
        }
1114

1115
        /**
1116
         * Returns the name of the represented method parameter.
1117
         *
1118
         * @return The name of the parameter or {@code null} if no explicit name is defined.
1119
         */
1120
        @MaybeNull
1121
        public String getName() {
1122
            return name;
1✔
1123
        }
1124

1125
        /**
1126
         * Returns the modifiers of the represented method parameter.
1127
         *
1128
         * @return The modifiers of the parameter or {@code null} if no explicit modifiers is defined.
1129
         */
1130
        @MaybeNull
1131
        public Integer getModifiers() {
1132
            return modifiers;
1✔
1133
        }
1134

1135
        /**
1136
         * {@inheritDoc}
1137
         */
1138
        public Token accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) {
1139
            return new Token(type.accept(visitor),
1✔
1140
                    annotations,
1141
                    name,
1142
                    modifiers);
1143
        }
1144

1145
        @Override
1146
        @CachedReturnPlugin.Enhance("hashCode")
1147
        public int hashCode() {
1148
            int result = type.hashCode();
×
1149
            result = 31 * result + annotations.hashCode();
×
1150
            result = 31 * result + (name != null ? name.hashCode() : 0);
×
1151
            result = 31 * result + (modifiers != null ? modifiers.hashCode() : 0);
×
1152
            return result;
×
1153
        }
1154

1155
        @Override
1156
        public boolean equals(@MaybeNull Object other) {
1157
            if (this == other) {
1✔
1158
                return true;
×
1159
            } else if (!(other instanceof Token)) {
1✔
1160
                return false;
×
1161
            }
1162
            Token token = (Token) other;
1✔
1163
            return type.equals(token.type)
1✔
1164
                    && annotations.equals(token.annotations)
1✔
1165
                    && (name != null ? name.equals(token.name) : token.name == null)
1✔
1166
                    && (modifiers != null ? modifiers.equals(token.modifiers) : token.modifiers == null);
1✔
1167
        }
1168

1169
        @Override
1170
        public String toString() {
1171
            return "ParameterDescription.Token{" +
×
1172
                    "type=" + type +
1173
                    ", annotations=" + annotations +
1174
                    ", name='" + name + '\'' +
1175
                    ", modifiers=" + modifiers +
1176
                    '}';
1177
        }
1178

1179
        /**
1180
         * A list of types represented as a list of parameter tokens.
1181
         */
1182
        public static class TypeList extends AbstractList<Token> {
1183

1184
            /**
1185
             * The list of types to represent as parameter tokens.
1186
             */
1187
            private final List<? extends TypeDefinition> typeDescriptions;
1188

1189
            /**
1190
             * Creates a new list of types that represent parameters.
1191
             *
1192
             * @param typeDescriptions The types to represent.
1193
             */
1194
            public TypeList(List<? extends TypeDefinition> typeDescriptions) {
1✔
1195
                this.typeDescriptions = typeDescriptions;
1✔
1196
            }
1✔
1197

1198
            /**
1199
             * {@inheritDoc}
1200
             */
1201
            public Token get(int index) {
1202
                return new Token(typeDescriptions.get(index).asGenericType());
1✔
1203
            }
1204

1205
            /**
1206
             * {@inheritDoc}
1207
             */
1208
            public int size() {
1209
                return typeDescriptions.size();
1✔
1210
            }
1211
        }
1212
    }
1213
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc