• 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

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

18
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19
import net.bytebuddy.description.field.FieldDescription;
20
import net.bytebuddy.description.method.MethodDescription;
21
import net.bytebuddy.description.method.MethodList;
22
import net.bytebuddy.description.type.TypeDefinition;
23
import net.bytebuddy.description.type.TypeDescription;
24
import net.bytebuddy.dynamic.scaffold.FieldLocator;
25
import net.bytebuddy.dynamic.scaffold.InstrumentedType;
26
import net.bytebuddy.dynamic.scaffold.MethodGraph;
27
import net.bytebuddy.implementation.bind.MethodDelegationBinder;
28
import net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder;
29
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
30
import net.bytebuddy.implementation.bytecode.Duplication;
31
import net.bytebuddy.implementation.bytecode.StackManipulation;
32
import net.bytebuddy.implementation.bytecode.TypeCreation;
33
import net.bytebuddy.implementation.bytecode.assign.Assigner;
34
import net.bytebuddy.implementation.bytecode.member.FieldAccess;
35
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
36
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
37
import net.bytebuddy.matcher.ElementMatcher;
38
import net.bytebuddy.utility.CompoundList;
39
import net.bytebuddy.utility.RandomString;
40
import org.objectweb.asm.MethodVisitor;
41
import org.objectweb.asm.Opcodes;
42

43
import java.lang.reflect.Type;
44
import java.util.ArrayList;
45
import java.util.Arrays;
46
import java.util.Collections;
47
import java.util.List;
48

49
import static net.bytebuddy.matcher.ElementMatchers.any;
50
import static net.bytebuddy.matcher.ElementMatchers.fieldType;
51
import static net.bytebuddy.matcher.ElementMatchers.isArray;
52
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
53
import static net.bytebuddy.matcher.ElementMatchers.isPrimitive;
54
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
55
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
56
import static net.bytebuddy.matcher.ElementMatchers.named;
57
import static net.bytebuddy.matcher.ElementMatchers.not;
58
import static net.bytebuddy.matcher.ElementMatchers.returns;
59
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
60

61
/**
62
 * This implementation delegates a method call to another method which can either be {@code static} by providing
63
 * a reference to a {@link java.lang.Class} or an instance method when another object is provided. The potential
64
 * targets of the method delegation can further be filtered by applying a filter. The method delegation can be
65
 * customized by invoking the {@code MethodDelegation}'s several builder methods.
66
 * <p>&nbsp;</p>
67
 * <b>Without any customization, the method delegation will work as follows:</b>
68
 * <p>&nbsp;</p>
69
 * <span style="text-decoration: underline">Binding an instrumented method to a given delegate method</span>
70
 * <p>&nbsp;</p>
71
 * A method will be bound parameter by parameter. Considering a method {@code Foo#bar} being bound to a method
72
 * {@code Qux#baz}, the method delegation will be decided on basis of the following annotations:
73
 * <ul>
74
 * <li>{@link net.bytebuddy.implementation.bind.annotation.Argument}:
75
 * This annotation will bind the {@code n}-th parameter of {@code Foo#bar} to that parameter of {@code Qux#baz}that
76
 * is annotated with this annotation where {@code n} is the obligatory argument of the {@code @Argument} annotation.</li>
77
 * <li>{@link net.bytebuddy.implementation.bind.annotation.AllArguments}:
78
 * This annotation will assign a collection of all parameters of {@code Foo#bar} to that parameter of {@code Qux#baz}
79
 * that is annotated with {@code AllArguments}.</li>
80
 * <li>{@link net.bytebuddy.implementation.bind.annotation.This}: A parameter
81
 * of {@code Qux#baz} that is annotated with {@code This} will be assigned the instance that is instrumented for
82
 * a non-static method.</li>
83
 * <li>{@link net.bytebuddy.implementation.bind.annotation.Super}: A parameter that is annotated with
84
 * this annotation is assigned a proxy that allows calling an instrumented type's super methods.</li>
85
 * <li>{@link net.bytebuddy.implementation.bind.annotation.Default}: A parameter that is annotated with
86
 * this annotation is assigned a proxy that allows calling an instrumented type's directly implemented interfaces'
87
 * default methods.</li>
88
 * <li>{@link net.bytebuddy.implementation.bind.annotation.SuperCall}: A parameter
89
 * of {@code Qux#baz} that is annotated with {@code SuperCall} will be assigned an instance of a type implementing both
90
 * {@link java.lang.Runnable} and {@link java.util.concurrent.Callable} which will invoke the instrumented method on the
91
 * invocation of either interface's method. The call is made using the original arguments of the method invocation.
92
 * The return value is only emitted for the {@link java.util.concurrent.Callable#call()} method which additionally
93
 * requires to catch any unchecked exceptions that might be thrown by the original method's implementation. If a
94
 * source method is abstract, using this annotation excludes the method with this parameter annotation from being bound
95
 * to this source method.
96
 * </li>
97
 * <li>{@link net.bytebuddy.implementation.bind.annotation.DefaultCall}:
98
 * This annotation is similar to the {@link net.bytebuddy.implementation.bind.annotation.SuperCall}
99
 * annotation but it invokes a default method that is compatible to this method. If a source method does not represent
100
 * a default method, using this annotation excludes the method with this parameter annotation from being bound to this
101
 * source method. For using method handles, the {@link net.bytebuddy.implementation.bind.annotation.SuperCallHandle}
102
 * and {@link net.bytebuddy.implementation.bind.annotation.DefaultCallHandle} annotations can be used.</li>
103
 * <li>The {@link net.bytebuddy.implementation.bind.annotation.SuperMethod} or
104
 * {@link net.bytebuddy.implementation.bind.annotation.DefaultMethod} annotations can be used on any parameter type
105
 * that is assignable from the {@link java.lang.reflect.Method} type. the parameter is bound a method instance that
106
 * allows for the reflective invocation of a super or default method. Note that this method is not equal to the intercepted
107
 * method but represents a synthetic accessor method. Using this annotation also causes this accessor to be {@code public}
108
 * which allows its outside invocation without any access checks by a security manager. For using method handles, the
109
 * {@link net.bytebuddy.implementation.bind.annotation.SuperCallHandle} and
110
 * {@link net.bytebuddy.implementation.bind.annotation.DefaultCallHandle} annotations can be used.</li>
111
 * <li>{@link net.bytebuddy.implementation.bind.annotation.Origin}: A parameter of
112
 * {@code Qux#baz} that is annotated with {@code Origin} is assigned a reference to either a {@link java.lang.reflect.Method},
113
 * a {@link java.lang.reflect.Constructor}, a {@code java.lang.reflect.Executable} or a {@link java.lang.Class} instance.
114
 * A {@code Method}-typed, {@code Constructor} or {@code Executable} parameter is assigned a reference to the original
115
 * method that is instrumented. A {@code Class}-typed parameter is assigned the type of the caller. Furthermore, {@code MethodType}
116
 * and {@code MethodHandle} parameters are also supported. When using the annotation on a {@link java.lang.String} type,
117
 * the intercepted method's {@code toString} value is injected. The same holds for a parameter of type {@code int} that receives
118
 * the modifiers of the instrumented method.</li>
119
 * <li>{@link net.bytebuddy.implementation.bind.annotation.StubValue}: Assigns the (boxed) default value of the
120
 * intercepted method's return type to the parameter. If the return type is {@code void}, {@code null} is assigned.</li>
121
 * <li>{@link net.bytebuddy.implementation.bind.annotation.Empty}: Assigns the parameter type's
122
 * default value, i.e. {@code null} for a reference type or zero for primitive types. This is an opportunity to
123
 * ignore a parameter.</li>
124
 * <li>{@link net.bytebuddy.implementation.bind.annotation.Pipe}: A parameter that is annotated
125
 * with this annotation is assigned a proxy for forwarding the source method invocation to another instance of the
126
 * same type as the declaring type of the intercepted method. <b>This annotation needs to be installed and explicitly
127
 * registered before it can be used.</b> See the {@link net.bytebuddy.implementation.bind.annotation.Pipe}
128
 * annotation's documentation for further information on how this can be done.</li>
129
 * <li>{@link net.bytebuddy.implementation.bind.annotation.Morph}: The morph annotation is similar to
130
 * the {@link net.bytebuddy.implementation.bind.annotation.SuperCall} annotation but allows to
131
 * explicitly define and therewith alter the arguments that are handed to the super method. <b>This annotation needs
132
 * to be installed and explicitly registered before it can be used.</b> See the documentation to the annotation for
133
 * further information.</li>
134
 * <li>{@link net.bytebuddy.implementation.bind.annotation.FieldValue}: Allows to access a field's value at the time
135
 * of the method invocation. The field's value is directly assigned to the annotated parameter.</li>
136
 * <li>{@link net.bytebuddy.implementation.bind.annotation.FieldProxy}: Allows to access fields via getter
137
 * and setter proxies. <b>This annotation needs to be installed and explicitly registered before it can be used.</b>
138
 * Note that any field access requires boxing such that a use of {@link net.bytebuddy.implementation.FieldAccessor} in
139
 * combination with {@link net.bytebuddy.implementation.MethodDelegation#andThen(Implementation)} might be a more
140
 * performant alternative for implementing field getters and setters.</li>
141
 * </ul>
142
 * If a method is not annotated with any of the above methods, it will be treated as if it was annotated
143
 * {@link net.bytebuddy.implementation.bind.annotation.Argument} using the next
144
 * unbound parameter index of the source method as its parameter. This means that a method
145
 * {@code Qux#baz(@Argument(2) Object p1, Object p2, @Argument(0) Object p3} would be treated as if {@code p2} was annotated
146
 * with {@code @Argument(1)}.
147
 * <p>&nbsp;</p>
148
 * In addition, the {@link net.bytebuddy.implementation.bind.annotation.RuntimeType}
149
 * annotation can instruct a parameter to be bound by a
150
 * {@link net.bytebuddy.implementation.bytecode.assign.Assigner} with considering the
151
 * runtime type of the parameter.
152
 * <p>&nbsp;</p>
153
 * <span style="text-decoration: underline">Selecting among different methods that can be used for binding a method
154
 * of the instrumented type</span>
155
 * <p>&nbsp;</p>
156
 * When deciding between two methods {@code Foo#bar} and {@code Foo#qux} that could both be used to delegating a
157
 * method call, the following consideration is applied in the given order:
158
 * <ol>
159
 * <li>{@link net.bytebuddy.implementation.bind.annotation.BindingPriority}:
160
 * A method that is annotated with this annotation is given a specific priority where the default priority is set
161
 * to {@link net.bytebuddy.implementation.bind.annotation.BindingPriority#DEFAULT}
162
 * for non-annotated method. A method with a higher priority is considered a better target for delegation.</li>
163
 * <li>{@link net.bytebuddy.implementation.bind.DeclaringTypeResolver}:
164
 * If a target method is declared by a more specific type than another method, the method with the most specific
165
 * type is bound.</li>
166
 * <li>{@link net.bytebuddy.implementation.bind.MethodNameEqualityResolver}:
167
 * If a source method {@code Baz#qux} is the source method, it will rather be assigned to {@code Foo#qux} because
168
 * of their equal names. Similar names and case-insensitive equality are not considered.</li>
169
 * <li>{@link net.bytebuddy.implementation.bind.ArgumentTypeResolver}:
170
 * The most specific type resolver will consider all bindings that are using the
171
 * {@link net.bytebuddy.implementation.bind.annotation.Argument}
172
 * annotation for resolving a binding conflict. In this context, the resolution will equal the most-specific
173
 * type resolution that is performed by the Java compiler. This means that a source method {@code Bar#baz(String)}
174
 * will rather be bound to a method {@code Foo#bar(String)} than {@code Foo#qux(Object)} because the {@code String}
175
 * type is more specific than the {@code Object} type. If two methods are equally adequate by their parameter types,
176
 * then the method with the higher numbers of {@code @Argument} annotated parameters is considered as the better
177
 * delegation target.</li>
178
 * <li>{@link net.bytebuddy.implementation.bind.ParameterLengthResolver}:
179
 * If a target methods has a higher number of total parameters that were successfully bound, the method with
180
 * the higher number will be considered as the better delegation target.</li>
181
 * </ol>
182
 * <p>
183
 * Additionally, if a method is annotated by
184
 * {@link net.bytebuddy.implementation.bind.annotation.IgnoreForBinding},
185
 * it is never considered as a target for a method delegation.
186
 * </p>
187
 * <p>
188
 * <b>Important</b>: For invoking a method on another instance, use the {@link MethodCall} implementation. A method delegation
189
 * intends to bind a interceptor class and its resolution algorithm will not necessarily yield a delegation to the intercepted
190
 * method.
191
 * </p>
192
 *
193
 * @see MethodCall
194
 * @see net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder.ForFixedValue
195
 */
