• 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

99.02
/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/attribute/MethodAttributeAppender.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.implementation.attribute;
17

18
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19
import net.bytebuddy.description.annotation.AnnotationDescription;
20
import net.bytebuddy.description.method.MethodDescription;
21
import net.bytebuddy.description.method.ParameterDescription;
22
import net.bytebuddy.description.method.ParameterList;
23
import net.bytebuddy.description.type.TypeDescription;
24
import org.objectweb.asm.MethodVisitor;
25

26
import java.util.ArrayList;
27
import java.util.Arrays;
28
import java.util.List;
29

30
import static net.bytebuddy.matcher.ElementMatchers.annotationType;
31
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
32
import static net.bytebuddy.matcher.ElementMatchers.not;
33

34
/**
35
 * An appender that writes attributes or annotations to a given ASM {@link org.objectweb.asm.MethodVisitor}.
36
 */
37
public interface MethodAttributeAppender {
38

39
    /**
40
     * Applies this attribute appender to a given method visitor.
41
     *
42
     * @param methodVisitor         The method visitor to which the attributes that are represented by this attribute
43
     *                              appender are written to.
44
     * @param methodDescription     The description of the method for which the given method visitor creates an
45
     *                              instrumentation for.
46
     * @param annotationValueFilter The annotation value filter to apply when the annotations are written.
47
     */
48
    void apply(MethodVisitor methodVisitor, MethodDescription methodDescription, AnnotationValueFilter annotationValueFilter);
49

50
    /**
51
     * A method attribute appender that does not append any attributes.
52
     */
53
    enum NoOp implements MethodAttributeAppender, Factory {
1✔
54

55
        /**
56
         * The singleton instance.
57
         */
58
        INSTANCE;
1✔
59

60
        /**
61
         * {@inheritDoc}
62
         */
63
        public MethodAttributeAppender make(TypeDescription typeDescription) {
64
            return this;
1✔
65
        }
66

67
        /**
68
         * {@inheritDoc}
69
         */
70
        public void apply(MethodVisitor methodVisitor, MethodDescription methodDescription, AnnotationValueFilter annotationValueFilter) {
71
            /* do nothing */
72
        }
1✔
73
    }
74

75
    /**
76
     * A factory that creates method attribute appenders for a given type.
77
     */
78
    interface Factory {
79

80
        /**
81
         * Returns a method attribute appender that is applicable for a given type description.
82
         *
83
         * @param typeDescription The type for which a method attribute appender is to be applied for.
84
         * @return The method attribute appender which should be applied for the given type.
85
         */
86
        MethodAttributeAppender make(TypeDescription typeDescription);
87

88
        /**
89
         * A method attribute appender factory that combines several method attribute appender factories to be
90
         * represented as a single factory.
91
         */
92
        @HashCodeAndEqualsPlugin.Enhance
93
        class Compound implements Factory {
94

95
            /**
96
             * The factories this compound factory represents in their application order.
97
             */
98
            private final List<Factory> factories;
99

100
            /**
101
             * Creates a new compound method attribute appender factory.
102
             *
103
             * @param factory The factories that are to be combined by this compound factory in the order of their application.
104
             */
105
            public Compound(Factory... factory) {
106
                this(Arrays.asList(factory));
1✔
107
            }
1✔
108

109
            /**
110
             * Creates a new compound method attribute appender factory.
111
             *
112
             * @param factories The factories that are to be combined by this compound factory in the order of their application.
113
             */
114
            public Compound(List<? extends Factory> factories) {
1✔
115
                this.factories = new ArrayList<Factory>();
1✔
116
                for (Factory factory : factories) {
1✔
117
                    if (factory instanceof Compound) {
1✔
118
                        this.factories.addAll(((Compound) factory).factories);
1✔
119
                    } else if (!(factory instanceof NoOp)) {
1✔
120
                        this.factories.add(factory);
1✔
121
                    }
122
                }
1✔
123
            }
1✔
124

125
            /**
126
             * {@inheritDoc}
127
             */
128
            public MethodAttributeAppender make(TypeDescription typeDescription) {
129
                List<MethodAttributeAppender> methodAttributeAppenders = new ArrayList<MethodAttributeAppender>(factories.size());
1✔
130
                for (Factory factory : factories) {
1✔
131
                    methodAttributeAppenders.add(factory.make(typeDescription));
1✔
132
                }
1✔
133
                return new MethodAttributeAppender.Compound(methodAttributeAppenders);
1✔
134
            }
135
        }
136
    }
137

138
    /**
139
     * <p>
140
     * Implementation of a method attribute appender that writes all annotations of the instrumented method to the
141
     * method that is being created. This includes method and parameter annotations.
142
     * </p>
143
     * <p>
144
     * <b>Important</b>: This attribute appender does not apply for annotation types within the {@code jdk.internal.} namespace
145
     * which are silently ignored. If such annotations should be inherited, they need to be added explicitly.
146
     * </p>
147
     */
148
    enum ForInstrumentedMethod implements MethodAttributeAppender, Factory {
1✔
149

150
        /**
151
         * Appends all annotations of the instrumented method but not the annotations of the method's receiver type if such a type exists.
152
         */
153
        EXCLUDING_RECEIVER {
1✔
154
            @Override
155
            protected AnnotationAppender appendReceiver(AnnotationAppender annotationAppender,
156
                                                        AnnotationValueFilter annotationValueFilter,
157
                                                        MethodDescription methodDescription) {
158
                return annotationAppender;
1✔
159
            }
160
        },
161

162
        /**
163
         * <p>
164
         * Appends all annotations of the instrumented method including the annotations of the method's receiver type if such a type exists.
165
         * </p>
166
         * <p>
167
         * If a method is overridden, the annotations can be misplaced if the overriding class does not expose a similar structure to
168
         * the method that declared the method, i.e. the same amount of type variables and similar owner types. If this is not the case,
169
         * type annotations are appended as if the overridden method was declared by the original type. This does not corrupt the resulting
170
         * class file but it might result in type annotations not being visible via core reflection. This might however confuse other tools
171
         * that parse the resulting class file manually.
172
         * </p>
173
         */
174
        INCLUDING_RECEIVER {
1✔
175
            @Override
176
            protected AnnotationAppender appendReceiver(AnnotationAppender annotationAppender,
177
                                                        AnnotationValueFilter annotationValueFilter,
178
                                                        MethodDescription methodDescription) {
179
                TypeDescription.Generic receiverType = methodDescription.getReceiverType();
1✔
180
                return receiverType == null
1✔
181
                        ? annotationAppender
182
                        : receiverType.accept(AnnotationAppender.ForTypeAnnotations.ofReceiverType(annotationAppender, annotationValueFilter));
1✔
183
            }
184
        };
185

186
        /**
187
         * {@inheritDoc}
188
         */
189
        public MethodAttributeAppender make(TypeDescription typeDescription) {
190
            return this;
1✔
191
        }
192

193
        /**
194
         * {@inheritDoc}
195
         */
196
        public void apply(MethodVisitor methodVisitor, MethodDescription methodDescription, AnnotationValueFilter annotationValueFilter) {
197
            AnnotationAppender annotationAppender = new AnnotationAppender.Default(new AnnotationAppender.Target.OnMethod(methodVisitor));
1✔
198
            annotationAppender = methodDescription.getReturnType().accept(AnnotationAppender.ForTypeAnnotations.ofMethodReturnType(annotationAppender,
1✔
199
                    annotationValueFilter));
200
            annotationAppender = AnnotationAppender.ForTypeAnnotations.ofTypeVariable(annotationAppender,
1✔
201
                    annotationValueFilter,
202
                    AnnotationAppender.ForTypeAnnotations.VARIABLE_ON_INVOKEABLE,
203
                    methodDescription.getTypeVariables());
1✔
204
            for (AnnotationDescription annotation : methodDescription.getDeclaredAnnotations().filter(not(annotationType(nameStartsWith("jdk.internal."))))) {
1✔
205
                annotationAppender = annotationAppender.append(annotation, annotationValueFilter);
1✔
206
            }
1✔
207
            for (ParameterDescription parameterDescription : methodDescription.getParameters()) {
1✔
208
                AnnotationAppender parameterAppender = new AnnotationAppender.Default(new AnnotationAppender.Target.OnMethodParameter(methodVisitor,
1✔
209
                        parameterDescription.getIndex()));
1✔
210
                parameterAppender = parameterDescription.getType().accept(AnnotationAppender.ForTypeAnnotations.ofMethodParameterType(parameterAppender,
1✔
211
                        annotationValueFilter,
212
                        parameterDescription.getIndex()));
1✔
213
                for (AnnotationDescription annotation : parameterDescription.getDeclaredAnnotations()) {
1✔
214
                    parameterAppender = parameterAppender.append(annotation, annotationValueFilter);
1✔
215
                }
1✔
216
            }
1✔
217
            annotationAppender = appendReceiver(annotationAppender, annotationValueFilter, methodDescription);
1✔
218
            int exceptionTypeIndex = 0;
1✔
219
            for (TypeDescription.Generic exceptionType : methodDescription.getExceptionTypes()) {
1✔
220
                annotationAppender = exceptionType.accept(AnnotationAppender.ForTypeAnnotations.ofExceptionType(annotationAppender,
1✔
221
                        annotationValueFilter,
222
                        exceptionTypeIndex++));
223
            }
1✔
224
        }
1✔
225

226
        /**
227
         * Appends the annotations of the instrumented method's receiver type if this is enabled and such a type exists.
228
         *
229
         * @param annotationAppender    The annotation appender to use.
230
         * @param annotationValueFilter The annotation value filter to apply when the annotations are written.
231
         * @param methodDescription     The instrumented method.
232
         * @return The resulting annotation appender.
233
         */
234
        protected abstract AnnotationAppender appendReceiver(AnnotationAppender annotationAppender,
235
                                                             AnnotationValueFilter annotationValueFilter,
236
                                                             MethodDescription methodDescription);
237
    }
238

239
    /**
240
     * Appends an annotation to a method or method parameter. The visibility of the annotation is determined by the
241
     * annotation type's {@link java.lang.annotation.RetentionPolicy} annotation.
242
     */
243
    @HashCodeAndEqualsPlugin.Enhance
244
    class Explicit implements MethodAttributeAppender, Factory {
245

246
        /**
247
         * The target to which the annotations are written to.
248
         */
249
        private final Target target;
250

251
        /**
252
         * the annotations this method attribute appender is writing to its target.
253
         */
254
        private final List<? extends AnnotationDescription> annotations;
255

256
        /**
257
         * Creates a new appender for appending an annotation to a method.
258
         *
259
         * @param parameterIndex The index of the parameter to which the annotations should be written.
260
         * @param annotations    The annotations that should be written.
261
         */
262
        public Explicit(int parameterIndex, List<? extends AnnotationDescription> annotations) {
263
            this(new Target.OnMethodParameter(parameterIndex), annotations);
1✔
264
        }
1✔
265

266
        /**
267
         * Creates a new appender for appending an annotation to a method.
268
         *
269
         * @param annotations The annotations that should be written.
270
         */
271
        public Explicit(List<? extends AnnotationDescription> annotations) {
272
            this(Target.OnMethod.INSTANCE, annotations);
1✔
273
        }
1✔
274

275
        /**
276
         * Creates an explicit annotation appender for a either a method or one of its parameters..
277
         *
278
         * @param target      The target to which the annotation should be written to.
279
         * @param annotations The annotations to write.
280
         */
281
        protected Explicit(Target target, List<? extends AnnotationDescription> annotations) {
1✔
282
            this.target = target;
1✔
283
            this.annotations = annotations;
1✔
284
        }
1✔
285

286
        /**
287
         * Creates a method attribute appender factory that writes all annotations of a given method, both the method
288
         * annotations themselves and all annotations that are defined for every parameter.
289
         *
290
         * @param methodDescription The method from which to extract the annotations.
291
         * @return A method attribute appender factory for an appender that writes all annotations of the supplied method.
292
         */
293
        public static Factory of(MethodDescription methodDescription) {
294
            return new Factory.Compound(ofMethodAnnotations(methodDescription), ofParameterAnnotations(methodDescription));
1✔
295
        }
296

297
        /**
298
         * Creates a method attribute appender factory that writes all method annotations that are defined on the given method.
299
         *
300
         * @param methodDescription The method from which to extract the method annotations.
301
         * @return A method attribute appender factory for an appender that writes all method annotations of the supplied method.
302
         */
303
        public static Factory ofMethodAnnotations(MethodDescription methodDescription) {
304
            return new Explicit(methodDescription.getDeclaredAnnotations());
1✔
305
        }
306

307
        /**
308
         * Creates a method attribute appender factory that writes all annotations that are defined for every parameter
309
         * of the given method.
310
         *
311
         * @param methodDescription The method from which to extract the parameter annotations.
312
         * @return A method attribute appender factory for an appender that writes all parameter annotations of the supplied method.
313
         */
314
        public static Factory ofParameterAnnotations(MethodDescription methodDescription) {
315
            ParameterList<?> parameters = methodDescription.getParameters();
1✔
316
            List<MethodAttributeAppender.Factory> factories = new ArrayList<MethodAttributeAppender.Factory>(parameters.size());
1✔
317
            for (ParameterDescription parameter : parameters) {
1✔
318
                factories.add(new Explicit(parameter.getIndex(), parameter.getDeclaredAnnotations()));
1✔
319
            }
1✔
320
            return new Factory.Compound(factories);
1✔
321
        }
322

323
        /**
324
         * {@inheritDoc}
325
         */
326
        public MethodAttributeAppender make(TypeDescription typeDescription) {
327
            return this;
1✔
328
        }
329

330
        /**
331
         * {@inheritDoc}
332
         */
333
        public void apply(MethodVisitor methodVisitor, MethodDescription methodDescription, AnnotationValueFilter annotationValueFilter) {
334
            AnnotationAppender appender = new AnnotationAppender.Default(target.make(methodVisitor, methodDescription));
1✔
335
            for (AnnotationDescription annotation : annotations) {
1✔
336
                appender = appender.append(annotation, annotationValueFilter);
1✔
337
            }
1✔
338
        }
1✔
339

340
        /**
341
         * Represents the target on which this method attribute appender should write its annotations to.
342
         */
343
        protected interface Target {
344

345
            /**
346
             * Materializes the target for a given creation process.
347
             *
348
             * @param methodVisitor     The method visitor to which the attributes that are represented by this
349
             *                          attribute appender are written to.
350
             * @param methodDescription The description of the method for which the given method visitor creates an
351
             *                          instrumentation for.
352
             * @return The target of the annotation appender this target represents.
353
             */
354
            AnnotationAppender.Target make(MethodVisitor methodVisitor, MethodDescription methodDescription);
355

356
            /**
357
             * A method attribute appender target for writing annotations directly onto the method.
358
             */
359
            enum OnMethod implements Target {
1✔
360

361
                /**
362
                 * The singleton instance.
363
                 */
364
                INSTANCE;
1✔
365

366
                /**
367
                 * {@inheritDoc}
368
                 */
369
                public AnnotationAppender.Target make(MethodVisitor methodVisitor, MethodDescription methodDescription) {
370
                    return new AnnotationAppender.Target.OnMethod(methodVisitor);
1✔
371
                }
372
            }
373

374
            /**
375
             * A method attribute appender target for writing annotations onto a given method parameter.
376
             */
377
            @HashCodeAndEqualsPlugin.Enhance
378
            class OnMethodParameter implements Target {
379

380
                /**
381
                 * The index of the parameter to write the annotation to.
382
                 */
383
                private final int parameterIndex;
384

385
                /**
386
                 * Creates a target for a method attribute appender for a method parameter of the given index.
387
                 *
388
                 * @param parameterIndex The index of the target parameter.
389
                 */
390
                protected OnMethodParameter(int parameterIndex) {
1✔
391
                    this.parameterIndex = parameterIndex;
1✔
392
                }
1✔
393

394
                /**
395
                 * {@inheritDoc}
396
                 */
397
                public AnnotationAppender.Target make(MethodVisitor methodVisitor, MethodDescription methodDescription) {
398
                    if (parameterIndex >= methodDescription.getParameters().size()) {
1✔
399
                        throw new IllegalArgumentException("Method " + methodDescription + " has less then " + parameterIndex + " parameters");
1✔
400
                    }
401
                    return new AnnotationAppender.Target.OnMethodParameter(methodVisitor, parameterIndex);
1✔
402
                }
403
            }
404
        }
405
    }
406

407
    /**
408
     * A method attribute appender that writes a receiver type.
409
     */
410
    @HashCodeAndEqualsPlugin.Enhance
411
    class ForReceiverType implements MethodAttributeAppender, Factory {
412

413
        /**
414
         * The receiver type for which annotations are appended to the instrumented method.
415
         */
416
        private final TypeDescription.Generic receiverType;
417

418
        /**
419
         * Creates a new attribute appender that writes a receiver type.
420
         *
421
         * @param receiverType The receiver type for which annotations are appended to the instrumented method.
422
         */
423
        public ForReceiverType(TypeDescription.Generic receiverType) {
1✔
424
            this.receiverType = receiverType;
1✔
425
        }
1✔
426

427
        /**
428
         * {@inheritDoc}
429
         */
430
        public MethodAttributeAppender make(TypeDescription typeDescription) {
431
            return this;
1✔
432
        }
433

434
        /**
435
         * {@inheritDoc}
436
         */
437
        public void apply(MethodVisitor methodVisitor, MethodDescription methodDescription, AnnotationValueFilter annotationValueFilter) {
438
            receiverType.accept(AnnotationAppender.ForTypeAnnotations.ofReceiverType(new AnnotationAppender.Default(new AnnotationAppender.Target.OnMethod(methodVisitor)), annotationValueFilter));
1✔
439
        }
1✔
440
    }
441

442
    /**
443
     * A method attribute appender that combines several method attribute appenders to be represented as a single
444
     * method attribute appender.
445
     */
446
    @HashCodeAndEqualsPlugin.Enhance
447
    class Compound implements MethodAttributeAppender {
448

449
        /**
450
         * The method attribute appenders this compound appender represents in their application order.
451
         */
452
        private final List<MethodAttributeAppender> methodAttributeAppenders;
453

454
        /**
455
         * Creates a new compound method attribute appender.
456
         *
457
         * @param methodAttributeAppender The method attribute appenders that are to be combined by this compound appender
458
         *                                in the order of their application.
459
         */
460
        public Compound(MethodAttributeAppender... methodAttributeAppender) {
461
            this(Arrays.asList(methodAttributeAppender));
1✔
462
        }
1✔
463

464
        /**
465
         * Creates a new compound method attribute appender.
466
         *
467
         * @param methodAttributeAppenders The method attribute appenders that are to be combined by this compound appender
468
         *                                 in the order of their application.
469
         */
470
        public Compound(List<? extends MethodAttributeAppender> methodAttributeAppenders) {
1✔
471
            this.methodAttributeAppenders = new ArrayList<MethodAttributeAppender>();
1✔
472
            for (MethodAttributeAppender methodAttributeAppender : methodAttributeAppenders) {
1✔
473
                if (methodAttributeAppender instanceof Compound) {
1✔
474
                    this.methodAttributeAppenders.addAll(((Compound) methodAttributeAppender).methodAttributeAppenders);
×
475
                } else if (!(methodAttributeAppender instanceof NoOp)) {
1✔
476
                    this.methodAttributeAppenders.add(methodAttributeAppender);
1✔
477
                }
478
            }
1✔
479
        }
1✔
480

481
        /**
482
         * {@inheritDoc}
483
         */
484
        public void apply(MethodVisitor methodVisitor, MethodDescription methodDescription, AnnotationValueFilter annotationValueFilter) {
485
            for (MethodAttributeAppender methodAttributeAppender : methodAttributeAppenders) {
1✔
486
                methodAttributeAppender.apply(methodVisitor, methodDescription, annotationValueFilter);
1✔
487
            }
1✔
488
        }
1✔
489
    }
490
}
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