196
@HashCodeAndEqualsPlugin.Enhance
197
public class MethodDelegation implements Implementation.Composable {
198

199
    /**
200
     * The implementation delegate for this method delegation.
201
     */
202
    private final ImplementationDelegate implementationDelegate;
203

204
    /**
205
     * A list of {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder}s
206
     * to be used by this method delegation.
207
     */
208
    private final List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
209

210
    /**
211
     * The {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver}
212
     * to be used by this method delegation.
213
     */
214
    private final MethodDelegationBinder.AmbiguityResolver ambiguityResolver;
215

216
    /**
217
     * The termination handler to apply.
218
     */
219
    private final TargetMethodAnnotationDrivenBinder.TerminationHandler terminationHandler;
220

221
    /**
222
     * The binding resolver being used to select the relevant method binding.
223
     */
224
    private final MethodDelegationBinder.BindingResolver bindingResolver;
225

226
    /**
227
     * The {@link net.bytebuddy.implementation.bytecode.assign.Assigner} to be used by this method delegation.
228
     */
229
    private final Assigner assigner;
230

231
    /**
232
     * Creates a new method delegation.
233
     *
234
     * @param implementationDelegate The implementation delegate to use by this method delegator.
235
     * @param parameterBinders       The parameter binders to use by this method delegator.
236
     * @param ambiguityResolver      The ambiguity resolver to use by this method delegator.
237
     * @param bindingResolver        The binding resolver being used to select the relevant method binding.
238
     */
239
    protected MethodDelegation(ImplementationDelegate implementationDelegate,
240
                               List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
241
                               MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
242
                               MethodDelegationBinder.BindingResolver bindingResolver) {
243
        this(implementationDelegate,
1✔
244
                parameterBinders,
245
                ambiguityResolver,
246
                MethodDelegationBinder.TerminationHandler.Default.RETURNING,
247
                bindingResolver,
248
                Assigner.DEFAULT);
249
    }
1✔
250

251
    /**
252
     * Creates a new method delegation.
253
     *
254
     * @param implementationDelegate The implementation delegate to use by this method delegator.
255
     * @param parameterBinders       The parameter binders to use by this method delegator.
256
     * @param ambiguityResolver      The ambiguity resolver to use by this method delegator.
257
     * @param terminationHandler     The termination handler to apply.
258
     * @param bindingResolver        The binding resolver being used to select the relevant method binding.
259
     * @param assigner               The assigner to be supplied by this method delegator.
260
     */
261
    private MethodDelegation(ImplementationDelegate implementationDelegate,
262
                             List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
263
                             MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
264
                             TargetMethodAnnotationDrivenBinder.TerminationHandler terminationHandler,
265
                             MethodDelegationBinder.BindingResolver bindingResolver,
266
                             Assigner assigner) {
1✔
267
        this.implementationDelegate = implementationDelegate;
1✔
268
        this.parameterBinders = parameterBinders;
1✔
269
        this.terminationHandler = terminationHandler;
1✔
270
        this.ambiguityResolver = ambiguityResolver;
1✔
271
        this.bindingResolver = bindingResolver;
1✔
272
        this.assigner = assigner;
1✔
273
    }
1✔
274

275
    /**
276
     * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
277
     * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
278
     * the target type is either public or in the same package as the instrumented type and if the target method is either public
279
     * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
280
     * the interception is targeting the instrumented type.
281
     *
282
     * @param type The target type for the delegation.
283
     * @return A method delegation that redirects method calls to a static method of the supplied type.
284
     */
285
    public static MethodDelegation to(Class<?> type) {
286
        return withDefaultConfiguration().to(type);
1✔
287
    }
288

289
    /**
290
     * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
291
     * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
292
     * the target type is either public or in the same package as the instrumented type and if the target method is either public
293
     * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
294
     * the interception is targeting the instrumented type.
295
     *
296
     * @param typeDescription The target type for the delegation.
297
     * @return A method delegation that redirects method calls to a static method of the supplied type.
298
     */
299
    public static MethodDelegation to(TypeDescription typeDescription) {
300
        return withDefaultConfiguration().to(typeDescription);
×
301
    }
302

303
    /**
304
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
305
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
306
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
307
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
308
     * a delegation target if the delegation is targeting the instrumented type.
309
     *
310
     * @param target The target instance for the delegation.
311
     * @return A method delegation that redirects method calls to a static method of the supplied type.
312
     */
313
    public static MethodDelegation to(Object target) {
314
        return withDefaultConfiguration().to(target);
1✔
315
    }
316

317
    /**
318
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
319
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
320
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
321
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
322
     * a delegation target if the delegation is targeting the instrumented type.
323
     *
324
     * @param target              The target instance for the delegation.
325
     * @param methodGraphCompiler The method graph compiler to use.
326
     * @return A method delegation that redirects method calls to a static method of the supplied type.
327
     */
328
    public static MethodDelegation to(Object target, MethodGraph.Compiler methodGraphCompiler) {
329
        return withDefaultConfiguration().to(target, methodGraphCompiler);
×
330
    }
331

332
    /**
333
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
334
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
335
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
336
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
337
     * a delegation target if the delegation is targeting the instrumented type.
338
     *
339
     * @param target    The target instance for the delegation.
340
     * @param fieldName The name of the field that is holding the {@code target} instance.
341
     * @return A method delegation that redirects method calls to a static method of the supplied type.
342
     */
343
    public static MethodDelegation to(Object target, String fieldName) {
344
        return withDefaultConfiguration().to(target, fieldName);
×
345
    }
346

347
    /**
348
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
349
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
350
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
351
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
352
     * a delegation target if the delegation is targeting the instrumented type.
353
     *
354
     * @param target              The target instance for the delegation.
355
     * @param fieldName           The name of the field that is holding the {@code target} instance.
356
     * @param methodGraphCompiler The method graph compiler to use.
357
     * @return A method delegation that redirects method calls to a static method of the supplied type.
358
     */
359
    public static MethodDelegation to(Object target, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
360
        return withDefaultConfiguration().to(target, fieldName, methodGraphCompiler);
×
361
    }
362

363
    /**
364
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
365
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
366
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
367
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
368
     * a delegation target if the delegation is targeting the instrumented type.
369
     *
370
     * @param target The target instance for the delegation.
371
     * @param type   The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
372
     * @return A method delegation that redirects method calls to a static method of the supplied type.
373
     */
374
    public static MethodDelegation to(Object target, Type type) {
375
        return withDefaultConfiguration().to(target, type);
×
376
    }
377

378
    /**
379
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
380
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
381
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
382
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
383
     * a delegation target if the delegation is targeting the instrumented type.
384
     *
385
     * @param target              The target instance for the delegation.
386
     * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
387
     * @param methodGraphCompiler The method graph compiler to use.
388
     * @return A method delegation that redirects method calls to a static method of the supplied type.
389
     */
390
    public static MethodDelegation to(Object target, Type type, MethodGraph.Compiler methodGraphCompiler) {
391
        return withDefaultConfiguration().to(target, type, methodGraphCompiler);
×
392
    }
393

394
    /**
395
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
396
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
397
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
398
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
399
     * a delegation target if the delegation is targeting the instrumented type.
400
     *
401
     * @param target    The target instance for the delegation.
402
     * @param type      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
403
     * @param fieldName The name of the field that is holding the {@code target} instance.
404
     * @return A method delegation that redirects method calls to a static method of the supplied type.
405
     */
406
    public static MethodDelegation to(Object target, Type type, String fieldName) {
407
        return withDefaultConfiguration().to(target, type, fieldName);
×
408
    }
409

410
    /**
411
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
412
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
413
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
414
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
415
     * a delegation target if the delegation is targeting the instrumented type.
416
     *
417
     * @param target              The target instance for the delegation.
418
     * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
419
     * @param fieldName           The name of the field that is holding the {@code target} instance.
420
     * @param methodGraphCompiler The method graph compiler to use.
421
     * @return A method delegation that redirects method calls to a static method of the supplied type.
422
     */
423
    public static MethodDelegation to(Object target, Type type, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
424
        return withDefaultConfiguration().to(target, type, fieldName, methodGraphCompiler);
×
425
    }
426

427
    /**
428
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
429
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
430
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
431
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
432
     * a delegation target if the delegation is targeting the instrumented type.
433
     *
434
     * @param target         The target instance for the delegation.
435
     * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
436
     * @return A method delegation that redirects method calls to a static method of the supplied type.
437
     */
438
    public static MethodDelegation to(Object target, TypeDefinition typeDefinition) {
439
        return withDefaultConfiguration().to(target, typeDefinition);
×
440
    }
441

442
    /**
443
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
444
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
445
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
446
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
447
     * a delegation target if the delegation is targeting the instrumented type.
448
     *
449
     * @param target              The target instance for the delegation.
450
     * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
451
     * @param methodGraphCompiler The method graph compiler to use.
452
     * @return A method delegation that redirects method calls to a static method of the supplied type.
453
     */
454
    public static MethodDelegation to(Object target, TypeDefinition typeDefinition, MethodGraph.Compiler methodGraphCompiler) {
455
        return withDefaultConfiguration().to(target, typeDefinition, methodGraphCompiler);
×
456
    }
457

458
    /**
459
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
460
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
461
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
462
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
463
     * a delegation target if the delegation is targeting the instrumented type.
464
     *
465
     * @param target         The target instance for the delegation.
466
     * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
467
     * @param fieldName      The name of the field that is holding the {@code target} instance.
468
     * @return A method delegation that redirects method calls to a static method of the supplied type.
469
     */
470
    public static MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName) {
471
        return withDefaultConfiguration().to(target, typeDefinition, fieldName);
×
472
    }
473

474
    /**
475
     * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
476
     * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
477
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
478
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
479
     * a delegation target if the delegation is targeting the instrumented type.
480
     *
481
     * @param target              The target instance for the delegation.
482
     * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
483
     * @param fieldName           The name of the field that is holding the {@code target} instance.
484
     * @param methodGraphCompiler The method graph compiler to use.
485
     * @return A method delegation that redirects method calls to a static method of the supplied type.
486
     */
487
    public static MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
488
        return withDefaultConfiguration().to(target, typeDefinition, fieldName, methodGraphCompiler);
×
489
    }
490

491
    /**
492
     * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
493
     * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
494
     * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
495
     * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
496
     * targeting the instrumented type.
497
     *
498
     * @param type The type to construct.
499
     * @return A delegation that redirects method calls to a constructor of the supplied type.
500
     */
501
    public static MethodDelegation toConstructor(Class<?> type) {
502
        return withDefaultConfiguration().toConstructor(type);
1✔
503
    }
504

505
    /**
506
     * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
507
     * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
508
     * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
509
     * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
510
     * targeting the instrumented type.
511
     *
512
     * @param typeDescription The type to construct.
513
     * @return A delegation that redirects method calls to a constructor of the supplied type.
514
     */
515
    public static MethodDelegation toConstructor(TypeDescription typeDescription) {
516
        return withDefaultConfiguration().toConstructor(typeDescription);
×
517
    }
518

519
    /**
520
     * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
521
     * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
522
     * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
523
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
524
     * a delegation target if the delegation is targeting the instrumented type.
525
     *
526
     * @param name The field's name.
527
     * @return A delegation that redirects invocations to a method of the specified field's instance.
528
     */
529
    public static MethodDelegation toField(String name) {
530
        return withDefaultConfiguration().toField(name);
1✔
531
    }
532

533
    /**
534
     * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
535
     * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
536
     * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
537
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
538
     * a delegation target if the delegation is targeting the instrumented type.
539
     *
540
     * @param name                The field's name.
541
     * @param fieldLocatorFactory The field locator factory to use.
542
     * @return A delegation that redirects invocations to a method of the specified field's instance.
543
     */
544
    public static MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory) {
545
        return withDefaultConfiguration().toField(name, fieldLocatorFactory);
×
546
    }
547

548
    /**
549
     * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
550
     * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
551
     * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
552
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
553
     * a delegation target if the delegation is targeting the instrumented type.
554
     *
555
     * @param name                The field's name.
556
     * @param methodGraphCompiler The method graph compiler to use.
557
     * @return A delegation that redirects invocations to a method of the specified field's instance.
558
     */
559
    public static MethodDelegation toField(String name, MethodGraph.Compiler methodGraphCompiler) {
560
        return withDefaultConfiguration().toField(name, methodGraphCompiler);
×
561
    }
562

563
    /**
564
     * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
565
     * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
566
     * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
567
     * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
568
     * a delegation target if the delegation is targeting the instrumented type.
569
     *
570
     * @param name                The field's name.
571
     * @param fieldLocatorFactory The field locator factory to use.
572
     * @param methodGraphCompiler The method graph compiler to use.
573
     * @return A delegation that redirects invocations to a method of the specified field's instance.
574
     */
575
    public static MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory, MethodGraph.Compiler methodGraphCompiler) {
576
        return withDefaultConfiguration().toField(name, fieldLocatorFactory, methodGraphCompiler);
×
577
    }
578

579
    /**
580
     * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
581
     * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
582
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
583
     * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
584
     * be used as a delegation target if the delegation is targeting the instrumented type.
585
     *
586
     * @param name The name of the method that returns the delegation target.
587
     * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
588
     */
589
    public static MethodDelegation toMethodReturnOf(String name) {
590
        return withDefaultConfiguration().toMethodReturnOf(name);
1✔
591
    }
592

593
    /**
594
     * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
595
     * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
596
     * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
597
     * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
598
     * be used as a delegation target if the delegation is targeting the instrumented type.
599
     *
600
     * @param name                The name of the method that returns the delegation target.
601
     * @param methodGraphCompiler The method graph compiler to use.
602
     * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
603
     */
604
    public static MethodDelegation toMethodReturnOf(String name, MethodGraph.Compiler methodGraphCompiler) {
605
        return withDefaultConfiguration().toMethodReturnOf(name, methodGraphCompiler);
×
606
    }
607

608
    /**
609
     * Creates a configuration builder for a method delegation that is pre-configured with the ambiguity resolvers defined by
610
     * {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver#DEFAULT} and the parameter binders
611
     * defined by {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder#DEFAULTS}.
612
     *
613
     * @return A method delegation configuration with pre-configuration.
614
     */
615
    public static WithCustomProperties withDefaultConfiguration() {
616
        return new WithCustomProperties(MethodDelegationBinder.AmbiguityResolver.DEFAULT, TargetMethodAnnotationDrivenBinder.ParameterBinder.DEFAULTS);
1✔
617
    }
618

619
    /**
620
     * Creates a configuration builder for a method delegation that does not apply any pre-configured
621
     * {@link net.bytebuddy.implementation.bind.MethodDelegationBinder.AmbiguityResolver}s or
622
     * {@link net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder.ParameterBinder}s.
623
     *
624
     * @return A method delegation configuration without any pre-configuration.
625
     */
626
    public static WithCustomProperties withEmptyConfiguration() {
627
        return new WithCustomProperties(MethodDelegationBinder.AmbiguityResolver.NoOp.INSTANCE, Collections.<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>>emptyList());
1✔
628
    }
629

630
    /**
631
     * Applies an assigner to the method delegation that is used for assigning method return and parameter types.
632
     *
633
     * @param assigner The assigner to apply.
634
     * @return A method delegation implementation that makes use of the given designer.
635
     */
636
    public Implementation.Composable withAssigner(Assigner assigner) {
637
        return new MethodDelegation(implementationDelegate,
×
638
                parameterBinders,
639
                ambiguityResolver,
640
                terminationHandler,
641
                bindingResolver,
642
                assigner);
643
    }
644

645
    /**
646
     * {@inheritDoc}
647
     */
648
    public Implementation andThen(Implementation implementation) {
649
        return new Compound(new MethodDelegation(implementationDelegate,
1✔
650
                parameterBinders,
651
                ambiguityResolver,
652
                MethodDelegationBinder.TerminationHandler.Default.DROPPING,
653
                bindingResolver,
654
                assigner), implementation);
655
    }
656

657
    /**
658
     * {@inheritDoc}
659
     */
660
    public Composable andThen(Composable implementation) {
661
        return new Compound.Composable(new MethodDelegation(implementationDelegate,
×
662
                parameterBinders,
663
                ambiguityResolver,
664
                MethodDelegationBinder.TerminationHandler.Default.DROPPING,
665
                bindingResolver,
666
                assigner), implementation);
667
    }
668

669
    /**
670
     * {@inheritDoc}
671
     */
672
    public InstrumentedType prepare(InstrumentedType instrumentedType) {
673
        return implementationDelegate.prepare(instrumentedType);
1✔
674
    }
675

676
    /**
677
     * {@inheritDoc}
678
     */
679
    public ByteCodeAppender appender(Target implementationTarget) {
680
        ImplementationDelegate.Compiled compiled = implementationDelegate.compile(implementationTarget.getInstrumentedType());
1✔
681
        return new Appender(implementationTarget,
1✔
682
                new MethodDelegationBinder.Processor(compiled.getRecords(), ambiguityResolver, bindingResolver),
1✔
683
                terminationHandler,
684
                assigner,
685
                compiled);
686
    }
687

688
    /**
689
     * An implementation delegate is responsible for executing the actual method delegation and for resolving the target methods.
690
     */
691
    protected interface ImplementationDelegate extends InstrumentedType.Prepareable {
692

693
        /**
694
         * A name prefix for fields.
695
         */
696
        String FIELD_NAME_PREFIX = "delegate";
697

698
        /**
699
         * Compiles this implementation delegate.
700
         *
701
         * @param instrumentedType The instrumented type.
702
         * @return A compiled implementation delegate.
703
         */
704
        Compiled compile(TypeDescription instrumentedType);
705

706
        /**
707
         * A compiled implementation delegate.
708
         */
709
        interface Compiled {
710

711
            /**
712
             * Resolves a stack manipulation that prepares the delegation invocation.
713
             *
714
             * @param instrumentedMethod The instrumented method.
715
             * @return A stack manipulation that is applied prior to loading arguments and executing the method call.
716
             */
717
            StackManipulation prepare(MethodDescription instrumentedMethod);
718

719
            /**
720
             * Resolves an invoker to use for invoking the delegation target.
721
             *
722
             * @return The method invoker to use.
723
             */
724
            MethodDelegationBinder.MethodInvoker invoke();
725

726
            /**
727
             * Returns a list of binding records to consider for delegation.
728
             *
729
             * @return A list of delegation binder records to consider.
730
             */
731
            List<MethodDelegationBinder.Record> getRecords();
732

733
            /**
734
             * A compiled implementation delegate for invoking a static method.
735
             */
736
            @HashCodeAndEqualsPlugin.Enhance
737
            class ForStaticCall implements Compiled {
738

739
                /**
740
                 * The list of records to consider.
741
                 */
742
                private final List<MethodDelegationBinder.Record> records;
743

744
                /**
745
                 * Creates a new compiled implementation delegate for a static method call.
746
                 *
747
                 * @param records The list of records to consider.
748
                 */
749
                protected ForStaticCall(List<MethodDelegationBinder.Record> records) {
1✔
750
                    this.records = records;
1✔
751
                }
1✔
752

753
                /**
754
                 * {@inheritDoc}
755
                 */
756
                public StackManipulation prepare(MethodDescription instrumentedMethod) {
757
                    return StackManipulation.Trivial.INSTANCE;
1✔
758
                }
759

760
                /**
761
                 * {@inheritDoc}
762
                 */
763
                public MethodDelegationBinder.MethodInvoker invoke() {
764
                    return MethodDelegationBinder.MethodInvoker.Simple.INSTANCE;
1✔
765
                }
766

767
                /**
768
                 * {@inheritDoc}
769
                 */
770
                public List<MethodDelegationBinder.Record> getRecords() {
771
                    return records;
1✔
772
                }
773
            }
774

775
            /**
776
             * A compiled implementation delegate that invokes methods on a field.
777
             */
778
            @HashCodeAndEqualsPlugin.Enhance
779
            class ForField implements Compiled {
780

781
                /**
782
                 * The field to delegate to.
783
                 */
784
                private final FieldDescription fieldDescription;
785

786
                /**
787
                 * The records to consider for delegation.
788
                 */
789
                private final List<MethodDelegationBinder.Record> records;
790

791
                /**
792
                 * Creates a new compiled implementation delegate for a field delegation.
793
                 *
794
                 * @param fieldDescription The field to delegate to.
795
                 * @param records          The records to consider for delegation.
796
                 */
797
                protected ForField(FieldDescription fieldDescription, List<MethodDelegationBinder.Record> records) {
1✔
798
                    this.fieldDescription = fieldDescription;
1✔
799
                    this.records = records;
1✔
800
                }
1✔
801

802
                /**
803
                 * {@inheritDoc}
804
                 */
805
                public StackManipulation prepare(MethodDescription instrumentedMethod) {
806
                    if (instrumentedMethod.isStatic() && !fieldDescription.isStatic()) {
1✔
807
                        throw new IllegalStateException("Cannot read " + fieldDescription + " from " + instrumentedMethod);
1✔
808
                    }
809
                    return new StackManipulation.Compound(fieldDescription.isStatic()
1✔
810
                            ? StackManipulation.Trivial.INSTANCE
811
                            : MethodVariableAccess.loadThis(), FieldAccess.forField(fieldDescription).read());
1✔
812
                }
813

814
                /**
815
                 * {@inheritDoc}
816
                 */
817
                public MethodDelegationBinder.MethodInvoker invoke() {
818
                    return new MethodDelegationBinder.MethodInvoker.Virtual(fieldDescription.getType().asErasure());
1✔
819
                }
820

821
                /**
822
                 * {@inheritDoc}
823
                 */
824
                public List<MethodDelegationBinder.Record> getRecords() {
825
                    return records;
1✔
826
                }
827
            }
828

829
            /**
830
             * A compiled implementation delegate that invokes a method on an instance that is returned by another method.
831
             */
832
            @HashCodeAndEqualsPlugin.Enhance
833
            class ForMethodReturn implements Compiled {
834

835
                /**
836
                 * The method to call for result.
837
                 */
838
                private final MethodDescription methodDescription;
839

840
                /**
841
                 * The records to consider for delegation.
842
                 */
843
                private final List<MethodDelegationBinder.Record> records;
844

845
                /**
846
                 * Creates a new compiled implementation delegate for a field delegation.
847
                 *
848
                 * @param methodDescription The method to call for result.
849
                 * @param records           The records to consider for delegation.
850
                 */
851
                protected ForMethodReturn(MethodDescription methodDescription, List<MethodDelegationBinder.Record> records) {
1✔
852
                    this.methodDescription = methodDescription;
1✔
853
                    this.records = records;
1✔
854
                }
1✔
855

856
                /**
857
                 * {@inheritDoc}
858
                 */
859
                public StackManipulation prepare(MethodDescription instrumentedMethod) {
860
                    if (instrumentedMethod.isStatic() && !methodDescription.isStatic()) {
1✔
861
                        throw new IllegalStateException("Cannot invoke " + methodDescription + " from " + instrumentedMethod);
×
862
                    }
863
                    return new StackManipulation.Compound(methodDescription.isStatic()
1✔
864
                            ? StackManipulation.Trivial.INSTANCE
865
                            : MethodVariableAccess.loadThis(), MethodInvocation.invoke(methodDescription));
1✔
866
                }
867

868
                /**
869
                 * {@inheritDoc}
870
                 */
871
                public MethodDelegationBinder.MethodInvoker invoke() {
872
                    return new MethodDelegationBinder.MethodInvoker.Virtual(methodDescription.getReturnType().asErasure());
1✔
873
                }
874

875
                /**
876
                 * {@inheritDoc}
877
                 */
878
                public List<MethodDelegationBinder.Record> getRecords() {
879
                    return records;
1✔
880
                }
881
            }
882

883
            /**
884
             * A compiled implementation delegate for a constructor delegation.
885
             */
886
            @HashCodeAndEqualsPlugin.Enhance
887
            class ForConstruction implements Compiled {
888

889
                /**
890
                 * The type to be constructed.
891
                 */
892
                private final TypeDescription typeDescription;
893

894
                /**
895
                 * The records to consider for delegation.
896
                 */
897
                private final List<MethodDelegationBinder.Record> records;
898

899
                /**
900
                 * Creates a new compiled implementation delegate for a constructor delegation.
901
                 *
902
                 * @param typeDescription The type to be constructed.
903
                 * @param records         The records to consider for delegation.
904
                 */
905
                protected ForConstruction(TypeDescription typeDescription, List<MethodDelegationBinder.Record> records) {
1✔
906
                    this.typeDescription = typeDescription;
1✔
907
                    this.records = records;
1✔
908
                }
1✔
909

910
                /**
911
                 * {@inheritDoc}
912
                 */
913
                public StackManipulation prepare(MethodDescription instrumentedMethod) {
914
                    return new StackManipulation.Compound(TypeCreation.of(typeDescription), Duplication.SINGLE);
1✔
915
                }
916

917
                /**
918
                 * {@inheritDoc}
919
                 */
920
                public MethodDelegationBinder.MethodInvoker invoke() {
921
                    return MethodDelegationBinder.MethodInvoker.Simple.INSTANCE;
1✔
922
                }
923

924
                /**
925
                 * {@inheritDoc}
926
                 */
927
                public List<MethodDelegationBinder.Record> getRecords() {
928
                    return records;
1✔
929
                }
930
            }
931
        }
932

933
        /**
934
         * An implementation delegate for a static method delegation.
935
         */
936
        @HashCodeAndEqualsPlugin.Enhance
937
        class ForStaticMethod implements ImplementationDelegate {
938

939
            /**
940
             * The precompiled records.
941
             */
942
            private final List<MethodDelegationBinder.Record> records;
943

944
            /**
945
             * Creates a new implementation delegate for a static method delegation.
946
             *
947
             * @param records The precompiled record.
948
             */
949
            protected ForStaticMethod(List<MethodDelegationBinder.Record> records) {
1✔
950
                this.records = records;
1✔
951
            }
1✔
952

953
            /**
954
             * Precompiles a static method delegation for a given list of methods.
955
             *
956
             * @param methods                The methods to consider.
957
             * @param methodDelegationBinder The method delegation binder to use.
958
             * @return An appropriate implementation delegate.
959
             */
960
            protected static ImplementationDelegate of(MethodList<?> methods, MethodDelegationBinder methodDelegationBinder) {
961
                List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size());
1✔
962
                for (MethodDescription methodDescription : methods) {
1✔
963
                    records.add(methodDelegationBinder.compile(methodDescription));
1✔
964
                }
1✔
965
                return new ForStaticMethod(records);
1✔
966
            }
967

968
            /**
969
             * {@inheritDoc}
970
             */
971
            public InstrumentedType prepare(InstrumentedType instrumentedType) {
972
                return instrumentedType;
1✔
973
            }
974

975
            /**
976
             * {@inheritDoc}
977
             */
978
            public ImplementationDelegate.Compiled compile(TypeDescription instrumentedType) {
979
                return new Compiled.ForStaticCall(records);
1✔
980
            }
981
        }
982

983
        /**
984
         * An implementation delegate for invoking methods on a field that is declared by the instrumented type or a super type.
985
         */
986
        @HashCodeAndEqualsPlugin.Enhance
987
        abstract class ForField implements ImplementationDelegate {
988

989
            /**
990
             * The name of the field that is target of the delegation.
991
             */
992
            protected final String fieldName;
993

994
            /**
995
             * The method graph compiler to use.
996
             */
997
            protected final MethodGraph.Compiler methodGraphCompiler;
998

999
            /**
1000
             * The parameter binders to use.
1001
             */
1002
            protected final List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
1003

1004
            /**
1005
             * The matcher to use for filtering methods.
1006
             */
1007
            protected final ElementMatcher<? super MethodDescription> matcher;
1008

1009
            /**
1010
             * Creates a new implementation delegate for a field delegation.
1011
             *
1012
             * @param fieldName           The name of the field that is target of the delegation.
1013
             * @param methodGraphCompiler The method graph compiler to use.
1014
             * @param parameterBinders    The parameter binders to use.
1015
             * @param matcher             The matcher to use for filtering methods.
1016
             */
1017
            protected ForField(String fieldName,
1018
                               MethodGraph.Compiler methodGraphCompiler,
1019
                               List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1020
                               ElementMatcher<? super MethodDescription> matcher) {
1✔
1021
                this.fieldName = fieldName;
1✔
1022
                this.methodGraphCompiler = methodGraphCompiler;
1✔
1023
                this.parameterBinders = parameterBinders;
1✔
1024
                this.matcher = matcher;
1✔
1025
            }
1✔
1026

1027
            /**
1028
             * {@inheritDoc}
1029
             */
1030
            public Compiled compile(TypeDescription instrumentedType) {
1031
                FieldDescription fieldDescription = resolve(instrumentedType);
1✔
1032
                if (!fieldDescription.getType().asErasure().isVisibleTo(instrumentedType)) {
1✔
1033
                    throw new IllegalStateException(fieldDescription + " is not visible to " + instrumentedType);
1✔
1034
                } else {
1035
                    MethodList<?> candidates = methodGraphCompiler.compile(fieldDescription.getType(), instrumentedType)
1✔
1036
                            .listNodes()
1✔
1037
                            .asMethodList()
1✔
1038
                            .filter(matcher);
1✔
1039
                    List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size());
1✔
1040
                    MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders);
1✔
1041
                    for (MethodDescription candidate : candidates) {
1✔
1042
                        records.add(methodDelegationBinder.compile(candidate));
1✔
1043
                    }
1✔
1044
                    return new Compiled.ForField(fieldDescription, records);
1✔
1045
                }
1046
            }
1047

1048
            /**
1049
             * Resolves the field to which is delegated.
1050
             *
1051
             * @param instrumentedType The instrumented type.
1052
             * @return The field that is the delegation target.
1053
             */
1054
            protected abstract FieldDescription resolve(TypeDescription instrumentedType);
1055

1056
            /**
1057
             * An implementation target for a static field that is declared by the instrumented type and that is assigned an instance.
1058
             */
1059
            @HashCodeAndEqualsPlugin.Enhance
1060
            protected static class WithInstance extends ForField {
1061

1062
                /**
1063
                 * The target instance.
1064
                 */
1065
                private final Object target;
1066

1067
                /**
1068
                 * The field's type.
1069
                 */
1070
                private final TypeDescription.Generic fieldType;
1071

1072
                /**
1073
                 * Creates a new implementation delegate for invoking methods on a supplied instance.
1074
                 *
1075
                 * @param fieldName           The name of the field that is target of the delegation.
1076
                 * @param methodGraphCompiler The method graph compiler to use.
1077
                 * @param parameterBinders    The parameter binders to use.
1078
                 * @param matcher             The matcher to use for filtering methods.
1079
                 * @param target              The target instance.
1080
                 * @param fieldType           The field's type.
1081
                 */
1082
                protected WithInstance(String fieldName,
1083
                                       MethodGraph.Compiler methodGraphCompiler,
1084
                                       List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1085
                                       ElementMatcher<? super MethodDescription> matcher,
1086
                                       Object target,
1087
                                       TypeDescription.Generic fieldType) {
1088
                    super(fieldName, methodGraphCompiler, parameterBinders, matcher);
1✔
1089
                    this.target = target;
1✔
1090
                    this.fieldType = fieldType;
1✔
1091
                }
1✔
1092

1093
                /**
1094
                 * {@inheritDoc}
1095
                 */
1096
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1097
                    return instrumentedType.withAuxiliaryField(new FieldDescription.Token(fieldName,
1✔
1098
                            Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_VOLATILE | Opcodes.ACC_SYNTHETIC,
1099
                            fieldType), target);
1100
                }
1101

1102
                @Override
1103
                protected FieldDescription resolve(TypeDescription instrumentedType) {
1104
                    if (!fieldType.asErasure().isVisibleTo(instrumentedType)) {
1✔
1105
                        throw new IllegalStateException(fieldType + " is not visible to " + instrumentedType);
1✔
1106
                    } else {
1107
                        return instrumentedType.getDeclaredFields()
1✔
1108
                                .filter(named(fieldName).and(fieldType(fieldType.asErasure())))
1✔
1109
                                .getOnly();
1✔
1110
                    }
1111
                }
1112
            }
1113

1114
            /**
1115
             * An implementation target for a field that is declared by the instrumented type or a super type.
1116
             */
1117
            @HashCodeAndEqualsPlugin.Enhance
1118
            protected static class WithLookup extends ForField {
1119

1120
                /**
1121
                 * The field locator factory to use for locating the field to delegate to.
1122
                 */
1123
                private final FieldLocator.Factory fieldLocatorFactory;
1124

1125
                /**
1126
                 * Creates a new implementation delegate for a field that is declared by the instrumented type or any super type.
1127
                 *
1128
                 * @param fieldName           The name of the field that is target of the delegation.
1129
                 * @param methodGraphCompiler The method graph compiler to use.
1130
                 * @param parameterBinders    The parameter binders to use.
1131
                 * @param matcher             The matcher to use for filtering methods.
1132
                 * @param fieldLocatorFactory The field locator factory to use for locating the field to delegate to.
1133
                 */
1134
                protected WithLookup(String fieldName,
1135
                                     MethodGraph.Compiler methodGraphCompiler,
1136
                                     List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1137
                                     ElementMatcher<? super MethodDescription> matcher,
1138
                                     FieldLocator.Factory fieldLocatorFactory) {
1139
                    super(fieldName, methodGraphCompiler, parameterBinders, matcher);
1✔
1140
                    this.fieldLocatorFactory = fieldLocatorFactory;
1✔
1141
                }
1✔
1142

1143
                /**
1144
                 * {@inheritDoc}
1145
                 */
1146
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1147
                    return instrumentedType;
1✔
1148
                }
1149

1150
                @Override
1151
                protected FieldDescription resolve(TypeDescription instrumentedType) {
1152
                    FieldLocator.Resolution resolution = fieldLocatorFactory.make(instrumentedType).locate(fieldName);
1✔
1153
                    if (!resolution.isResolved()) {
1✔
1154
                        throw new IllegalStateException("Could not locate " + fieldName + " on " + instrumentedType);
1✔
1155
                    } else {
1156
                        return resolution.getField();
1✔
1157
                    }
1158
                }
1159
            }
1160
        }
1161

1162
        /**
1163
         * An implementation delegate for invoking a delegation target on the another methods return value.
1164
         */
1165
        @HashCodeAndEqualsPlugin.Enhance
1166
        class ForMethodReturn implements ImplementationDelegate {
1167

1168
            /**
1169
             * The name of the method to invoke.
1170
             */
1171
            private final String name;
1172

1173
            /**
1174
             * The method graph compiler to use.
1175
             */
1176
            private final MethodGraph.Compiler methodGraphCompiler;
1177

1178
            /**
1179
             * The parameter binders to use.
1180
             */
1181
            private final List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
1182

1183
            /**
1184
             * The matcher to use for filtering methods.
1185
             */
1186
            private final ElementMatcher<? super MethodDescription> matcher;
1187

1188
            /**
1189
             * Creates a new implementation delegate for a method return value delegation.
1190
             *
1191
             * @param name                The name of the method to invoke.
1192
             * @param methodGraphCompiler The method graph compiler to use.
1193
             * @param parameterBinders    The parameter binders to use.
1194
             * @param matcher             The matcher to use for filtering methods.
1195
             */
1196
            protected ForMethodReturn(String name,
1197
                                      MethodGraph.Compiler methodGraphCompiler,
1198
                                      List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1199
                                      ElementMatcher<? super MethodDescription> matcher) {
1✔
1200
                this.name = name;
1✔
1201
                this.methodGraphCompiler = methodGraphCompiler;
1✔
1202
                this.parameterBinders = parameterBinders;
1✔
1203
                this.matcher = matcher;
1✔
1204
            }
1✔
1205

1206
            /**
1207
             * {@inheritDoc}
1208
             */
1209
            public Compiled compile(TypeDescription instrumentedType) {
1210
                MethodList<?> targets = new MethodList.Explicit<MethodDescription>(CompoundList.<MethodDescription>of(
1✔
1211
                        instrumentedType.getDeclaredMethods().filter(isStatic().or(isPrivate())),
1✔
1212
                        methodGraphCompiler.compile((TypeDefinition) instrumentedType).listNodes().asMethodList())
1✔
1213
                ).filter(named(name).and(takesArguments(0)).and(not(returns(isPrimitive().or(isArray())))));
1✔
1214
                if (targets.size() != 1) {
1✔
1215
                    throw new IllegalStateException(instrumentedType + " does not define method without arguments with name " + name + ": " + targets);
1✔
1216
                } else if (!targets.getOnly().getReturnType().asErasure().isVisibleTo(instrumentedType)) {
1✔
1217
                    throw new IllegalStateException(targets.getOnly() + " is not visible to " + instrumentedType);
×
1218
                } else {
1219
                    MethodList<?> candidates = methodGraphCompiler.compile(targets.getOnly().getReturnType(), instrumentedType)
1✔
1220
                            .listNodes()
1✔
1221
                            .asMethodList()
1✔
1222
                            .filter(matcher);
1✔
1223
                    List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(candidates.size());
1✔
1224
                    MethodDelegationBinder methodDelegationBinder = TargetMethodAnnotationDrivenBinder.of(parameterBinders);
1✔
1225
                    for (MethodDescription candidate : candidates) {
1✔
1226
                        records.add(methodDelegationBinder.compile(candidate));
1✔
1227
                    }
1✔
1228
                    return new Compiled.ForMethodReturn(targets.get(0), records);
1✔
1229
                }
1230
            }
1231

1232
            /**
1233
             * {@inheritDoc}
1234
             */
1235
            public InstrumentedType prepare(InstrumentedType instrumentedType) {
1236
                return instrumentedType;
1✔
1237
            }
1238
        }
1239

1240
        /**
1241
         * An implementation delegate for constructing an instance.
1242
         */
1243
        @HashCodeAndEqualsPlugin.Enhance
1244
        class ForConstruction implements ImplementationDelegate {
1245

1246
            /**
1247
             * The type being constructed.
1248
             */
1249
            private final TypeDescription typeDescription;
1250

1251
            /**
1252
             * The precompiled delegation records.
1253
             */
1254
            private final List<MethodDelegationBinder.Record> records;
1255

1256
            /**
1257
             * Creates an implementation delegate for constructing a new instance.
1258
             *
1259
             * @param typeDescription The type being constructed.
1260
             * @param records         The precompiled delegation records.
1261
             */
1262
            protected ForConstruction(TypeDescription typeDescription, List<MethodDelegationBinder.Record> records) {
1✔
1263
                this.typeDescription = typeDescription;
1✔
1264
                this.records = records;
1✔
1265
            }
1✔
1266

1267
            /**
1268
             * Creates an implementation delegate for constructing a new instance.
1269
             *
1270
             * @param typeDescription        The type being constructed.
1271
             * @param methods                The constructors to consider.
1272
             * @param methodDelegationBinder The method delegation binder to use.
1273
             * @return An appropriate implementation delegate.
1274
             */
1275
            protected static ImplementationDelegate of(TypeDescription typeDescription,
1276
                                                       MethodList<?> methods,
1277
                                                       MethodDelegationBinder methodDelegationBinder) {
1278
                List<MethodDelegationBinder.Record> records = new ArrayList<MethodDelegationBinder.Record>(methods.size());
1✔
1279
                for (MethodDescription methodDescription : methods) {
1✔
1280
                    records.add(methodDelegationBinder.compile(methodDescription));
1✔
1281
                }
1✔
1282
                return new ForConstruction(typeDescription, records);
1✔
1283
            }
1284

1285
            /**
1286
             * {@inheritDoc}
1287
             */
1288
            public InstrumentedType prepare(InstrumentedType instrumentedType) {
1289
                return instrumentedType;
1✔
1290
            }
1291

1292
            /**
1293
             * {@inheritDoc}
1294
             */
1295
            public Compiled compile(TypeDescription instrumentedType) {
1296
                return new Compiled.ForConstruction(typeDescription, records);
1✔
1297
            }
1298
        }
1299
    }
1300

1301
    /**
1302
     * The appender for implementing a {@link net.bytebuddy.implementation.MethodDelegation}.
1303
     */
1304
    @HashCodeAndEqualsPlugin.Enhance
1305
    protected static class Appender implements ByteCodeAppender {
1306

1307
        /**
1308
         * The implementation target of this implementation.
1309
         */
1310
        private final Target implementationTarget;
1311

1312
        /**
1313
         * The method delegation binder processor which is responsible for implementing the method delegation.
1314
         */
1315
        private final MethodDelegationBinder.Record processor;
1316

1317
        /**
1318
         * A termination handler for a method delegation binder.
1319
         */
1320
        private final MethodDelegationBinder.TerminationHandler terminationHandler;
1321

1322
        /**
1323
         * The assigner to use.
1324
         */
1325
        private final Assigner assigner;
1326

1327
        /**
1328
         * The compiled implementation delegate.
1329
         */
1330
        private final ImplementationDelegate.Compiled compiled;
1331

1332
        /**
1333
         * Creates a new appender for a method delegation.
1334
         *
1335
         * @param implementationTarget The implementation target of this implementation.
1336
         * @param processor            The method delegation binder processor which is responsible for implementing the method delegation.
1337
         * @param terminationHandler   A termination handler for a method delegation binder.
1338
         * @param assigner             The assigner to use.
1339
         * @param compiled             The compiled implementation delegate.
1340
         */
1341
        protected Appender(Target implementationTarget,
1342
                           MethodDelegationBinder.Record processor,
1343
                           MethodDelegationBinder.TerminationHandler terminationHandler,
1344
                           Assigner assigner,
1345
                           ImplementationDelegate.Compiled compiled) {
1✔
1346
            this.implementationTarget = implementationTarget;
1✔
1347
            this.processor = processor;
1✔
1348
            this.terminationHandler = terminationHandler;
1✔
1349
            this.assigner = assigner;
1✔
1350
            this.compiled = compiled;
1✔
1351
        }
1✔
1352

1353
        /**
1354
         * {@inheritDoc}
1355
         */
1356
        public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
1357
            StackManipulation.Size stackSize = new StackManipulation.Compound(
1✔
1358
                    compiled.prepare(instrumentedMethod),
1✔
1359
                    processor.bind(implementationTarget, instrumentedMethod, terminationHandler, compiled.invoke(), assigner)
1✔
1360
            ).apply(methodVisitor, implementationContext);
1✔
1361
            return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
1✔
1362
        }
1363
    }
1364

1365
    /**
1366
     * A {@link MethodDelegation} with custom configuration.
1367
     */
1368
    @HashCodeAndEqualsPlugin.Enhance
1369
    public static class WithCustomProperties {
1370

1371
        /**
1372
         * The ambiguity resolver to use.
1373
         */
1374
        private final MethodDelegationBinder.AmbiguityResolver ambiguityResolver;
1375

1376
        /**
1377
         * The parameter binders to use.
1378
         */
1379
        private final List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders;
1380

1381
        /**
1382
         * The binding resolver being used to select the relevant method binding.
1383
         */
1384
        private final MethodDelegationBinder.BindingResolver bindingResolver;
1385

1386
        /**
1387
         * The matcher to use for filtering relevant methods.
1388
         */
1389
        private final ElementMatcher<? super MethodDescription> matcher;
1390

1391
        /**
1392
         * Creates a new method delegation with custom properties that does not filter any methods.
1393
         *
1394
         * @param ambiguityResolver The ambiguity resolver to use.
1395
         * @param parameterBinders  The parameter binders to use.
1396
         */
1397
        protected WithCustomProperties(MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
1398
                                       List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders) {
1399
            this(ambiguityResolver, parameterBinders, MethodDelegationBinder.BindingResolver.Default.INSTANCE, any());
1✔
1400
        }
1✔
1401

1402
        /**
1403
         * Creates a new method delegation with custom properties.
1404
         *
1405
         * @param ambiguityResolver The ambiguity resolver to use.
1406
         * @param parameterBinders  The parameter binders to use.
1407
         * @param bindingResolver   The binding resolver being used to select the relevant method binding.
1408
         * @param matcher           The matcher to use for filtering relevant methods.
1409
         */
1410
        private WithCustomProperties(MethodDelegationBinder.AmbiguityResolver ambiguityResolver,
1411
                                     List<TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders,
1412
                                     MethodDelegationBinder.BindingResolver bindingResolver,
1413
                                     ElementMatcher<? super MethodDescription> matcher) {
1✔
1414
            this.ambiguityResolver = ambiguityResolver;
1✔
1415
            this.parameterBinders = parameterBinders;
1✔
1416
            this.bindingResolver = bindingResolver;
1✔
1417
            this.matcher = matcher;
1✔
1418
        }
1✔
1419

1420
        /**
1421
         * Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore
1422
         * more legal delegation targets should be considered.
1423
         *
1424
         * @param ambiguityResolver The ambiguity resolvers to use in their application order.
1425
         * @return A new delegation configuration which also applies the supplied ambiguity resolvers.
1426
         */
1427
        public WithCustomProperties withResolvers(MethodDelegationBinder.AmbiguityResolver... ambiguityResolver) {
1428
            return withResolvers(Arrays.asList(ambiguityResolver));
1✔
1429
        }
1430

1431
        /**
1432
         * Configures this method delegation to use the supplied ambiguity resolvers when deciding which out of two ore
1433
         * more legal delegation targets should be considered.
1434
         *
1435
         * @param ambiguityResolvers The ambiguity resolvers to use in their application order.
1436
         * @return A new delegation configuration which also applies the supplied ambiguity resolvers.
1437
         */
1438
        public WithCustomProperties withResolvers(List<? extends MethodDelegationBinder.AmbiguityResolver> ambiguityResolvers) {
1439
            return new WithCustomProperties(new MethodDelegationBinder.AmbiguityResolver.Compound(CompoundList.of(this.ambiguityResolver,
1✔
1440
                    ambiguityResolvers)), parameterBinders, bindingResolver, matcher);
1441
        }
1442

1443
        /**
1444
         * Configures this method delegation to use the supplied parameter binders when deciding what value to assign to
1445
         * a parameter of a delegation target.
1446
         *
1447
         * @param parameterBinder The parameter binders to use.
1448
         * @return A new delegation configuration which also applies the supplied parameter binders.
1449
         */
1450
        public WithCustomProperties withBinders(TargetMethodAnnotationDrivenBinder.ParameterBinder<?>... parameterBinder) {
1451
            return withBinders(Arrays.asList(parameterBinder));
1✔
1452
        }
1453

1454
        /**
1455
         * Configures this method delegation to use the supplied parameter binders when deciding what value to assign to
1456
         * a parameter of a delegation target.
1457
         *
1458
         * @param parameterBinders The parameter binders to use.
1459
         * @return A new delegation configuration which also applies the supplied parameter binders.
1460
         */
1461
        public WithCustomProperties withBinders(List<? extends TargetMethodAnnotationDrivenBinder.ParameterBinder<?>> parameterBinders) {
1462
            return new WithCustomProperties(ambiguityResolver, CompoundList.of(this.parameterBinders, parameterBinders), bindingResolver, matcher);
1✔
1463
        }
1464

1465
        /**
1466
         * Configures a custom binding resolver which is responsible for choosing a method binding among multiple candidates. Configuring
1467
         * a resolver overrides any previous configuration.
1468
         *
1469
         * @param bindingResolver The binding resolver being used to select the relevant method binding.
1470
         * @return A new delegation configuration which applies the supplied binding resolver.
1471
         */
1472
        public WithCustomProperties withBindingResolver(MethodDelegationBinder.BindingResolver bindingResolver) {
1473
            return new WithCustomProperties(ambiguityResolver, parameterBinders, bindingResolver, matcher);
×
1474
        }
1475

1476
        /**
1477
         * Configures this method delegation to only consider methods or constructors as a delegation target if they match the supplied matcher.
1478
         *
1479
         * @param matcher The matcher any delegation target needs to match in order to be considered a for delegation.
1480
         * @return A new delegation configuration which only considers methods for delegation if they match the supplied matcher.
1481
         */
1482
        @SuppressWarnings("unchecked")
1483
        public WithCustomProperties filter(ElementMatcher<? super MethodDescription> matcher) {
1484
            return new WithCustomProperties(ambiguityResolver,
1✔
1485
                    parameterBinders,
1486
                    bindingResolver,
1487
                    new ElementMatcher.Junction.Conjunction<MethodDescription>(this.matcher, matcher));
1488
        }
1489

1490
        /**
1491
         * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
1492
         * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
1493
         * the target type is either public or in the same package as the instrumented type and if the target method is either public
1494
         * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
1495
         * the interception is targeting the instrumented type.
1496
         *
1497
         * @param type The target type for the delegation.
1498
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1499
         */
1500
        public MethodDelegation to(Class<?> type) {
1501
            return to(TypeDescription.ForLoadedType.of(type));
1✔
1502
        }
1503

1504
        /**
1505
         * Delegates any intercepted method to invoke a {@code static} method that is declared by the supplied type. To be considered
1506
         * a valid delegation target, the target method must be visible and accessible to the instrumented type. This is the case if
1507
         * the target type is either public or in the same package as the instrumented type and if the target method is either public
1508
         * or non-private and in the same package as the instrumented type. Private methods can only be used as a delegation target if
1509
         * the delegation is targeting the instrumented type.
1510
         *
1511
         * @param typeDescription The target type for the delegation.
1512
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1513
         */
1514
        public MethodDelegation to(TypeDescription typeDescription) {
1515
            if (typeDescription.isArray()) {
1✔
1516
                throw new IllegalArgumentException("Cannot delegate to array " + typeDescription);
1✔
1517
            } else if (typeDescription.isPrimitive()) {
1✔
1518
                throw new IllegalArgumentException("Cannot delegate to primitive " + typeDescription);
1✔
1519
            }
1520
            return new MethodDelegation(ImplementationDelegate.ForStaticMethod.of(typeDescription.getDeclaredMethods().filter(isStatic().and(matcher)),
1✔
1521
                    TargetMethodAnnotationDrivenBinder.of(parameterBinders)), parameterBinders, ambiguityResolver, bindingResolver);
1✔
1522
        }
1523

1524
        /**
1525
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1526
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1527
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1528
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1529
         * a delegation target if the delegation is targeting the instrumented type.
1530
         *
1531
         * @param target The target instance for the delegation.
1532
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1533
         */
1534
        public MethodDelegation to(Object target) {
1535
            return to(target, MethodGraph.Compiler.DEFAULT);
1✔
1536
        }
1537

1538
        /**
1539
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1540
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1541
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1542
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1543
         * a delegation target if the delegation is targeting the instrumented type.
1544
         *
1545
         * @param target              The target instance for the delegation.
1546
         * @param methodGraphCompiler The method graph compiler to use.
1547
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1548
         */
1549
        public MethodDelegation to(Object target, MethodGraph.Compiler methodGraphCompiler) {
1550
            return to(target, target.getClass(), methodGraphCompiler);
1✔
1551
        }
1552

1553
        /**
1554
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1555
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1556
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1557
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1558
         * a delegation target if the delegation is targeting the instrumented type.
1559
         *
1560
         * @param target    The target instance for the delegation.
1561
         * @param fieldName The name of the field that is holding the {@code target} instance.
1562
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1563
         */
1564
        public MethodDelegation to(Object target, String fieldName) {
1565
            return to(target, fieldName, MethodGraph.Compiler.DEFAULT);
×
1566
        }
1567

1568
        /**
1569
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1570
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1571
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1572
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1573
         * a delegation target if the delegation is targeting the instrumented type.
1574
         *
1575
         * @param target              The target instance for the delegation.
1576
         * @param fieldName           The name of the field that is holding the {@code target} instance.
1577
         * @param methodGraphCompiler The method graph compiler to use.
1578
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1579
         */
1580
        public MethodDelegation to(Object target, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
1581
            return to(target, target.getClass(), fieldName, methodGraphCompiler);
×
1582
        }
1583

1584
        /**
1585
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1586
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1587
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1588
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1589
         * a delegation target if the delegation is targeting the instrumented type.
1590
         *
1591
         * @param target The target instance for the delegation.
1592
         * @param type   The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1593
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1594
         */
1595
        public MethodDelegation to(Object target, Type type) {
1596
            return to(target, type, MethodGraph.Compiler.DEFAULT);
×
1597
        }
1598

1599
        /**
1600
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1601
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1602
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1603
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1604
         * a delegation target if the delegation is targeting the instrumented type.
1605
         *
1606
         * @param target              The target instance for the delegation.
1607
         * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1608
         * @param methodGraphCompiler The method graph compiler to use.
1609
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1610
         */
1611
        public MethodDelegation to(Object target, Type type, MethodGraph.Compiler methodGraphCompiler) {
1612
            return to(target,
1✔
1613
                    type,
1614
                    ImplementationDelegate.FIELD_NAME_PREFIX + "$" + RandomString.hashOf(target),
1✔
1615
                    methodGraphCompiler);
1616
        }
1617

1618
        /**
1619
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1620
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1621
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1622
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1623
         * a delegation target if the delegation is targeting the instrumented type.
1624
         *
1625
         * @param target    The target instance for the delegation.
1626
         * @param type      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1627
         * @param fieldName The name of the field that is holding the {@code target} instance.
1628
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1629
         */
1630
        public MethodDelegation to(Object target, Type type, String fieldName) {
1631
            return to(target, type, fieldName, MethodGraph.Compiler.DEFAULT);
×
1632
        }
1633

1634
        /**
1635
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1636
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1637
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1638
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1639
         * a delegation target if the delegation is targeting the instrumented type.
1640
         *
1641
         * @param target              The target instance for the delegation.
1642
         * @param type                The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1643
         * @param fieldName           The name of the field that is holding the {@code target} instance.
1644
         * @param methodGraphCompiler The method graph compiler to use.
1645
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1646
         */
1647
        public MethodDelegation to(Object target, Type type, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
1648
            return to(target, TypeDefinition.Sort.describe(type), fieldName, methodGraphCompiler);
1✔
1649
        }
1650

1651
        /**
1652
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1653
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1654
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1655
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1656
         * a delegation target if the delegation is targeting the instrumented type.
1657
         *
1658
         * @param target         The target instance for the delegation.
1659
         * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1660
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1661
         */
1662
        public MethodDelegation to(Object target, TypeDefinition typeDefinition) {
1663
            return to(target, typeDefinition, MethodGraph.Compiler.DEFAULT);
×
1664
        }
1665

1666
        /**
1667
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1668
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1669
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1670
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1671
         * a delegation target if the delegation is targeting the instrumented type.
1672
         *
1673
         * @param target              The target instance for the delegation.
1674
         * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1675
         * @param methodGraphCompiler The method graph compiler to use.
1676
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1677
         */
1678
        public MethodDelegation to(Object target, TypeDefinition typeDefinition, MethodGraph.Compiler methodGraphCompiler) {
1679
            return to(target,
×
1680
                    typeDefinition,
1681
                    ImplementationDelegate.FIELD_NAME_PREFIX + "$" + RandomString.hashOf(target),
×
1682
                    methodGraphCompiler);
1683
        }
1684

1685
        /**
1686
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1687
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1688
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1689
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1690
         * a delegation target if the delegation is targeting the instrumented type.
1691
         *
1692
         * @param target         The target instance for the delegation.
1693
         * @param typeDefinition The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1694
         * @param fieldName      The name of the field that is holding the {@code target} instance.
1695
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1696
         */
1697
        public MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName) {
1698
            return to(target, typeDefinition, fieldName, MethodGraph.Compiler.DEFAULT);
×
1699
        }
1700

1701
        /**
1702
         * Delegates any intercepted method to invoke a non-{@code static} method that is declared by the supplied type's instance or any
1703
         * of its super types. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1704
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1705
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1706
         * a delegation target if the delegation is targeting the instrumented type.
1707
         *
1708
         * @param target              The target instance for the delegation.
1709
         * @param typeDefinition      The most specific type of which {@code target} should be considered. Must be a super type of the target's actual type.
1710
         * @param fieldName           The name of the field that is holding the {@code target} instance.
1711
         * @param methodGraphCompiler The method graph compiler to use.
1712
         * @return A method delegation that redirects method calls to a static method of the supplied type.
1713
         */
1714
        public MethodDelegation to(Object target, TypeDefinition typeDefinition, String fieldName, MethodGraph.Compiler methodGraphCompiler) {
1715
            if (!typeDefinition.asErasure().isInstance(target)) {
1✔
1716
                throw new IllegalArgumentException(target + " is not an instance of " + typeDefinition);
1✔
1717
            }
1718
            return new MethodDelegation(new ImplementationDelegate.ForField.WithInstance(fieldName,
1✔
1719
                    methodGraphCompiler,
1720
                    parameterBinders,
1721
                    matcher,
1722
                    target,
1723
                    typeDefinition.asGenericType()), parameterBinders, ambiguityResolver, bindingResolver);
1✔
1724
        }
1725

1726
        /**
1727
         * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
1728
         * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
1729
         * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
1730
         * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
1731
         * targeting the instrumented type.
1732
         *
1733
         * @param type The type to construct.
1734
         * @return A delegation that redirects method calls to a constructor of the supplied type.
1735
         */
1736
        public MethodDelegation toConstructor(Class<?> type) {
1737
            return toConstructor(TypeDescription.ForLoadedType.of(type));
1✔
1738
        }
1739

1740
        /**
1741
         * Delegates any intercepted method to invoke a constructor of the supplied type. To be considered a valid delegation target,
1742
         * a constructor must be visible and accessible to the instrumented type. This is the case if the constructor's declaring type is
1743
         * either public or in the same package as the instrumented type and if the constructor is either public or non-private and in
1744
         * the same package as the instrumented type. Private constructors can only be used as a delegation target if the delegation is
1745
         * targeting the instrumented type.
1746
         *
1747
         * @param typeDescription The type to construct.
1748
         * @return A delegation that redirects method calls to a constructor of the supplied type.
1749
         */
1750
        public MethodDelegation toConstructor(TypeDescription typeDescription) {
1751
            return new MethodDelegation(ImplementationDelegate.ForConstruction.of(typeDescription,
1✔
1752
                    typeDescription.getDeclaredMethods().filter(isConstructor().and(matcher)),
1✔
1753
                    TargetMethodAnnotationDrivenBinder.of(parameterBinders)), parameterBinders, ambiguityResolver, bindingResolver);
1✔
1754
        }
1755

1756
        /**
1757
         * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1758
         * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1759
         * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1760
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1761
         * a delegation target if the delegation is targeting the instrumented type.
1762
         *
1763
         * @param name The field's name.
1764
         * @return A delegation that redirects invocations to a method of the specified field's instance.
1765
         */
1766
        public MethodDelegation toField(String name) {
1767
            return toField(name, FieldLocator.ForClassHierarchy.Factory.INSTANCE);
1✔
1768
        }
1769

1770
        /**
1771
         * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1772
         * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1773
         * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1774
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1775
         * a delegation target if the delegation is targeting the instrumented type.
1776
         *
1777
         * @param name                The field's name.
1778
         * @param fieldLocatorFactory The field locator factory to use.
1779
         * @return A delegation that redirects invocations to a method of the specified field's instance.
1780
         */
1781
        public MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory) {
1782
            return toField(name, fieldLocatorFactory, MethodGraph.Compiler.DEFAULT);
1✔
1783
        }
1784

1785
        /**
1786
         * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1787
         * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1788
         * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1789
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1790
         * a delegation target if the delegation is targeting the instrumented type.
1791
         *
1792
         * @param name                The field's name.
1793
         * @param methodGraphCompiler The method graph compiler to use.
1794
         * @return A delegation that redirects invocations to a method of the specified field's instance.
1795
         */
1796
        public MethodDelegation toField(String name, MethodGraph.Compiler methodGraphCompiler) {
1797
            return toField(name, FieldLocator.ForClassHierarchy.Factory.INSTANCE, methodGraphCompiler);
×
1798
        }
1799

1800
        /**
1801
         * Delegates any intercepted method to invoke a non-{@code static} method on the instance of the supplied field. To be
1802
         * considered a valid delegation target, a method must be visible and accessible to the instrumented type. This is the
1803
         * case if the method's declaring type is either public or in the same package as the instrumented type and if the method
1804
         * is either public or non-private and in the same package as the instrumented type. Private methods can only be used as
1805
         * a delegation target if the delegation is targeting the instrumented type.
1806
         *
1807
         * @param name                The field's name.
1808
         * @param fieldLocatorFactory The field locator factory to use.
1809
         * @param methodGraphCompiler The method graph compiler to use.
1810
         * @return A delegation that redirects invocations to a method of the specified field's instance.
1811
         */
1812
        public MethodDelegation toField(String name, FieldLocator.Factory fieldLocatorFactory, MethodGraph.Compiler methodGraphCompiler) {
1813
            return new MethodDelegation(new ImplementationDelegate.ForField.WithLookup(name,
1✔
1814
                    methodGraphCompiler,
1815
                    parameterBinders,
1816
                    matcher,
1817
                    fieldLocatorFactory), parameterBinders, ambiguityResolver, bindingResolver);
1818
        }
1819

1820
        /**
1821
         * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
1822
         * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1823
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
1824
         * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
1825
         * be used as a delegation target if the delegation is targeting the instrumented type.
1826
         *
1827
         * @param name The name of the method that returns the delegation target.
1828
         * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
1829
         */
1830
        public MethodDelegation toMethodReturnOf(String name) {
1831
            return toMethodReturnOf(name, MethodGraph.Compiler.DEFAULT);
1✔
1832
        }
1833

1834
        /**
1835
         * Delegates any intercepted method to invoke a method on an instance that is returned by a parameterless method of the
1836
         * given name. To be considered a valid delegation target, a method must be visible and accessible to the instrumented type.
1837
         * This is the case if the method's declaring type is either public or in the same package as the instrumented type and if
1838
         * the method is either public or non-private and in the same package as the instrumented type. Private methods can only
1839
         * be used as a delegation target if the delegation is targeting the instrumented type.
1840
         *
1841
         * @param name                The name of the method that returns the delegation target.
1842
         * @param methodGraphCompiler The method graph compiler to use.
1843
         * @return A delegation that redirects invocations to the return value of a method that is declared by the instrumented type.
1844
         */
1845
        public MethodDelegation toMethodReturnOf(String name, MethodGraph.Compiler methodGraphCompiler) {
1846
            return new MethodDelegation(new ImplementationDelegate.ForMethodReturn(name,
1✔
1847
                    methodGraphCompiler,
1848
                    parameterBinders,
1849
                    matcher), parameterBinders, ambiguityResolver, bindingResolver);
1850
        }
1851
    }
1852
}
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