• 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

59.34
/byte-buddy-dep/src/main/java/net/bytebuddy/implementation/InvokeDynamic.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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
20
import net.bytebuddy.description.annotation.AnnotationDescription;
21
import net.bytebuddy.description.annotation.AnnotationValue;
22
import net.bytebuddy.description.enumeration.EnumerationDescription;
23
import net.bytebuddy.description.field.FieldDescription;
24
import net.bytebuddy.description.method.MethodDescription;
25
import net.bytebuddy.description.method.MethodList;
26
import net.bytebuddy.description.method.ParameterDescription;
27
import net.bytebuddy.description.method.ParameterList;
28
import net.bytebuddy.description.type.TypeDefinition;
29
import net.bytebuddy.description.type.TypeDescription;
30
import net.bytebuddy.description.type.TypeList;
31
import net.bytebuddy.description.type.TypeVariableToken;
32
import net.bytebuddy.dynamic.scaffold.FieldLocator;
33
import net.bytebuddy.dynamic.scaffold.InstrumentedType;
34
import net.bytebuddy.dynamic.scaffold.MethodGraph;
35
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
36
import net.bytebuddy.implementation.bytecode.Removal;
37
import net.bytebuddy.implementation.bytecode.StackManipulation;
38
import net.bytebuddy.implementation.bytecode.assign.Assigner;
39
import net.bytebuddy.implementation.bytecode.constant.ClassConstant;
40
import net.bytebuddy.implementation.bytecode.constant.DoubleConstant;
41
import net.bytebuddy.implementation.bytecode.constant.FloatConstant;
42
import net.bytebuddy.implementation.bytecode.constant.IntegerConstant;
43
import net.bytebuddy.implementation.bytecode.constant.LongConstant;
44
import net.bytebuddy.implementation.bytecode.constant.NullConstant;
45
import net.bytebuddy.implementation.bytecode.constant.TextConstant;
46
import net.bytebuddy.implementation.bytecode.member.FieldAccess;
47
import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
48
import net.bytebuddy.implementation.bytecode.member.MethodReturn;
49
import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
50
import net.bytebuddy.utility.CompoundList;
51
import net.bytebuddy.utility.ConstantValue;
52
import net.bytebuddy.utility.JavaConstant;
53
import net.bytebuddy.utility.JavaType;
54
import net.bytebuddy.utility.RandomString;
55
import org.objectweb.asm.MethodVisitor;
56
import org.objectweb.asm.Opcodes;
57

58
import java.lang.reflect.Constructor;
59
import java.lang.reflect.Method;
60
import java.lang.reflect.Type;
61
import java.util.ArrayList;
62
import java.util.Arrays;
63
import java.util.Collections;
64
import java.util.List;
65

66
import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
67
import static net.bytebuddy.matcher.ElementMatchers.named;
68

69
/**
70
 * An implementation that applies a
71
 * <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/invoke/package-summary.html">dynamic method invocation</a>.
72
 */
73
@HashCodeAndEqualsPlugin.Enhance
74
public class InvokeDynamic implements Implementation.Composable {
75

76
    /**
77
     * The bootstrap method.
78
     */
79
    protected final MethodDescription.InDefinedShape bootstrap;
80

81
    /**
82
     * The arguments that are provided to the bootstrap method.
83
     */
84
    protected final List<? extends JavaConstant> arguments;
85

86
    /**
87
     * The target provided that identifies the method to be bootstrapped.
88
     */
89
    protected final InvocationProvider invocationProvider;
90

91
    /**
92
     * A handler that handles the method return.
93
     */
94
    protected final TerminationHandler terminationHandler;
95

96
    /**
97
     * The assigner to be used.
98
     */
99
    protected final Assigner assigner;
100

101
    /**
102
     * Indicates if dynamic type castings should be attempted for incompatible assignments.
103
     */
104
    protected final Assigner.Typing typing;
105

106
    /**
107
     * Creates a new invoke dynamic implementation.
108
     *
109
     * @param bootstrap          The bootstrap method.
110
     * @param arguments          The arguments that are provided to the bootstrap method.
111
     * @param invocationProvider The target provided that identifies the method to be bootstrapped.
112
     * @param terminationHandler A handler that handles the method return.
113
     * @param assigner           The assigner to be used.
114
     * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
115
     */
116
    protected InvokeDynamic(MethodDescription.InDefinedShape bootstrap,
117
                            List<? extends JavaConstant> arguments,
118
                            InvocationProvider invocationProvider,
119
                            TerminationHandler terminationHandler,
120
                            Assigner assigner,
121
                            Assigner.Typing typing) {
1✔
122
        this.bootstrap = bootstrap;
1✔
123
        this.arguments = arguments;
1✔
124
        this.invocationProvider = invocationProvider;
1✔
125
        this.terminationHandler = terminationHandler;
1✔
126
        this.assigner = assigner;
1✔
127
        this.typing = typing;
1✔
128
    }
1✔
129

130
    /**
131
     * Implements the instrumented method with a dynamic method invocation which is linked at runtime using the
132
     * specified bootstrap method.
133
     *
134
     * @param method   The bootstrap method that is used to link the instrumented method.
135
     * @param constant The constant values passed to the bootstrap method. Values can be represented either
136
     *                 as {@link TypeDescription}, as {@link JavaConstant}, as {@link String} or a primitive
137
     *                 {@code int}, {@code long}, {@code float} or {@code double} represented as wrapper type.
138
     * @return An implementation where a {@code this} reference, if available, and all arguments of the
139
     * instrumented method are passed to the bootstrapped method unless explicit parameters are specified.
140
     */
141
    public static WithImplicitTarget bootstrap(Method method, Object... constant) {
142
        return bootstrap(new MethodDescription.ForLoadedMethod(method), constant);
1✔
143
    }
144

145
    /**
146
     * Implements the instrumented method with a dynamic method invocation which is linked at runtime using the
147
     * specified bootstrap method.
148
     *
149
     * @param method    The bootstrap method that is used to link the instrumented method.
150
     * @param constants The constant values passed to the bootstrap method. Values can be represented either
151
     *                  as {@link TypeDescription}, as {@link JavaConstant}, as {@link String} or a primitive
152
     *                  {@code int}, {@code long}, {@code float} or {@code double} represented as wrapper type.
153
     * @return An implementation where a {@code this} reference, if available, and all arguments of the
154
     * instrumented method are passed to the bootstrapped method unless explicit parameters are specified.
155
     */
156
    public static WithImplicitTarget bootstrap(Method method, List<?> constants) {
157
        return bootstrap(new MethodDescription.ForLoadedMethod(method), constants);
×
158
    }
159

160
    /**
161
     * Implements the instrumented method with a dynamic method invocation which is linked at runtime using the
162
     * specified bootstrap constructor.
163
     *
164
     * @param constructor The bootstrap constructor that is used to link the instrumented method.
165
     * @param constant    The constant values passed to the bootstrap method. Values can be represented either
166
     *                    as {@link TypeDescription}, as {@link JavaConstant}, as {@link String} or a primitive
167
     *                    {@code int}, {@code long}, {@code float} or {@code double} represented as wrapper type.
168
     * @return An implementation where a {@code this} reference, if available, and all arguments of the
169
     * instrumented method are passed to the bootstrapped method unless explicit parameters are specified.
170
     */
171
    public static WithImplicitTarget bootstrap(Constructor<?> constructor, Object... constant) {
172
        return bootstrap(new MethodDescription.ForLoadedConstructor(constructor), constant);
1✔
173
    }
174

175
    /**
176
     * Implements the instrumented method with a dynamic method invocation which is linked at runtime using the
177
     * specified bootstrap constructor.
178
     *
179
     * @param constructor The bootstrap constructor that is used to link the instrumented method.
180
     * @param constants   The constant values passed to the bootstrap method. Values can be represented either
181
     *                    as {@link TypeDescription}, as {@link JavaConstant}, as {@link String} or a primitive
182
     *                    {@code int}, {@code long}, {@code float} or {@code double} represented as wrapper type.
183
     * @return An implementation where a {@code this} reference, if available, and all arguments of the
184
     * instrumented method are passed to the bootstrapped method unless explicit parameters are specified.
185
     */
186
    public static WithImplicitTarget bootstrap(Constructor<?> constructor, List<?> constants) {
187
        return bootstrap(new MethodDescription.ForLoadedConstructor(constructor), constants);
×
188
    }
189

190
    /**
191
     * Implements the instrumented method with a dynamic method invocation which is linked at runtime using the
192
     * specified bootstrap method or constructor.
193
     *
194
     * @param bootstrap The bootstrap method or constructor that is used to link the instrumented method.
195
     * @param constant  The constant values passed to the bootstrap method. Values can be represented either
196
     *                  as {@link TypeDescription}, as {@link JavaConstant}, as {@link String} or a primitive
197
     *                  {@code int}, {@code long}, {@code float} or {@code double} represented as wrapper type.
198
     * @return An implementation where a {@code this} reference, if available, and all arguments of the
199
     * instrumented method are passed to the bootstrapped method unless explicit parameters are specified.
200
     */
201
    public static WithImplicitTarget bootstrap(MethodDescription.InDefinedShape bootstrap, Object... constant) {
202
        return bootstrap(bootstrap, Arrays.asList(constant));
1✔
203
    }
204

205
    /**
206
     * Implements the instrumented method with a dynamic method invocation which is linked at runtime using the
207
     * specified bootstrap method or constructor.
208
     *
209
     * @param bootstrap The bootstrap method or constructor that is used to link the instrumented method.
210
     * @param constants The constant values passed to the bootstrap method. Values can be represented either
211
     *                  as {@link TypeDescription}, as {@link JavaConstant}, as {@link String} or a primitive
212
     *                  {@code int}, {@code long}, {@code float} or {@code double} represented as wrapper type.
213
     * @return An implementation where a {@code this} reference, if available, and all arguments of the
214
     * instrumented method are passed to the bootstrapped method unless explicit parameters are specified.
215
     */
216
    public static WithImplicitTarget bootstrap(MethodDescription.InDefinedShape bootstrap, List<?> constants) {
217
        List<JavaConstant> arguments = JavaConstant.Simple.wrap(constants);
1✔
218
        if (!bootstrap.isInvokeBootstrap(TypeList.Explicit.of(arguments))) {
1✔
219
            throw new IllegalArgumentException("Not a valid bootstrap method " + bootstrap + " for " + arguments);
1✔
220
        }
221
        return new WithImplicitTarget(bootstrap,
1✔
222
                arguments,
223
                new InvocationProvider.Default(),
224
                TerminationHandler.RETURNING,
225
                Assigner.DEFAULT,
226
                Assigner.Typing.STATIC);
227
    }
228

229
    /**
230
     * <p>
231
     * Creates a lambda expression using the JVM's lambda meta factory. The method that is implementing the lambda expression is provided
232
     * the explicit arguments first and the functional interface's method second.
233
     * </p>
234
     * <p>
235
     * <b>Important</b>: Byte Buddy does not validate that the provided arguments are correct considering the required arguments of the bound
236
     * functional interface. Binding an incorrect number of arguments or arguments of incompatible types does not create illegal byte code
237
     * but yields a runtime error when the call site is first used. This is done to support future extensions or alternative implementations
238
     * of the Java virtual machine.
239
     * </p>
240
     *
241
     * @param method              The method that implements the lambda expression.
242
     * @param functionalInterface The functional interface that is an instance of the lambda expression.
243
     * @return A builder for creating a lambda expression.
244
     */
245
    public static WithImplicitArguments lambda(Method method, Type functionalInterface) {
246
        return lambda(new MethodDescription.ForLoadedMethod(method), TypeDefinition.Sort.describe(functionalInterface));
1✔
247
    }
248

249
    /**
250
     * <p>
251
     * Creates a lambda expression using the JVM's lambda meta factory. The method that is implementing the lambda expression is provided
252
     * the explicit arguments first and the functional interface's method second.
253
     * </p>
254
     * <p>
255
     * <b>Important</b>: Byte Buddy does not validate that the provided arguments are correct considering the required arguments of the bound
256
     * functional interface. Binding an incorrect number of arguments or arguments of incompatible types does not create illegal byte code
257
     * but yields a runtime error when the call site is first used. This is done to support future extensions or alternative implementations
258
     * of the Java virtual machine.
259
     * </p>
260
     *
261
     * @param method              The method that implements the lambda expression.
262
     * @param functionalInterface The functional interface that is an instance of the lambda expression.
263
     * @param methodGraphCompiler The method graph compiler to use.
264
     * @return A builder for creating a lambda expression.
265
     */
266
    public static WithImplicitArguments lambda(Method method, Type functionalInterface, MethodGraph.Compiler methodGraphCompiler) {
267
        return lambda(new MethodDescription.ForLoadedMethod(method), TypeDefinition.Sort.describe(functionalInterface), methodGraphCompiler);
×
268
    }
269

270
    /**
271
     * <p>
272
     * Creates a lambda expression using the JVM's lambda meta factory. The method that is implementing the lambda expression is provided
273
     * the explicit arguments first and the functional interface's method second.
274
     * </p>
275
     * <p>
276
     * <b>Important</b>: Byte Buddy does not validate that the provided arguments are correct considering the required arguments of the bound
277
     * functional interface. Binding an incorrect number of arguments or arguments of incompatible types does not create illegal byte code
278
     * but yields a runtime error when the call site is first used. This is done to support future extensions or alternative implementations
279
     * of the Java virtual machine.
280
     * </p>
281
     *
282
     * @param methodDescription   The method that implements the lambda expression.
283
     * @param functionalInterface The functional interface that is an instance of the lambda expression.
284
     * @return A builder for creating a lambda expression.
285
     */
286
    public static WithImplicitArguments lambda(MethodDescription.InDefinedShape methodDescription, TypeDefinition functionalInterface) {
287
        return lambda(methodDescription, functionalInterface, MethodGraph.Compiler.Default.forJavaHierarchy());
1✔
288
    }
289

290
    /**
291
     * <p>
292
     * Creates a lambda expression using the JVM's lambda meta factory. The method that is implementing the lambda expression is provided
293
     * the explicit arguments first and the functional interface's method second.
294
     * </p>
295
     * <p>
296
     * <b>Important</b>: Byte Buddy does not validate that the provided arguments are correct considering the required arguments of the bound
297
     * functional interface. Binding an incorrect number of arguments or arguments of incompatible types does not create illegal byte code
298
     * but yields a runtime error when the call site is first used. This is done to support future extensions or alternative implementations
299
     * of the Java virtual machine.
300
     * </p>
301
     *
302
     * @param methodDescription   The method that implements the lambda expression.
303
     * @param functionalInterface The functional interface that is an instance of the lambda expression.
304
     * @param methodGraphCompiler The method graph compiler to use.
305
     * @return A builder for creating a lambda expression.
306
     */
307
    public static WithImplicitArguments lambda(MethodDescription.InDefinedShape methodDescription,
308
                                               TypeDefinition functionalInterface,
309
                                               MethodGraph.Compiler methodGraphCompiler) {
310
        if (!functionalInterface.isInterface()) {
1✔
311
            throw new IllegalArgumentException(functionalInterface + " is not an interface type");
1✔
312
        }
313
        MethodList<?> methods = methodGraphCompiler.compile(functionalInterface)
1✔
314
                .listNodes()
1✔
315
                .asMethodList()
1✔
316
                .filter(isAbstract());
1✔
317
        if (methods.size() != 1) {
1✔
318
            throw new IllegalArgumentException(functionalInterface + " does not define exactly one abstract method: " + methods);
1✔
319
        }
320
        return bootstrap(new MethodDescription.Latent(new TypeDescription.Latent("java.lang.invoke.LambdaMetafactory",
1✔
321
                        Opcodes.ACC_PUBLIC,
322
                        TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(Object.class)),
1✔
323
                        "metafactory",
324
                        Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC,
325
                        Collections.<TypeVariableToken>emptyList(),
1✔
326
                        JavaType.CALL_SITE.getTypeStub().asGenericType(),
1✔
327
                        Arrays.asList(new ParameterDescription.Token(JavaType.METHOD_HANDLES_LOOKUP.getTypeStub().asGenericType()),
1✔
328
                                new ParameterDescription.Token(TypeDescription.ForLoadedType.of(String.class).asGenericType()),
1✔
329
                                new ParameterDescription.Token(JavaType.METHOD_TYPE.getTypeStub().asGenericType()),
1✔
330
                                new ParameterDescription.Token(JavaType.METHOD_TYPE.getTypeStub().asGenericType()),
1✔
331
                                new ParameterDescription.Token(JavaType.METHOD_HANDLE.getTypeStub().asGenericType()),
1✔
332
                                new ParameterDescription.Token(JavaType.METHOD_TYPE.getTypeStub().asGenericType())),
1✔
333
                        Collections.<TypeDescription.Generic>emptyList(),
1✔
334
                        Collections.<AnnotationDescription>emptyList(),
1✔
335
                        AnnotationValue.UNDEFINED,
336
                        TypeDescription.Generic.UNDEFINED),
337
                JavaConstant.MethodType.ofSignature(methods.asDefined().getOnly()),
1✔
338
                JavaConstant.MethodHandle.of(methodDescription),
1✔
339
                JavaConstant.MethodType.ofSignature(methods.getOnly())).invoke(methods.asDefined().getOnly().getInternalName());
1✔
340
    }
341

342
    /**
343
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code boolean} arguments
344
     * as its next parameters.
345
     *
346
     * @param value The arguments to pass to the bootstrapped method.
347
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
348
     */
349
    public InvokeDynamic withBooleanValue(boolean... value) {
350
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
351
        for (boolean aValue : value) {
×
352
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForBooleanConstant(aValue));
×
353
        }
354
        return new InvokeDynamic(bootstrap,
×
355
                arguments,
356
                invocationProvider.appendArguments(argumentProviders),
×
357
                terminationHandler,
358
                assigner,
359
                typing);
360
    }
361

362
    /**
363
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code byte} arguments
364
     * as its next parameters.
365
     *
366
     * @param value The arguments to pass to the bootstrapped method.
367
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
368
     */
369
    public InvokeDynamic withByteValue(byte... value) {
370
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
371
        for (byte aValue : value) {
×
372
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForByteConstant(aValue));
×
373
        }
374
        return new InvokeDynamic(bootstrap,
×
375
                arguments,
376
                invocationProvider.appendArguments(argumentProviders),
×
377
                terminationHandler,
378
                assigner,
379
                typing);
380
    }
381

382
    /**
383
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code short} arguments
384
     * as its next parameters.
385
     *
386
     * @param value The arguments to pass to the bootstrapped method.
387
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
388
     */
389
    public InvokeDynamic withShortValue(short... value) {
390
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
391
        for (short aValue : value) {
×
392
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForShortConstant(aValue));
×
393
        }
394
        return new InvokeDynamic(bootstrap,
×
395
                arguments,
396
                invocationProvider.appendArguments(argumentProviders),
×
397
                terminationHandler,
398
                assigner,
399
                typing);
400
    }
401

402
    /**
403
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code char} arguments
404
     * as its next parameters.
405
     *
406
     * @param value The arguments to pass to the bootstrapped method.
407
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
408
     */
409
    public InvokeDynamic withCharacterValue(char... value) {
410
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
411
        for (char aValue : value) {
×
412
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForCharacterConstant(aValue));
×
413
        }
414
        return new InvokeDynamic(bootstrap,
×
415
                arguments,
416
                invocationProvider.appendArguments(argumentProviders),
×
417
                terminationHandler,
418
                assigner,
419
                typing);
420
    }
421

422
    /**
423
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code int} arguments
424
     * as its next parameters.
425
     *
426
     * @param value The arguments to pass to the bootstrapped method.
427
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
428
     */
429
    public InvokeDynamic withIntegerValue(int... value) {
430
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
431
        for (int aValue : value) {
×
432
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForIntegerConstant(aValue));
×
433
        }
434
        return new InvokeDynamic(bootstrap,
×
435
                arguments,
436
                invocationProvider.appendArguments(argumentProviders),
×
437
                terminationHandler,
438
                assigner,
439
                typing);
440
    }
441

442
    /**
443
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code long} arguments
444
     * as its next parameters.
445
     *
446
     * @param value The arguments to pass to the bootstrapped method.
447
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
448
     */
449
    public InvokeDynamic withLongValue(long... value) {
450
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
451
        for (long aValue : value) {
×
452
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForLongConstant(aValue));
×
453
        }
454
        return new InvokeDynamic(bootstrap,
×
455
                arguments,
456
                invocationProvider.appendArguments(argumentProviders),
×
457
                terminationHandler,
458
                assigner,
459
                typing);
460
    }
461

462
    /**
463
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code float} arguments
464
     * as its next parameters.
465
     *
466
     * @param value The arguments to pass to the bootstrapped method.
467
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
468
     */
469
    public InvokeDynamic withFloatValue(float... value) {
470
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
471
        for (float aValue : value) {
×
472
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForFloatConstant(aValue));
×
473
        }
474
        return new InvokeDynamic(bootstrap,
×
475
                arguments,
476
                invocationProvider.appendArguments(argumentProviders),
×
477
                terminationHandler,
478
                assigner,
479
                typing);
480
    }
481

482
    /**
483
     * Requires the bootstrap method to bootstrap a method that takes the specified {@code double} arguments
484
     * as its next parameters.
485
     *
486
     * @param value The arguments to pass to the bootstrapped method.
487
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
488
     */
489
    public InvokeDynamic withDoubleValue(double... value) {
490
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
×
491
        for (double aValue : value) {
×
492
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForDoubleConstant(aValue));
×
493
        }
494
        return new InvokeDynamic(bootstrap,
×
495
                arguments,
496
                invocationProvider.appendArguments(argumentProviders),
×
497
                terminationHandler,
498
                assigner,
499
                typing);
500
    }
501

502
    /**
503
     * <p>
504
     * Requires the bootstrap method to bootstrap a method that takes the specified arguments as its next parameters.
505
     * Note that any primitive parameters are passed as their wrapper types. Furthermore, values that can be stored
506
     * in the instrumented class's constant pool might be of different object identity when passed to the
507
     * bootstrapped method or might not be visible to the the created class what later results in a runtime error.
508
     * </p>
509
     *
510
     * @param value The arguments to pass to the bootstrapped method.
511
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
512
     */
513
    public InvokeDynamic withValue(Object... value) {
514
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
1✔
515
        for (Object aValue : value) {
1✔
516
            argumentProviders.add(InvocationProvider.ArgumentProvider.ConstantPoolWrapper.of(aValue));
1✔
517
        }
518
        return new InvokeDynamic(bootstrap,
1✔
519
                arguments,
520
                invocationProvider.appendArguments(argumentProviders),
1✔
521
                terminationHandler,
522
                assigner,
523
                typing);
524
    }
525

526
    /**
527
     * <p>
528
     * Requires the bootstrap method to bootstrap a method that takes the specified argument as its next parameter while
529
     * allowing to specify the value to be of a different type than the actual instance type.
530
     * </p>
531
     *
532
     * @param value The arguments to pass to the bootstrapped method.
533
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
534
     */
535
    public WithImplicitType withReference(Object value) {
536
        return new WithImplicitType.OfInstance(bootstrap,
1✔
537
                arguments,
538
                invocationProvider,
539
                terminationHandler,
540
                assigner,
541
                typing,
542
                value);
543
    }
544

545
    /**
546
     * Requires the bootstrap method to bootstrap a method that takes the specified arguments as its next parameters.
547
     * Note that any primitive parameters are passed as their wrapper types. Any value that is passed to the
548
     * bootstrapped method is guaranteed to be of the same object identity.
549
     *
550
     * @param value The arguments to pass to the bootstrapped method.
551
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
552
     */
553
    public InvokeDynamic withReference(Object... value) {
554
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(value.length);
1✔
555
        for (Object aValue : value) {
1✔
556
            argumentProviders.add(InvocationProvider.ArgumentProvider.ForInstance.of(aValue));
1✔
557
        }
558
        return new InvokeDynamic(bootstrap,
1✔
559
                arguments,
560
                invocationProvider.appendArguments(argumentProviders),
1✔
561
                terminationHandler,
562
                assigner,
563
                typing);
564
    }
565

566
    /**
567
     * Hands the provided types to the dynamically bound method. The type is stored in the generated class's
568
     * constant pool and is loaded at invocation time. For this to be possible, the created class's
569
     * class loader must be able to see the provided type.
570
     *
571
     * @param typeDescription The classes to provide to the bound method as an argument.
572
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified type.
573
     */
574
    public InvokeDynamic withType(TypeDescription... typeDescription) {
575
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(typeDescription.length);
×
576
        for (TypeDescription aTypeDescription : typeDescription) {
×
577
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForClassConstant(aTypeDescription));
×
578
        }
579
        return new InvokeDynamic(bootstrap,
×
580
                arguments,
581
                invocationProvider.appendArguments(argumentProviders),
×
582
                terminationHandler,
583
                assigner,
584
                typing);
585
    }
586

587
    /**
588
     * Hands the provided enumerations to the dynamically bound method. The enumeration values are read from
589
     * the enumeration class on demand. For this to be possible, the created class's class loader must be
590
     * able to see the enumeration type.
591
     *
592
     * @param enumerationDescription The enumeration values to provide to the bound method as an argument.
593
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified enumerations.
594
     */
595
    public InvokeDynamic withEnumeration(EnumerationDescription... enumerationDescription) {
596
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(enumerationDescription.length);
×
597
        for (EnumerationDescription anEnumerationDescription : enumerationDescription) {
×
598
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForEnumerationValue(anEnumerationDescription));
×
599
        }
600
        return new InvokeDynamic(bootstrap,
×
601
                arguments,
602
                invocationProvider.appendArguments(argumentProviders),
×
603
                terminationHandler,
604
                assigner,
605
                typing);
606
    }
607

608
    /**
609
     * Hands the provided Java instance to the dynamically bound method. The instance is stored in the generated class's
610
     * constant pool and is loaded at invocation time. For this to be possible, the created class's class loader must
611
     * be able to create the provided Java instance.
612
     *
613
     * @param constant The constants to provide to the bound method as an argument.
614
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified Java instance.
615
     */
616
    public InvokeDynamic withInstance(ConstantValue... constant) {
617
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(constant.length);
×
618
        for (ConstantValue aConstant : constant) {
×
619
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForJavaConstant(aConstant));
×
620
        }
621
        return new InvokeDynamic(bootstrap,
×
622
                arguments,
623
                invocationProvider.appendArguments(argumentProviders),
×
624
                terminationHandler,
625
                assigner,
626
                typing);
627
    }
628

629
    /**
630
     * Hands the provided Java instance to the dynamically bound method. The instance is stored in the generated class's
631
     * constant pool and is loaded at invocation time. For this to be possible, the created class's class loader must
632
     * be able to create the provided Java instance.
633
     *
634
     * @param constant The constants to provide to the bound method as an argument.
635
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified Java instance.
636
     */
637
    public InvokeDynamic withInstance(JavaConstant... constant) {
638
        return withInstance((ConstantValue[]) constant);
×
639
    }
640

641
    /**
642
     * Passes {@code null} values of the given types to the bootstrapped method.
643
     *
644
     * @param type The type that the {@code null} values should represent.
645
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
646
     */
647
    public InvokeDynamic withNullValue(Class<?>... type) {
648
        return withNullValue(new TypeList.ForLoadedTypes(type).toArray(new TypeDescription[0]));
1✔
649
    }
650

651
    /**
652
     * Passes {@code null} values of the given types to the bootstrapped method.
653
     *
654
     * @param typeDescription The type that the {@code null} values should represent.
655
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
656
     */
657
    public InvokeDynamic withNullValue(TypeDescription... typeDescription) {
658
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(typeDescription.length);
1✔
659
        for (TypeDescription aTypeDescription : typeDescription) {
1✔
660
            if (aTypeDescription.isPrimitive()) {
1✔
661
                throw new IllegalArgumentException("Cannot assign null to primitive type: " + aTypeDescription);
×
662
            }
663
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForNullValue(aTypeDescription));
1✔
664
        }
665
        return new InvokeDynamic(bootstrap,
1✔
666
                arguments,
667
                invocationProvider.appendArguments(argumentProviders),
1✔
668
                terminationHandler,
669
                assigner,
670
                typing);
671
    }
672

673
    /**
674
     * Passes parameters of the instrumented method to the bootstrapped method.
675
     *
676
     * @param index The indices of the parameters that should be passed to the bootstrapped method.
677
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
678
     */
679
    public InvokeDynamic withArgument(int... index) {
680
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(index.length);
×
681
        for (int anIndex : index) {
×
682
            if (anIndex < 0) {
×
683
                throw new IllegalArgumentException("Method parameter indices cannot be negative: " + anIndex);
×
684
            }
685
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForMethodParameter(anIndex));
×
686
        }
687
        return new InvokeDynamic(bootstrap,
×
688
                arguments,
689
                invocationProvider.appendArguments(argumentProviders),
×
690
                terminationHandler,
691
                assigner,
692
                typing);
693
    }
694

695
    /**
696
     * Passes a parameter of the instrumented method to the bootstrapped method.
697
     *
698
     * @param index The index of the parameter that should be passed to the bootstrapped method.
699
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified argument
700
     * with its implicit type.
701
     */
702
    public WithImplicitType withArgument(int index) {
703
        if (index < 0) {
1✔
704
            throw new IllegalArgumentException("Method parameter indices cannot be negative: " + index);
1✔
705
        }
706
        return new WithImplicitType.OfArgument(bootstrap,
1✔
707
                arguments,
708
                invocationProvider,
709
                terminationHandler,
710
                assigner,
711
                typing,
712
                index);
713
    }
714

715
    /**
716
     * Passes references to {@code this} onto the operand stack where the instance is represented as
717
     * the given types.
718
     *
719
     * @param type The types as which the {@code this} reference of the intercepted method should be masked.
720
     * @return This implementation where {@code this} references are passed as the next arguments.
721
     */
722
    public InvokeDynamic withThis(Class<?>... type) {
723
        return withThis(new TypeList.ForLoadedTypes(type).toArray(new TypeDescription[0]));
1✔
724
    }
725

726
    /**
727
     * Passes references to {@code this} onto the operand stack where the instance is represented as
728
     * the given types.
729
     *
730
     * @param typeDescription The types as which the {@code this} reference of the intercepted method should be masked.
731
     * @return This implementation where {@code this} references are passed as the next arguments.
732
     */
733
    public InvokeDynamic withThis(TypeDescription... typeDescription) {
734
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(typeDescription.length);
1✔
735
        for (TypeDescription aTypeDescription : typeDescription) {
1✔
736
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForThisInstance(aTypeDescription));
1✔
737
        }
738
        return new InvokeDynamic(bootstrap,
1✔
739
                arguments,
740
                invocationProvider.appendArguments(argumentProviders),
1✔
741
                terminationHandler,
742
                assigner,
743
                typing);
744
    }
745

746
    /**
747
     * Adds all method arguments to the the bootstrapped method.
748
     *
749
     * @return This invoke dynamic implementation with all parameters of the instrumented method added.
750
     */
751
    public InvokeDynamic withMethodArguments() {
752
        return new InvokeDynamic(bootstrap,
1✔
753
                arguments,
754
                invocationProvider.appendArgument(InvocationProvider.ArgumentProvider.ForInterceptedMethodParameters.INSTANCE),
1✔
755
                terminationHandler,
756
                assigner,
757
                typing);
758
    }
759

760
    /**
761
     * Adds a potential {@code this} reference and all method arguments to the the bootstrapped method.
762
     *
763
     * @return This invoke dynamic implementation with a potential {@code this} reference and all
764
     * parameters of the instrumented method added.
765
     */
766
    public InvokeDynamic withImplicitAndMethodArguments() {
767
        return new InvokeDynamic(bootstrap,
×
768
                arguments,
769
                invocationProvider.appendArgument(InvocationProvider.ArgumentProvider.ForInterceptedMethodInstanceAndParameters.INSTANCE),
×
770
                terminationHandler,
771
                assigner,
772
                typing);
773
    }
774

775
    /**
776
     * Passes the values of the specified fields to the bootstrap method. Any of the specified fields must already
777
     * exist for the instrumented type.
778
     *
779
     * @param name The names of the fields to be passed to the bootstrapped method.
780
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
781
     */
782
    public InvokeDynamic withField(String... name) {
783
        return withField(FieldLocator.ForClassHierarchy.Factory.INSTANCE, name);
×
784
    }
785

786
    /**
787
     * Passes the values of the specified fields to the bootstrap method. Any of the specified fields must already
788
     * exist for the instrumented type.
789
     *
790
     * @param fieldLocatorFactory The field locator factory to use.
791
     * @param name                The names of the fields to be passed to the bootstrapped method.
792
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
793
     */
794
    public InvokeDynamic withField(FieldLocator.Factory fieldLocatorFactory, String... name) {
795
        List<InvocationProvider.ArgumentProvider> argumentProviders = new ArrayList<InvocationProvider.ArgumentProvider>(name.length);
×
796
        for (String aName : name) {
×
797
            argumentProviders.add(new InvocationProvider.ArgumentProvider.ForField(aName, fieldLocatorFactory));
×
798
        }
799
        return new InvokeDynamic(bootstrap,
×
800
                arguments,
801
                invocationProvider.appendArguments(argumentProviders),
×
802
                terminationHandler,
803
                assigner,
804
                typing);
805
    }
806

807
    /**
808
     * Passes the values of the specified fields to the bootstrap method. Any of the specified fields must already
809
     * exist for the instrumented type.
810
     *
811
     * @param name The names of the fields to be passed to the bootstrapped method.
812
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
813
     */
814
    public WithImplicitType withField(String name) {
815
        return withField(name, FieldLocator.ForClassHierarchy.Factory.INSTANCE);
1✔
816
    }
817

818
    /**
819
     * Passes the values of the specified fields to the bootstrap method. Any of the specified fields must already
820
     * exist for the instrumented type.
821
     *
822
     * @param fieldLocatorFactory The field locator factory to use.
823
     * @param name                The names of the fields to be passed to the bootstrapped method.
824
     * @return This invoke dynamic implementation where the bootstrapped method is passed the specified arguments.
825
     */
826
    public WithImplicitType withField(String name, FieldLocator.Factory fieldLocatorFactory) {
827
        return new WithImplicitType.OfField(bootstrap,
1✔
828
                arguments,
829
                invocationProvider,
830
                terminationHandler,
831
                assigner,
832
                typing,
833
                name,
834
                fieldLocatorFactory);
835
    }
836

837
    /**
838
     * Instructs this implementation to use the provided assigner and decides if the assigner should apply
839
     * dynamic typing.
840
     *
841
     * @param assigner The assigner to use.
842
     * @param typing   {@code true} if the assigner should attempt dynamic typing.
843
     * @return The invoke dynamic instruction where the given assigner and dynamic-typing directive are applied.
844
     */
845
    public Implementation.Composable withAssigner(Assigner assigner, Assigner.Typing typing) {
846
        return new InvokeDynamic(bootstrap,
1✔
847
                arguments,
848
                invocationProvider,
849
                terminationHandler,
850
                assigner,
851
                typing);
852
    }
853

854
    /**
855
     * {@inheritDoc}
856
     */
857
    public Implementation andThen(Implementation implementation) {
858
        return new Implementation.Compound(new InvokeDynamic(bootstrap,
1✔
859
                arguments,
860
                invocationProvider,
861
                TerminationHandler.DROPPING,
862
                assigner,
863
                typing),
864
                implementation);
865
    }
866

867
    /**
868
     * {@inheritDoc}
869
     */
870
    public Composable andThen(Composable implementation) {
871
        return new Implementation.Compound.Composable(new InvokeDynamic(bootstrap,
×
872
                arguments,
873
                invocationProvider,
874
                TerminationHandler.DROPPING,
875
                assigner,
876
                typing),
877
                implementation);
878
    }
879

880
    /**
881
     * {@inheritDoc}
882
     */
883
    public InstrumentedType prepare(InstrumentedType instrumentedType) {
884
        return invocationProvider.prepare(instrumentedType);
1✔
885
    }
886

887
    /**
888
     * {@inheritDoc}
889
     */
890
    public ByteCodeAppender appender(Target implementationTarget) {
891
        return new Appender(implementationTarget.getInstrumentedType());
1✔
892
    }
893

894
    /**
895
     * An invocation provider is responsible for loading the arguments of the invoked method onto the operand
896
     * stack and for creating the actual <i>invoke dynamic</i> instruction.
897
     */
898
    protected interface InvocationProvider {
899

900
        /**
901
         * Creates a target for the invocation.
902
         *
903
         * @param methodDescription The method that is being intercepted.
904
         * @return The target for the invocation.
905
         */
906
        Target make(MethodDescription methodDescription);
907

908
        /**
909
         * Appends the given arguments to the invocation to be loaded onto the operand stack.
910
         *
911
         * @param argumentProviders The next arguments to be loaded onto the operand stack.
912
         * @return An invocation provider for this target that loads the given arguments onto the operand stack.
913
         */
914
        InvocationProvider appendArguments(List<ArgumentProvider> argumentProviders);
915

916
        /**
917
         * Appends the given argument to the invocation to be loaded onto the operand stack.
918
         *
919
         * @param argumentProvider The next argument to be loaded onto the operand stack.
920
         * @return An invocation provider for this target that loads the given arguments onto the operand stack.
921
         */
922
        InvocationProvider appendArgument(ArgumentProvider argumentProvider);
923

924
        /**
925
         * Returns a copy of this invocation provider that does not add any arguments.
926
         *
927
         * @return A copy of this invocation provider that does not add any arguments.
928
         */
929
        InvocationProvider withoutArguments();
930

931
        /**
932
         * Returns a copy of this invocation provider that applies the given name provider.
933
         *
934
         * @param nameProvider The name provider to be used.
935
         * @return A copy of this invocation provider that applies the given name provider.
936
         */
937
        InvocationProvider withNameProvider(NameProvider nameProvider);
938

939
        /**
940
         * Returns a copy of this invocation provider that applies the given return type provider.
941
         *
942
         * @param returnTypeProvider The return type provider to be used.
943
         * @return A copy of this invocation provider that applies the given return type provider.
944
         */
945
        InvocationProvider withReturnTypeProvider(ReturnTypeProvider returnTypeProvider);
946

947
        /**
948
         * Prepares the instrumented type.
949
         *
950
         * @param instrumentedType The instrumented type to prepare.
951
         * @return The prepared instrumented type.
952
         */
953
        InstrumentedType prepare(InstrumentedType instrumentedType);
954

955
        /**
956
         * A target for a dynamic method invocation.
957
         */
958
        interface Target {
959

960
            /**
961
             * Resolves the target.
962
             *
963
             * @param instrumentedType The instrumented type.
964
             * @param assigner         The assigner to be used.
965
             * @param typing           Indicates if dynamic type castings should be attempted for incompatible assignments.
966
             * @return The resolved target.
967
             */
968
            Resolved resolve(TypeDescription instrumentedType, Assigner assigner, Assigner.Typing typing);
969

970
            /**
971
             * Represents a resolved {@link net.bytebuddy.implementation.InvokeDynamic.InvocationProvider.Target}.
972
             */
973
            interface Resolved {
974

975
                /**
976
                 * Returns the stack manipulation that loads the arguments onto the operand stack.
977
                 *
978
                 * @return The stack manipulation that loads the arguments onto the operand stack.
979
                 */
980
                StackManipulation getStackManipulation();
981

982
                /**
983
                 * Returns the requested return type.
984
                 *
985
                 * @return The requested return type.
986
                 */
987
                TypeDescription getReturnType();
988

989
                /**
990
                 * Returns the internal name of the requested method.
991
                 *
992
                 * @return The internal name of the requested method.
993
                 */
994
                String getInternalName();
995

996
                /**
997
                 * Returns the types of the values on the operand stack.
998
                 *
999
                 * @return The types of the values on the operand stack.
1000
                 */
1001
                List<TypeDescription> getParameterTypes();
1002

1003
                /**
1004
                 * A simple implementation of
1005
                 * {@link net.bytebuddy.implementation.InvokeDynamic.InvocationProvider.Target.Resolved}.
1006
                 */
1007
                @HashCodeAndEqualsPlugin.Enhance
1008
                class Simple implements Resolved {
1009

1010
                    /**
1011
                     * The stack manipulation that loads the arguments onto the operand stack.
1012
                     */
1013
                    private final StackManipulation stackManipulation;
1014

1015
                    /**
1016
                     * The internal name of the requested method.
1017
                     */
1018
                    private final String internalName;
1019

1020
                    /**
1021
                     * The requested return type.
1022
                     */
1023
                    private final TypeDescription returnType;
1024

1025
                    /**
1026
                     * The types of the values on the operand stack.
1027
                     */
1028
                    private final List<TypeDescription> parameterTypes;
1029

1030
                    /**
1031
                     * Creates a new simple instance.
1032
                     *
1033
                     * @param stackManipulation The stack manipulation that loads the arguments onto the operand stack.
1034
                     * @param internalName      The internal name of the requested method.
1035
                     * @param returnType        The requested return type.
1036
                     * @param parameterTypes    The types of the values on the operand stack.
1037
                     */
1038
                    public Simple(StackManipulation stackManipulation,
1039
                                  String internalName,
1040
                                  TypeDescription returnType,
1041
                                  List<TypeDescription> parameterTypes) {
1✔
1042
                        this.stackManipulation = stackManipulation;
1✔
1043
                        this.internalName = internalName;
1✔
1044
                        this.returnType = returnType;
1✔
1045
                        this.parameterTypes = parameterTypes;
1✔
1046
                    }
1✔
1047

1048
                    /**
1049
                     * {@inheritDoc}
1050
                     */
1051
                    public StackManipulation getStackManipulation() {
1052
                        return stackManipulation;
1✔
1053
                    }
1054

1055
                    /**
1056
                     * {@inheritDoc}
1057
                     */
1058
                    public TypeDescription getReturnType() {
1059
                        return returnType;
1✔
1060
                    }
1061

1062
                    /**
1063
                     * {@inheritDoc}
1064
                     */
1065
                    public String getInternalName() {
1066
                        return internalName;
1✔
1067
                    }
1068

1069
                    /**
1070
                     * {@inheritDoc}
1071
                     */
1072
                    public List<TypeDescription> getParameterTypes() {
1073
                        return parameterTypes;
1✔
1074
                    }
1075
                }
1076
            }
1077
        }
1078

1079
        /**
1080
         * An argument provider is responsible for loading arguments to a bootstrapped method onto the operand
1081
         * stack and providing the types of these arguments.
1082
         */
1083
        interface ArgumentProvider {
1084

1085
            /**
1086
             * Resolves an argument provider.
1087
             *
1088
             * @param instrumentedType   The instrumented type.
1089
             * @param instrumentedMethod The instrumented method.
1090
             * @param assigner           The assigner to be used.
1091
             * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
1092
             * @return A resolved version of this argument provider.
1093
             */
1094
            Resolved resolve(TypeDescription instrumentedType,
1095
                             MethodDescription instrumentedMethod,
1096
                             Assigner assigner,
1097
                             Assigner.Typing typing);
1098

1099
            /**
1100
             * Prepares the instrumented type.
1101
             *
1102
             * @param instrumentedType The instrumented type.
1103
             * @return The prepared instrumented type.
1104
             */
1105
            InstrumentedType prepare(InstrumentedType instrumentedType);
1106

1107
            /**
1108
             * An argument provider that loads a reference to the intercepted instance and all arguments of
1109
             * the intercepted method.
1110
             */
1111
            enum ForInterceptedMethodInstanceAndParameters implements ArgumentProvider {
1✔
1112

1113
                /**
1114
                 * The singleton instance.
1115
                 */
1116
                INSTANCE;
1✔
1117

1118
                /**
1119
                 * {@inheritDoc}
1120
                 */
1121
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1122
                    return new Resolved.Simple(MethodVariableAccess.allArgumentsOf(instrumentedMethod).prependThisReference(),
×
1123
                            instrumentedMethod.isStatic()
×
1124
                                    ? instrumentedMethod.getParameters().asTypeList().asErasures()
×
1125
                                    : CompoundList.of(instrumentedMethod.getDeclaringType().asErasure(), instrumentedMethod.getParameters().asTypeList().asErasures()));
×
1126
                }
1127

1128
                /**
1129
                 * {@inheritDoc}
1130
                 */
1131
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1132
                    return instrumentedType;
×
1133
                }
1134
            }
1135

1136
            /**
1137
             * An argument provider that loads all arguments of the intercepted method.
1138
             */
1139
            enum ForInterceptedMethodParameters implements ArgumentProvider {
1✔
1140

1141
                /**
1142
                 * The singleton instance.
1143
                 */
1144
                INSTANCE;
1✔
1145

1146
                /**
1147
                 * {@inheritDoc}
1148
                 */
1149
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1150
                    return new Resolved.Simple(MethodVariableAccess.allArgumentsOf(instrumentedMethod),
1✔
1151
                            instrumentedMethod.getParameters().asTypeList().asErasures());
1✔
1152
                }
1153

1154
                /**
1155
                 * {@inheritDoc}
1156
                 */
1157
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1158
                    return instrumentedType;
1✔
1159
                }
1160
            }
1161

1162
            /**
1163
             * Represents wrapper types and types that could be stored in a class's constant pool as such
1164
             * constant pool values.
1165
             */
1166
            enum ConstantPoolWrapper {
1✔
1167

1168
                /**
1169
                 * Stores a {@link java.lang.Boolean} as a {@code boolean} and wraps it on load.
1170
                 */
1171
                BOOLEAN(boolean.class, Boolean.class) {
1✔
1172
                    @Override
1173
                    protected ArgumentProvider make(Object value) {
1174
                        return new WrappingArgumentProvider(IntegerConstant.forValue((Boolean) value));
×
1175
                    }
1176
                },
1177

1178
                /**
1179
                 * Stores a {@link java.lang.Byte} as a {@code byte} and wraps it on load.
1180
                 */
1181
                BYTE(byte.class, Byte.class) {
1✔
1182
                    @Override
1183
                    protected ArgumentProvider make(Object value) {
1184
                        return new WrappingArgumentProvider(IntegerConstant.forValue((Byte) value));
×
1185
                    }
1186
                },
1187

1188
                /**
1189
                 * Stores a {@link java.lang.Short} as a {@code short} and wraps it on load.
1190
                 */
1191
                SHORT(short.class, Short.class) {
1✔
1192
                    @Override
1193
                    protected ArgumentProvider make(Object value) {
1194
                        return new WrappingArgumentProvider(IntegerConstant.forValue((Short) value));
×
1195
                    }
1196
                },
1197

1198
                /**
1199
                 * Stores a {@link java.lang.Character} as a {@code char} and wraps it on load.
1200
                 */
1201
                CHARACTER(char.class, Character.class) {
1✔
1202
                    @Override
1203
                    protected ArgumentProvider make(Object value) {
1204
                        return new WrappingArgumentProvider(IntegerConstant.forValue((Character) value));
×
1205
                    }
1206
                },
1207

1208
                /**
1209
                 * Stores a {@link java.lang.Integer} as a {@code int} and wraps it on load.
1210
                 */
1211
                INTEGER(int.class, Integer.class) {
1✔
1212
                    @Override
1213
                    protected ArgumentProvider make(Object value) {
1214
                        return new WrappingArgumentProvider(IntegerConstant.forValue((Integer) value));
×
1215
                    }
1216
                },
1217

1218
                /**
1219
                 * Stores a {@link java.lang.Long} as a {@code long} and wraps it on load.
1220
                 */
1221
                LONG(long.class, Long.class) {
1✔
1222
                    @Override
1223
                    protected ArgumentProvider make(Object value) {
1224
                        return new WrappingArgumentProvider(LongConstant.forValue((Long) value));
×
1225
                    }
1226
                },
1227

1228
                /**
1229
                 * Stores a {@link java.lang.Float} as a {@code float} and wraps it on load.
1230
                 */
1231
                FLOAT(float.class, Float.class) {
1✔
1232
                    @Override
1233
                    protected ArgumentProvider make(Object value) {
1234
                        return new WrappingArgumentProvider(FloatConstant.forValue((Float) value));
×
1235
                    }
1236
                },
1237

1238
                /**
1239
                 * Stores a {@link java.lang.Double} as a {@code double} and wraps it on load.
1240
                 */
1241
                DOUBLE(double.class, Double.class) {
1✔
1242
                    @Override
1243
                    protected ArgumentProvider make(Object value) {
1244
                        return new WrappingArgumentProvider(DoubleConstant.forValue((Double) value));
×
1245
                    }
1246
                };
1247

1248
                /**
1249
                 * The primitive type that can be stored on the constant pool.
1250
                 */
1251
                private final TypeDescription primitiveType;
1252

1253
                /**
1254
                 * The wrapper type that is to be represented.
1255
                 */
1256
                private final TypeDescription wrapperType;
1257

1258
                /**
1259
                 * Creates a new wrapper delegate for a primitive type.
1260
                 *
1261
                 * @param primitiveType The primitive type that can be stored on the constant pool.
1262
                 * @param wrapperType   The wrapper type that is to be represented.
1263
                 */
1264
                ConstantPoolWrapper(Class<?> primitiveType, Class<?> wrapperType) {
1✔
1265
                    this.primitiveType = TypeDescription.ForLoadedType.of(primitiveType);
1✔
1266
                    this.wrapperType = TypeDescription.ForLoadedType.of(wrapperType);
1✔
1267
                }
1✔
1268

1269
                /**
1270
                 * Represents the given value by a constant pool value or as a field if this is not possible.
1271
                 *
1272
                 * @param value The value to provide to the bootstrapped method.
1273
                 * @return An argument provider for this value.
1274
                 */
1275
                public static ArgumentProvider of(Object value) {
1276
                    if (value instanceof Boolean) {
1✔
1277
                        return BOOLEAN.make(value);
×
1278
                    } else if (value instanceof Byte) {
1✔
1279
                        return BYTE.make(value);
×
1280
                    } else if (value instanceof Short) {
1✔
1281
                        return SHORT.make(value);
×
1282
                    } else if (value instanceof Character) {
1✔
1283
                        return CHARACTER.make(value);
×
1284
                    } else if (value instanceof Integer) {
1✔
1285
                        return INTEGER.make(value);
×
1286
                    } else if (value instanceof Long) {
1✔
1287
                        return LONG.make(value);
×
1288
                    } else if (value instanceof Float) {
1✔
1289
                        return FLOAT.make(value);
×
1290
                    } else if (value instanceof Double) {
1✔
1291
                        return DOUBLE.make(value);
×
1292
                    } else if (value instanceof String) {
1✔
1293
                        return new ForStringConstant((String) value);
1✔
1294
                    } else if (value instanceof Class<?>) {
×
1295
                        return new ForClassConstant(TypeDescription.ForLoadedType.of((Class<?>) value));
×
1296
                    } else if (value instanceof TypeDescription) {
×
1297
                        return new ForClassConstant((TypeDescription) value);
×
1298
                    } else if (value instanceof Enum<?>) {
×
1299
                        return new ForEnumerationValue(new EnumerationDescription.ForLoadedEnumeration((Enum<?>) value));
×
1300
                    } else if (value instanceof EnumerationDescription) {
×
1301
                        return new ForEnumerationValue((EnumerationDescription) value);
×
1302
                    } else if (JavaType.METHOD_HANDLE.isInstance(value)) {
×
1303
                        return new ForJavaConstant(JavaConstant.MethodHandle.ofLoaded(value));
×
1304
                    } else if (JavaType.METHOD_TYPE.isInstance(value)) {
×
1305
                        return new ForJavaConstant(JavaConstant.MethodType.ofLoaded(value));
×
1306
                    } else if (value instanceof JavaConstant) {
×
1307
                        return new ForJavaConstant((JavaConstant) value);
×
1308
                    } else {
1309
                        return ForInstance.of(value);
×
1310
                    }
1311
                }
1312

1313
                /**
1314
                 * Creates an argument provider for a given primitive value.
1315
                 *
1316
                 * @param value The wrapper-type value to provide to the bootstrapped method.
1317
                 * @return An argument provider for this value.
1318
                 */
1319
                protected abstract ArgumentProvider make(Object value);
1320

1321
                /**
1322
                 * An argument provider that loads a primitive value from the constant pool and wraps it.
1323
                 */
1324
                @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
1325
                protected class WrappingArgumentProvider implements ArgumentProvider {
1326

1327
                    /**
1328
                     * The stack manipulation that represents the loading of the primitive value.
1329
                     */
1330
                    private final StackManipulation stackManipulation;
1331

1332
                    /**
1333
                     * Creates a new wrapping argument provider.
1334
                     *
1335
                     * @param stackManipulation The stack manipulation that represents the loading of the
1336
                     *                          primitive value.
1337
                     */
1338
                    protected WrappingArgumentProvider(StackManipulation stackManipulation) {
×
1339
                        this.stackManipulation = stackManipulation;
×
1340
                    }
×
1341

1342
                    /**
1343
                     * {@inheritDoc}
1344
                     */
1345
                    public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1346
                        return new Resolved.Simple(new StackManipulation.Compound(stackManipulation,
×
1347
                                assigner.assign(primitiveType.asGenericType(), wrapperType.asGenericType(), typing)), wrapperType);
×
1348
                    }
1349

1350
                    /**
1351
                     * {@inheritDoc}
1352
                     */
1353
                    public InstrumentedType prepare(InstrumentedType instrumentedType) {
1354
                        return instrumentedType;
×
1355
                    }
1356
                }
1357
            }
1358

1359
            /**
1360
             * A resolved {@link net.bytebuddy.implementation.InvokeDynamic.InvocationProvider.ArgumentProvider}.
1361
             */
1362
            interface Resolved {
1363

1364
                /**
1365
                 * Returns a stack manipulation that loads the arguments onto the operand stack.
1366
                 *
1367
                 * @return A stack manipulation that loads the arguments onto the operand stack.
1368
                 */
1369
                StackManipulation getLoadInstruction();
1370

1371
                /**
1372
                 * Returns a list of all types of the arguments that were loaded onto the operand stack.
1373
                 *
1374
                 * @return A list of all types of the arguments that were loaded onto the operand stack.
1375
                 */
1376
                List<TypeDescription> getLoadedTypes();
1377

1378
                /**
1379
                 * A simple implementation of a resolved argument provider.
1380
                 */
1381
                @HashCodeAndEqualsPlugin.Enhance
1382
                class Simple implements Resolved {
1383

1384
                    /**
1385
                     * A stack manipulation that loads the arguments onto the operand stack.
1386
                     */
1387
                    private final StackManipulation stackManipulation;
1388

1389
                    /**
1390
                     * A list of all types of the arguments that were loaded onto the operand stack.
1391
                     */
1392
                    private final List<TypeDescription> loadedTypes;
1393

1394
                    /**
1395
                     * Creates a simple resolved argument provider.
1396
                     *
1397
                     * @param stackManipulation A stack manipulation that loads the argument onto the operand stack.
1398
                     * @param loadedType        The type of the arguments that is loaded onto the operand stack.
1399
                     */
1400
                    public Simple(StackManipulation stackManipulation, TypeDescription loadedType) {
1401
                        this(stackManipulation, Collections.singletonList(loadedType));
1✔
1402
                    }
1✔
1403

1404
                    /**
1405
                     * Creates a simple resolved argument provider.
1406
                     *
1407
                     * @param stackManipulation A stack manipulation that loads the arguments onto the operand stack.
1408
                     * @param loadedTypes       A list of all types of the arguments that were loaded onto the
1409
                     *                          operand stack.
1410
                     */
1411
                    public Simple(StackManipulation stackManipulation, List<TypeDescription> loadedTypes) {
1✔
1412
                        this.stackManipulation = stackManipulation;
1✔
1413
                        this.loadedTypes = loadedTypes;
1✔
1414
                    }
1✔
1415

1416
                    /**
1417
                     * {@inheritDoc}
1418
                     */
1419
                    public StackManipulation getLoadInstruction() {
1420
                        return stackManipulation;
1✔
1421
                    }
1422

1423
                    /**
1424
                     * {@inheritDoc}
1425
                     */
1426
                    public List<TypeDescription> getLoadedTypes() {
1427
                        return loadedTypes;
1✔
1428
                    }
1429
                }
1430
            }
1431

1432
            /**
1433
             * An argument provider that loads the intercepted instance.
1434
             */
1435
            @HashCodeAndEqualsPlugin.Enhance
1436
            class ForThisInstance implements ArgumentProvider {
1437

1438
                /**
1439
                 * The type as which the intercepted instance should be loaded onto the operand stack.
1440
                 */
1441
                private final TypeDescription typeDescription;
1442

1443
                /**
1444
                 * Creates a new argument provider for the instance of the instrumented type.
1445
                 *
1446
                 * @param typeDescription The type as which the instrumented type should be loaded onto the operand stack.
1447
                 */
1448
                protected ForThisInstance(TypeDescription typeDescription) {
1✔
1449
                    this.typeDescription = typeDescription;
1✔
1450
                }
1✔
1451

1452
                /**
1453
                 * {@inheritDoc}
1454
                 */
1455
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1456
                    if (instrumentedMethod.isStatic()) {
1✔
1457
                        throw new IllegalStateException("Cannot get this instance from static method: " + instrumentedMethod);
×
1458
                    } else if (!instrumentedType.isAssignableTo(typeDescription)) {
1✔
1459
                        throw new IllegalStateException(instrumentedType + " is not assignable to " + instrumentedType);
×
1460
                    }
1461
                    return new Resolved.Simple(MethodVariableAccess.loadThis(), typeDescription);
1✔
1462
                }
1463

1464
                /**
1465
                 * {@inheritDoc}
1466
                 */
1467
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1468
                    return instrumentedType;
1✔
1469
                }
1470
            }
1471

1472
            /**
1473
             * An argument provider for a value that is stored in a randomly named static field.
1474
             */
1475
            @HashCodeAndEqualsPlugin.Enhance
1476
            class ForInstance implements ArgumentProvider {
1477

1478
                /**
1479
                 * The prefix of any field generated by this argument provider.
1480
                 */
1481
                private static final String FIELD_PREFIX = "invokeDynamic";
1482

1483
                /**
1484
                 * The value that is stored in the static field.
1485
                 */
1486
                private final Object value;
1487

1488
                /**
1489
                 * The type of the static field.
1490
                 */
1491
                private final TypeDescription fieldType;
1492

1493
                /**
1494
                 * The name of the field.
1495
                 */
1496
                @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.IGNORE)
1497
                private final String name;
1498

1499
                /**
1500
                 * Creates a new argument provider that stores the given value in a static field.
1501
                 *
1502
                 * @param value     The value that is to be provided to the bootstrapped method.
1503
                 * @param fieldType The type of the field which is also provided to the bootstrap method.
1504
                 */
1505
                protected ForInstance(Object value, TypeDescription fieldType) {
1✔
1506
                    this.value = value;
1✔
1507
                    this.fieldType = fieldType;
1✔
1508
                    name = FIELD_PREFIX + "$" + RandomString.hashOf(value);
1✔
1509
                }
1✔
1510

1511
                /**
1512
                 * Creates a new argument provider that stores the given value in a static field of the instance type.
1513
                 *
1514
                 * @param value The value that is to be provided to the bootstrapped method.
1515
                 * @return A corresponding argument provider.
1516
                 */
1517
                protected static ArgumentProvider of(Object value) {
1518
                    return new ForInstance(value, TypeDescription.ForLoadedType.of(value.getClass()));
1✔
1519
                }
1520

1521
                /**
1522
                 * {@inheritDoc}
1523
                 */
1524
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1525
                    FieldDescription fieldDescription = instrumentedType.getDeclaredFields().filter(named(name)).getOnly();
1✔
1526
                    StackManipulation stackManipulation = assigner.assign(fieldDescription.getType(), fieldType.asGenericType(), typing);
1✔
1527
                    if (!stackManipulation.isValid()) {
1✔
1528
                        throw new IllegalStateException("Cannot assign " + fieldDescription + " to " + fieldType);
×
1529
                    }
1530
                    return new Resolved.Simple(new StackManipulation.Compound(FieldAccess.forField(fieldDescription).read(),
1✔
1531
                            stackManipulation), fieldDescription.getType().asErasure());
1✔
1532
                }
1533

1534
                /**
1535
                 * {@inheritDoc}
1536
                 */
1537
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1538
                    return instrumentedType.withAuxiliaryField(new FieldDescription.Token(name,
1✔
1539
                            Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_VOLATILE | Opcodes.ACC_SYNTHETIC,
1540
                            fieldType.asGenericType()), value);
1✔
1541
                }
1542
            }
1543

1544
            /**
1545
             * Provides an argument from an existing field.
1546
             */
1547
            @HashCodeAndEqualsPlugin.Enhance
1548
            class ForField implements ArgumentProvider {
1549

1550
                /**
1551
                 * The name of the field.
1552
                 */
1553
                protected final String fieldName;
1554

1555
                /**
1556
                 * The field locator factory to use.
1557
                 */
1558
                protected final FieldLocator.Factory fieldLocatorFactory;
1559

1560
                /**
1561
                 * Creates a new argument provider that loads the value of an existing field.
1562
                 *
1563
                 * @param fieldName           The name of the field.
1564
                 * @param fieldLocatorFactory The field locator factory to use.
1565
                 */
1566
                protected ForField(String fieldName, FieldLocator.Factory fieldLocatorFactory) {
1✔
1567
                    this.fieldName = fieldName;
1✔
1568
                    this.fieldLocatorFactory = fieldLocatorFactory;
1✔
1569
                }
1✔
1570

1571
                /**
1572
                 * {@inheritDoc}
1573
                 */
1574
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1575
                    FieldLocator.Resolution resolution = fieldLocatorFactory.make(instrumentedType).locate(fieldName);
1✔
1576
                    if (!resolution.isResolved()) {
1✔
1577
                        throw new IllegalStateException("Cannot find a field " + fieldName + " for " + instrumentedType);
1✔
1578
                    } else if (!resolution.getField().isStatic() && instrumentedMethod.isStatic()) {
1✔
1579
                        throw new IllegalStateException("Cannot access non-static " + resolution.getField() + " from " + instrumentedMethod);
×
1580
                    }
1581
                    return doResolve(new StackManipulation.Compound(resolution.getField().isStatic()
1✔
1582
                                    ? StackManipulation.Trivial.INSTANCE
1583
                                    : MethodVariableAccess.loadThis(), FieldAccess.forField(resolution.getField()).read()),
1✔
1584
                            resolution.getField().getType(),
1✔
1585
                            assigner,
1586
                            typing);
1587
                }
1588

1589
                /**
1590
                 * Resolves this argument provider.
1591
                 *
1592
                 * @param access   The stack manipulation for accessing the argument value.
1593
                 * @param type     The type of the loaded value.
1594
                 * @param assigner The assigner to use.
1595
                 * @param typing   The typing required.
1596
                 * @return A resolved version of this arguments provider.
1597
                 */
1598
                protected Resolved doResolve(StackManipulation access, TypeDescription.Generic type, Assigner assigner, Assigner.Typing typing) {
1599
                    return new Resolved.Simple(access, type.asErasure());
1✔
1600
                }
1601

1602
                /**
1603
                 * {@inheritDoc}
1604
                 */
1605
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1606
                    return instrumentedType;
1✔
1607
                }
1608

1609
                /**
1610
                 * An argument provider for a field value with an explicit type.
1611
                 */
1612
                @HashCodeAndEqualsPlugin.Enhance
1613
                protected static class WithExplicitType extends ForField {
1614

1615
                    /**
1616
                     * The explicit type.
1617
                     */
1618
                    private final TypeDescription typeDescription;
1619

1620
                    /**
1621
                     * Creates an argument provider for a field value with an explicit type.
1622
                     *
1623
                     * @param fieldName           The name of the field.
1624
                     * @param fieldLocatorFactory The field locator factory to use.
1625
                     * @param typeDescription     The explicit type.
1626
                     */
1627
                    protected WithExplicitType(String fieldName, FieldLocator.Factory fieldLocatorFactory, TypeDescription typeDescription) {
1628
                        super(fieldName, fieldLocatorFactory);
1✔
1629
                        this.typeDescription = typeDescription;
1✔
1630
                    }
1✔
1631

1632
                    /**
1633
                     * {@inheritDoc}
1634
                     */
1635
                    protected Resolved doResolve(StackManipulation access, TypeDescription.Generic typeDescription, Assigner assigner, Assigner.Typing typing) {
1636
                        StackManipulation stackManipulation = assigner.assign(typeDescription, this.typeDescription.asGenericType(), typing);
1✔
1637
                        if (!stackManipulation.isValid()) {
1✔
1638
                            throw new IllegalStateException("Cannot assign " + typeDescription + " to " + this.typeDescription);
1✔
1639
                        }
1640
                        return new Resolved.Simple(new StackManipulation.Compound(access, stackManipulation), this.typeDescription);
1✔
1641
                    }
1642
                }
1643
            }
1644

1645
            /**
1646
             * An argument provider that loads an argument of the intercepted method.
1647
             */
1648
            @HashCodeAndEqualsPlugin.Enhance
1649
            class ForMethodParameter implements ArgumentProvider {
1650

1651
                /**
1652
                 * The index of the parameter.
1653
                 */
1654
                protected final int index;
1655

1656
                /**
1657
                 * Creates an argument provider for an argument of the intercepted method.
1658
                 *
1659
                 * @param index The index of the parameter.
1660
                 */
1661
                protected ForMethodParameter(int index) {
1✔
1662
                    this.index = index;
1✔
1663
                }
1✔
1664

1665
                /**
1666
                 * {@inheritDoc}
1667
                 */
1668
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1669
                    ParameterList<?> parameters = instrumentedMethod.getParameters();
1✔
1670
                    if (index >= parameters.size()) {
1✔
1671
                        throw new IllegalStateException("No parameter " + index + " for " + instrumentedMethod);
1✔
1672
                    }
1673
                    return doResolve(MethodVariableAccess.load(parameters.get(index)), parameters.get(index).getType(), assigner, typing);
1✔
1674
                }
1675

1676
                /**
1677
                 * Resolves this argument provider.
1678
                 *
1679
                 * @param access   The stack manipulation for accessing the argument value.
1680
                 * @param type     The type of the loaded value.
1681
                 * @param assigner The assigner to use.
1682
                 * @param typing   The typing required.
1683
                 * @return A resolved version of this arguments provider.
1684
                 */
1685
                protected Resolved doResolve(StackManipulation access, TypeDescription.Generic type, Assigner assigner, Assigner.Typing typing) {
1686
                    return new Resolved.Simple(access, type.asErasure());
1✔
1687
                }
1688

1689
                /**
1690
                 * {@inheritDoc}
1691
                 */
1692
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1693
                    return instrumentedType;
1✔
1694
                }
1695

1696
                /**
1697
                 * An argument provider for a method parameter with an explicit type.
1698
                 */
1699
                @HashCodeAndEqualsPlugin.Enhance
1700
                protected static class WithExplicitType extends ForMethodParameter {
1701

1702
                    /**
1703
                     * The explicit type.
1704
                     */
1705
                    private final TypeDescription typeDescription;
1706

1707
                    /**
1708
                     * Creates a new argument provider for a method parameter with an explicit type.
1709
                     *
1710
                     * @param index           The index of the parameter.
1711
                     * @param typeDescription The explicit type.
1712
                     */
1713
                    protected WithExplicitType(int index, TypeDescription typeDescription) {
1714
                        super(index);
×
1715
                        this.typeDescription = typeDescription;
×
1716
                    }
×
1717

1718
                    /**
1719
                     * {@inheritDoc}
1720
                     */
1721
                    protected Resolved doResolve(StackManipulation access, TypeDescription.Generic type, Assigner assigner, Assigner.Typing typing) {
1722
                        StackManipulation stackManipulation = assigner.assign(type, typeDescription.asGenericType(), typing);
×
1723
                        if (!stackManipulation.isValid()) {
×
1724
                            throw new IllegalStateException("Cannot assign " + type + " to " + typeDescription);
×
1725
                        }
1726
                        return new Resolved.Simple(new StackManipulation.Compound(access, stackManipulation), typeDescription);
×
1727
                    }
1728
                }
1729
            }
1730

1731
            /**
1732
             * An argument provider for a {@code boolean} value.
1733
             */
1734
            @HashCodeAndEqualsPlugin.Enhance
1735
            class ForBooleanConstant implements ArgumentProvider {
1736

1737
                /**
1738
                 * The represented {@code boolean} value.
1739
                 */
1740
                private final boolean value;
1741

1742
                /**
1743
                 * Creates a new argument provider for a {@code boolean} value.
1744
                 *
1745
                 * @param value The represented {@code boolean} value.
1746
                 */
1747
                protected ForBooleanConstant(boolean value) {
×
1748
                    this.value = value;
×
1749
                }
×
1750

1751
                /**
1752
                 * {@inheritDoc}
1753
                 */
1754
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1755
                    return new Resolved.Simple(IntegerConstant.forValue(value), TypeDescription.ForLoadedType.of(boolean.class));
×
1756
                }
1757

1758
                /**
1759
                 * {@inheritDoc}
1760
                 */
1761
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1762
                    return instrumentedType;
×
1763
                }
1764
            }
1765

1766
            /**
1767
             * An argument provider for a {@code byte} value.
1768
             */
1769
            @HashCodeAndEqualsPlugin.Enhance
1770
            class ForByteConstant implements ArgumentProvider {
1771

1772
                /**
1773
                 * The represented {@code byte} value.
1774
                 */
1775
                private final byte value;
1776

1777
                /**
1778
                 * Creates a new argument provider for a {@code byte} value.
1779
                 *
1780
                 * @param value The represented {@code byte} value.
1781
                 */
1782
                protected ForByteConstant(byte value) {
×
1783
                    this.value = value;
×
1784
                }
×
1785

1786
                /**
1787
                 * {@inheritDoc}
1788
                 */
1789
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1790
                    return new Resolved.Simple(IntegerConstant.forValue(value), TypeDescription.ForLoadedType.of(byte.class));
×
1791
                }
1792

1793
                /**
1794
                 * {@inheritDoc}
1795
                 */
1796
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1797
                    return instrumentedType;
×
1798
                }
1799
            }
1800

1801
            /**
1802
             * An argument provider for a {@code short} value.
1803
             */
1804
            @HashCodeAndEqualsPlugin.Enhance
1805
            class ForShortConstant implements ArgumentProvider {
1806

1807
                /**
1808
                 * The represented {@code short} value.
1809
                 */
1810
                private final short value;
1811

1812
                /**
1813
                 * Creates a new argument provider for a {@code short} value.
1814
                 *
1815
                 * @param value The represented {@code short} value.
1816
                 */
1817
                protected ForShortConstant(short value) {
×
1818
                    this.value = value;
×
1819
                }
×
1820

1821
                /**
1822
                 * {@inheritDoc}
1823
                 */
1824
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1825
                    return new Resolved.Simple(IntegerConstant.forValue(value), TypeDescription.ForLoadedType.of(short.class));
×
1826
                }
1827

1828
                /**
1829
                 * {@inheritDoc}
1830
                 */
1831
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1832
                    return instrumentedType;
×
1833
                }
1834
            }
1835

1836
            /**
1837
             * An argument provider for a {@code char} value.
1838
             */
1839
            @HashCodeAndEqualsPlugin.Enhance
1840
            class ForCharacterConstant implements ArgumentProvider {
1841

1842
                /**
1843
                 * The represented {@code char} value.
1844
                 */
1845
                private final char value;
1846

1847
                /**
1848
                 * Creates a new argument provider for a {@code char} value.
1849
                 *
1850
                 * @param value The represented {@code char} value.
1851
                 */
1852
                protected ForCharacterConstant(char value) {
×
1853
                    this.value = value;
×
1854
                }
×
1855

1856
                /**
1857
                 * {@inheritDoc}
1858
                 */
1859
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1860
                    return new Resolved.Simple(IntegerConstant.forValue(value), TypeDescription.ForLoadedType.of(char.class));
×
1861
                }
1862

1863
                /**
1864
                 * {@inheritDoc}
1865
                 */
1866
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1867
                    return instrumentedType;
×
1868
                }
1869
            }
1870

1871
            /**
1872
             * An argument provider for a {@code int} value.
1873
             */
1874
            @HashCodeAndEqualsPlugin.Enhance
1875
            class ForIntegerConstant implements ArgumentProvider {
1876

1877
                /**
1878
                 * The represented {@code int} value.
1879
                 */
1880
                private final int value;
1881

1882
                /**
1883
                 * Creates a new argument provider for a {@code int} value.
1884
                 *
1885
                 * @param value The represented {@code int} value.
1886
                 */
1887
                protected ForIntegerConstant(int value) {
×
1888
                    this.value = value;
×
1889
                }
×
1890

1891
                /**
1892
                 * {@inheritDoc}
1893
                 */
1894
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1895
                    return new Resolved.Simple(IntegerConstant.forValue(value), TypeDescription.ForLoadedType.of(int.class));
×
1896
                }
1897

1898
                /**
1899
                 * {@inheritDoc}
1900
                 */
1901
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1902
                    return instrumentedType;
×
1903
                }
1904
            }
1905

1906
            /**
1907
             * An argument provider for a {@code long} value.
1908
             */
1909
            @HashCodeAndEqualsPlugin.Enhance
1910
            class ForLongConstant implements ArgumentProvider {
1911

1912
                /**
1913
                 * The represented {@code long} value.
1914
                 */
1915
                private final long value;
1916

1917
                /**
1918
                 * Creates a new argument provider for a {@code long} value.
1919
                 *
1920
                 * @param value The represented {@code long} value.
1921
                 */
1922
                protected ForLongConstant(long value) {
×
1923
                    this.value = value;
×
1924
                }
×
1925

1926
                /**
1927
                 * {@inheritDoc}
1928
                 */
1929
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1930
                    return new Resolved.Simple(LongConstant.forValue(value), TypeDescription.ForLoadedType.of(long.class));
×
1931
                }
1932

1933
                /**
1934
                 * {@inheritDoc}
1935
                 */
1936
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1937
                    return instrumentedType;
×
1938
                }
1939
            }
1940

1941
            /**
1942
             * An argument provider for a {@code float} value.
1943
             */
1944
            @HashCodeAndEqualsPlugin.Enhance
1945
            class ForFloatConstant implements ArgumentProvider {
1946

1947
                /**
1948
                 * The represented {@code float} value.
1949
                 */
1950
                private final float value;
1951

1952
                /**
1953
                 * Creates a new argument provider for a {@code float} value.
1954
                 *
1955
                 * @param value The represented {@code float} value.
1956
                 */
1957
                protected ForFloatConstant(float value) {
×
1958
                    this.value = value;
×
1959
                }
×
1960

1961
                /**
1962
                 * {@inheritDoc}
1963
                 */
1964
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
1965
                    return new Resolved.Simple(FloatConstant.forValue(value), TypeDescription.ForLoadedType.of(float.class));
×
1966
                }
1967

1968
                /**
1969
                 * {@inheritDoc}
1970
                 */
1971
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
1972
                    return instrumentedType;
×
1973
                }
1974
            }
1975

1976
            /**
1977
             * An argument provider for a {@code double} value.
1978
             */
1979
            @HashCodeAndEqualsPlugin.Enhance
1980
            class ForDoubleConstant implements ArgumentProvider {
1981

1982
                /**
1983
                 * The represented {@code double} value.
1984
                 */
1985
                private final double value;
1986

1987
                /**
1988
                 * Creates a new argument provider for a {@code double} value.
1989
                 *
1990
                 * @param value The represented {@code double} value.
1991
                 */
1992
                protected ForDoubleConstant(double value) {
×
1993
                    this.value = value;
×
1994
                }
×
1995

1996
                /**
1997
                 * {@inheritDoc}
1998
                 */
1999
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
2000
                    return new Resolved.Simple(DoubleConstant.forValue(value), TypeDescription.ForLoadedType.of(double.class));
×
2001
                }
2002

2003
                /**
2004
                 * {@inheritDoc}
2005
                 */
2006
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
2007
                    return instrumentedType;
×
2008
                }
2009
            }
2010

2011
            /**
2012
             * An argument provider for a {@link java.lang.String} value.
2013
             */
2014
            @HashCodeAndEqualsPlugin.Enhance
2015
            class ForStringConstant implements ArgumentProvider {
2016

2017
                /**
2018
                 * The represented {@link java.lang.String} value.
2019
                 */
2020
                private final String value;
2021

2022
                /**
2023
                 * Creates a new argument provider for a {@link java.lang.String} value.
2024
                 *
2025
                 * @param value The represented {@link java.lang.String} value.
2026
                 */
2027
                protected ForStringConstant(String value) {
1✔
2028
                    this.value = value;
1✔
2029
                }
1✔
2030

2031
                /**
2032
                 * {@inheritDoc}
2033
                 */
2034
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
2035
                    return new Resolved.Simple(new TextConstant(value), TypeDescription.ForLoadedType.of(String.class));
1✔
2036
                }
2037

2038
                /**
2039
                 * {@inheritDoc}
2040
                 */
2041
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
2042
                    return instrumentedType;
1✔
2043
                }
2044
            }
2045

2046
            /**
2047
             * An argument provider for a {@link java.lang.Class} constant.
2048
             */
2049
            @HashCodeAndEqualsPlugin.Enhance
2050
            class ForClassConstant implements ArgumentProvider {
2051

2052
                /**
2053
                 * The type that is represented by this constant.
2054
                 */
2055
                private final TypeDescription typeDescription;
2056

2057
                /**
2058
                 * Creates a new argument provider for the given type description.
2059
                 *
2060
                 * @param typeDescription The type to represent.
2061
                 */
2062
                protected ForClassConstant(TypeDescription typeDescription) {
×
2063
                    this.typeDescription = typeDescription;
×
2064
                }
×
2065

2066
                /**
2067
                 * {@inheritDoc}
2068
                 */
2069
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
2070
                    return new Resolved.Simple(ClassConstant.of(typeDescription), TypeDescription.ForLoadedType.of(Class.class));
×
2071
                }
2072

2073
                /**
2074
                 * {@inheritDoc}
2075
                 */
2076
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
2077
                    return instrumentedType;
×
2078
                }
2079
            }
2080

2081
            /**
2082
             * An argument provider for an {@link java.lang.Enum} constant.
2083
             */
2084
            @HashCodeAndEqualsPlugin.Enhance
2085
            class ForEnumerationValue implements ArgumentProvider {
2086

2087
                /**
2088
                 * A description of the enumeration to represent.
2089
                 */
2090
                private final EnumerationDescription enumerationDescription;
2091

2092
                /**
2093
                 * Creates a new argument provider for an enumeration value.
2094
                 *
2095
                 * @param enumerationDescription A description of the enumeration to represent.
2096
                 */
2097
                protected ForEnumerationValue(EnumerationDescription enumerationDescription) {
×
2098
                    this.enumerationDescription = enumerationDescription;
×
2099
                }
×
2100

2101
                /**
2102
                 * {@inheritDoc}
2103
                 */
2104
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
2105
                    return new Resolved.Simple(FieldAccess.forEnumeration(enumerationDescription), enumerationDescription.getEnumerationType());
×
2106
                }
2107

2108
                /**
2109
                 * {@inheritDoc}
2110
                 */
2111
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
2112
                    return instrumentedType;
×
2113
                }
2114
            }
2115

2116
            /**
2117
             * An argument provider for the {@code null} value.
2118
             */
2119
            @HashCodeAndEqualsPlugin.Enhance
2120
            class ForNullValue implements ArgumentProvider {
2121

2122
                /**
2123
                 * The type to be represented by the {@code null} value.
2124
                 */
2125
                private final TypeDescription typeDescription;
2126

2127
                /**
2128
                 * Creates a new argument provider for the {@code null} value.
2129
                 *
2130
                 * @param typeDescription The type to be represented by the {@code null} value.
2131
                 */
2132
                protected ForNullValue(TypeDescription typeDescription) {
1✔
2133
                    this.typeDescription = typeDescription;
1✔
2134
                }
1✔
2135

2136
                /**
2137
                 * {@inheritDoc}
2138
                 */
2139
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
2140
                    return new Resolved.Simple(NullConstant.INSTANCE, typeDescription);
1✔
2141
                }
2142

2143
                /**
2144
                 * {@inheritDoc}
2145
                 */
2146
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
2147
                    return instrumentedType;
1✔
2148
                }
2149
            }
2150

2151
            /**
2152
             * An argument provider for a Java instance.
2153
             */
2154
            @HashCodeAndEqualsPlugin.Enhance
2155
            class ForJavaConstant implements ArgumentProvider {
2156

2157
                /**
2158
                 * The Java instance to provide to the bootstrapped method.
2159
                 */
2160
                private final ConstantValue constant;
2161

2162
                /**
2163
                 * Creates a new argument provider for the given Java instance.
2164
                 *
2165
                 * @param constant The Java instance to provide to the bootstrapped method.
2166
                 */
2167
                protected ForJavaConstant(ConstantValue constant) {
×
2168
                    this.constant = constant;
×
2169
                }
×
2170

2171
                /**
2172
                 * {@inheritDoc}
2173
                 */
2174
                public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) {
2175
                    return new Resolved.Simple(constant.toStackManipulation(), constant.getTypeDescription());
×
2176
                }
2177

2178
                /**
2179
                 * {@inheritDoc}
2180
                 */
2181
                public InstrumentedType prepare(InstrumentedType instrumentedType) {
2182
                    return instrumentedType;
×
2183
                }
2184
            }
2185
        }
2186

2187
        /**
2188
         * Provides the name of the method that is to be bound by a dynamic method call.
2189
         */
2190
        interface NameProvider {
2191

2192
            /**
2193
             * Resolves the name given the intercepted method.
2194
             *
2195
             * @param methodDescription The intercepted method.
2196
             * @return The name of the method to be bound by the bootstrap method.
2197
             */
2198
            String resolve(MethodDescription methodDescription);
2199

2200
            /**
2201
             * A name provider that provides the name of the intercepted method.
2202
             */
2203
            enum ForInterceptedMethod implements NameProvider {
1✔
2204

2205
                /**
2206
                 * The singleton instance.
2207
                 */
2208
                INSTANCE;
1✔
2209

2210
                /**
2211
                 * {@inheritDoc}
2212
                 */
2213
                public String resolve(MethodDescription methodDescription) {
2214
                    return methodDescription.getInternalName();
1✔
2215
                }
2216
            }
2217

2218
            /**
2219
             * A name provider that provides an explicit name.
2220
             */
2221
            @HashCodeAndEqualsPlugin.Enhance
2222
            class ForExplicitName implements NameProvider {
2223

2224
                /**
2225
                 * The name to be provided.
2226
                 */
2227
                private final String internalName;
2228

2229
                /**
2230
                 * Creates a new name provider for an explicit name.
2231
                 *
2232
                 * @param internalName The name to be provided.
2233
                 */
2234
                protected ForExplicitName(String internalName) {
1✔
2235
                    this.internalName = internalName;
1✔
2236
                }
1✔
2237

2238
                /**
2239
                 * {@inheritDoc}
2240
                 */
2241
                public String resolve(MethodDescription methodDescription) {
2242
                    return internalName;
1✔
2243
                }
2244
            }
2245
        }
2246

2247
        /**
2248
         * Provides the return type that is requested from the bootstrap method.
2249
         */
2250
        interface ReturnTypeProvider {
2251

2252
            /**
2253
             * Resolves the return type that is requested from the bootstrap method.
2254
             *
2255
             * @param methodDescription The intercepted method.
2256
             * @return The return type that is requested from the bootstrap method.
2257
             */
2258
            TypeDescription resolve(MethodDescription methodDescription);
2259

2260
            /**
2261
             * Requests the return type of the intercepted method.
2262
             */
2263
            enum ForInterceptedMethod implements ReturnTypeProvider {
1✔
2264

2265
                /**
2266
                 * The singleton instance.
2267
                 */
2268
                INSTANCE;
1✔
2269

2270
                /**
2271
                 * {@inheritDoc}
2272
                 */
2273
                public TypeDescription resolve(MethodDescription methodDescription) {
2274
                    return methodDescription.getReturnType().asErasure();
1✔
2275
                }
2276
            }
2277

2278
            /**
2279
             * Requests an explicit return type.
2280
             */
2281
            @HashCodeAndEqualsPlugin.Enhance
2282
            class ForExplicitType implements ReturnTypeProvider {
2283

2284
                /**
2285
                 * The requested return type.
2286
                 */
2287
                private final TypeDescription typeDescription;
2288

2289
                /**
2290
                 * Creates a new return type provider for an explicit return type.
2291
                 *
2292
                 * @param typeDescription The requested return type.
2293
                 */
2294
                protected ForExplicitType(TypeDescription typeDescription) {
1✔
2295
                    this.typeDescription = typeDescription;
1✔
2296
                }
1✔
2297

2298
                /**
2299
                 * {@inheritDoc}
2300
                 */
2301
                public TypeDescription resolve(MethodDescription methodDescription) {
2302
                    return typeDescription;
1✔
2303
                }
2304
            }
2305
        }
2306

2307
        /**
2308
         * An invocation provider that requests a synthetic dynamic invocation where all arguments are explicitly
2309
         * provided by the user.
2310
         */
2311
        @HashCodeAndEqualsPlugin.Enhance
2312
        class Default implements InvocationProvider {
2313

2314
            /**
2315
             * The provider for the name of the intercepted method.
2316
             */
2317
            private final NameProvider nameProvider;
2318

2319
            /**
2320
             * The provider for the required return type.
2321
             */
2322
            private final ReturnTypeProvider returnTypeProvider;
2323

2324
            /**
2325
             * The providers for the method arguments in their order.
2326
             */
2327
            private final List<ArgumentProvider> argumentProviders;
2328

2329
            /**
2330
             * Creates a new default invocation provider that provides information and arguments of the
2331
             * intercepted method.
2332
             */
2333
            protected Default() {
2334
                this(NameProvider.ForInterceptedMethod.INSTANCE,
1✔
2335
                        ReturnTypeProvider.ForInterceptedMethod.INSTANCE,
2336
                        Collections.<ArgumentProvider>singletonList(ArgumentProvider.ForInterceptedMethodInstanceAndParameters.INSTANCE));
1✔
2337
            }
1✔
2338

2339
            /**
2340
             * Creates a new default invocation provider.
2341
             *
2342
             * @param nameProvider       The provider for the name of the intercepted method.
2343
             * @param returnTypeProvider The provider for the required return type.
2344
             * @param argumentProviders  The providers for the method arguments in their order.
2345
             */
2346
            protected Default(NameProvider nameProvider,
2347
                              ReturnTypeProvider returnTypeProvider,
2348
                              List<ArgumentProvider> argumentProviders) {
1✔
2349
                this.nameProvider = nameProvider;
1✔
2350
                this.returnTypeProvider = returnTypeProvider;
1✔
2351
                this.argumentProviders = argumentProviders;
1✔
2352
            }
1✔
2353

2354
            /**
2355
             * {@inheritDoc}
2356
             */
2357
            public Target make(MethodDescription methodDescription) {
2358
                return new Target(nameProvider.resolve(methodDescription),
1✔
2359
                        returnTypeProvider.resolve(methodDescription),
1✔
2360
                        argumentProviders,
2361
                        methodDescription);
2362
            }
2363

2364
            /**
2365
             * {@inheritDoc}
2366
             */
2367
            public InvocationProvider appendArguments(List<ArgumentProvider> argumentProviders) {
2368
                return new Default(nameProvider,
1✔
2369
                        returnTypeProvider,
2370
                        CompoundList.of(this.argumentProviders, argumentProviders));
1✔
2371
            }
2372

2373
            /**
2374
             * {@inheritDoc}
2375
             */
2376
            public InvocationProvider appendArgument(ArgumentProvider argumentProvider) {
2377
                return new Default(nameProvider,
1✔
2378
                        returnTypeProvider,
2379
                        CompoundList.of(this.argumentProviders, argumentProvider));
1✔
2380
            }
2381

2382
            /**
2383
             * {@inheritDoc}
2384
             */
2385
            public InvocationProvider withoutArguments() {
2386
                return new Default(nameProvider,
1✔
2387
                        returnTypeProvider,
2388
                        Collections.<ArgumentProvider>emptyList());
1✔
2389
            }
2390

2391
            /**
2392
             * {@inheritDoc}
2393
             */
2394
            public InvocationProvider withNameProvider(NameProvider nameProvider) {
2395
                return new Default(nameProvider,
1✔
2396
                        returnTypeProvider,
2397
                        argumentProviders);
2398
            }
2399

2400
            /**
2401
             * {@inheritDoc}
2402
             */
2403
            public InvocationProvider withReturnTypeProvider(ReturnTypeProvider returnTypeProvider) {
2404
                return new Default(nameProvider,
1✔
2405
                        returnTypeProvider,
2406
                        argumentProviders);
2407
            }
2408

2409
            /**
2410
             * {@inheritDoc}
2411
             */
2412
            public InstrumentedType prepare(InstrumentedType instrumentedType) {
2413
                for (ArgumentProvider argumentProvider : argumentProviders) {
1✔
2414
                    instrumentedType = argumentProvider.prepare(instrumentedType);
1✔
2415
                }
1✔
2416
                return instrumentedType;
1✔
2417
            }
2418

2419
            /**
2420
             * A target for a synthetically bound method call.
2421
             */
2422
            @HashCodeAndEqualsPlugin.Enhance
2423
            protected static class Target implements InvocationProvider.Target {
2424

2425
                /**
2426
                 * The name to be passed to the bootstrap method.
2427
                 */
2428
                private final String internalName;
2429

2430
                /**
2431
                 * The return type to be requested from the bootstrapping method.
2432
                 */
2433
                private final TypeDescription returnType;
2434

2435
                /**
2436
                 * The arguments to be passed to the bootstrap method.
2437
                 */
2438
                private final List<ArgumentProvider> argumentProviders;
2439

2440
                /**
2441
                 * The intercepted method.
2442
                 */
2443
                private final MethodDescription instrumentedMethod;
2444

2445
                /**
2446
                 * Creates a new target.
2447
                 *
2448
                 * @param internalName       The name to be passed to the bootstrap method.
2449
                 * @param returnType         The return type to be requested from the bootstrapping method.
2450
                 * @param argumentProviders  The arguments to be passed to the bootstrap method.
2451
                 * @param instrumentedMethod The intercepted method.
2452
                 */
2453
                protected Target(String internalName,
2454
                                 TypeDescription returnType,
2455
                                 List<ArgumentProvider> argumentProviders,
2456
                                 MethodDescription instrumentedMethod) {
1✔
2457
                    this.internalName = internalName;
1✔
2458
                    this.returnType = returnType;
1✔
2459
                    this.argumentProviders = argumentProviders;
1✔
2460
                    this.instrumentedMethod = instrumentedMethod;
1✔
2461
                }
1✔
2462

2463
                /**
2464
                 * {@inheritDoc}
2465
                 */
2466
                public InvocationProvider.Target.Resolved resolve(TypeDescription instrumentedType, Assigner assigner, Assigner.Typing typing) {
2467
                    StackManipulation[] stackManipulation = new StackManipulation[argumentProviders.size()];
1✔
2468
                    List<TypeDescription> parameterTypes = new ArrayList<TypeDescription>();
1✔
2469
                    int index = 0;
1✔
2470
                    for (ArgumentProvider argumentProvider : argumentProviders) {
1✔
2471
                        ArgumentProvider.Resolved resolved = argumentProvider.resolve(instrumentedType, instrumentedMethod, assigner, typing);
1✔
2472
                        parameterTypes.addAll(resolved.getLoadedTypes());
1✔
2473
                        stackManipulation[index++] = resolved.getLoadInstruction();
1✔
2474
                    }
1✔
2475
                    return new Resolved.Simple(new StackManipulation.Compound(stackManipulation),
1✔
2476
                            internalName,
2477
                            returnType,
2478
                            parameterTypes);
2479
                }
2480
            }
2481
        }
2482
    }
2483

2484
    /**
2485
     * A termination handler is responsible to handle the return value of a method that is invoked via a
2486
     * {@link net.bytebuddy.implementation.InvokeDynamic}.
2487
     */
2488
    protected enum TerminationHandler {
1✔
2489

2490
        /**
2491
         * A termination handler that returns the bound method's return value.
2492
         */
2493
        RETURNING {
1✔
2494
            @Override
2495
            protected StackManipulation resolve(MethodDescription interceptedMethod, TypeDescription returnType, Assigner assigner, Assigner.Typing typing) {
2496
                StackManipulation stackManipulation = assigner.assign(returnType.asGenericType(), interceptedMethod.getReturnType(), typing);
1✔
2497
                if (!stackManipulation.isValid()) {
1✔
2498
                    throw new IllegalStateException("Cannot return " + returnType + " from " + interceptedMethod);
×
2499
                }
2500
                return new StackManipulation.Compound(stackManipulation, MethodReturn.of(interceptedMethod.getReturnType()));
1✔
2501
            }
2502
        },
2503

2504
        /**
2505
         * A termination handler that drops the bound method's return value.
2506
         */
2507
        DROPPING {
1✔
2508
            @Override
2509
            protected StackManipulation resolve(MethodDescription interceptedMethod, TypeDescription returnType, Assigner assigner, Assigner.Typing typing) {
2510
                return Removal.of(returnType);
1✔
2511
            }
2512
        };
2513

2514
        /**
2515
         * Returns a stack manipulation that handles the method return.
2516
         *
2517
         * @param interceptedMethod The method being intercepted.
2518
         * @param returnType        The return type of the instrumented method.
2519
         * @param assigner          The assigner to use.
2520
         * @param typing            Indicates if dynamic type castings should be attempted for incompatible assignments.
2521
         * @return A stack manipulation that handles the method return.
2522
         */
2523
        protected abstract StackManipulation resolve(MethodDescription interceptedMethod,
2524
                                                     TypeDescription returnType,
2525
                                                     Assigner assigner,
2526
                                                     Assigner.Typing typing);
2527
    }
2528

2529
    /**
2530
     * An abstract delegator that allows to specify a configuration for any specification of an argument.
2531
     */
2532
    protected abstract static class AbstractDelegator extends InvokeDynamic {
2533

2534
        /**
2535
         * Creates a new abstract delegator for a dynamic method invocation.
2536
         *
2537
         * @param bootstrap          The bootstrap method or constructor.
2538
         * @param arguments          The arguments that are provided to the bootstrap method or constructor.
2539
         * @param invocationProvider The target provided that identifies the method to be bootstrapped.
2540
         * @param terminationHandler A handler that handles the method return.
2541
         * @param assigner           The assigner to be used.
2542
         * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
2543
         */
2544
        protected AbstractDelegator(MethodDescription.InDefinedShape bootstrap,
2545
                                    List<? extends JavaConstant> arguments,
2546
                                    InvocationProvider invocationProvider,
2547
                                    TerminationHandler terminationHandler,
2548
                                    Assigner assigner,
2549
                                    Assigner.Typing typing) {
2550
            super(bootstrap, arguments, invocationProvider, terminationHandler, assigner, typing);
1✔
2551
        }
1✔
2552

2553
        /**
2554
         * Resolves the current configuration into a fully initialized invoke dynamic instance.
2555
         *
2556
         * @return The fully resolved invoke dynamic instance.
2557
         */
2558
        protected abstract InvokeDynamic materialize();
2559

2560
        /**
2561
         * {@inheritDoc}
2562
         */
2563
        public InvokeDynamic withBooleanValue(boolean... value) {
2564
            return materialize().withBooleanValue(value);
×
2565
        }
2566

2567
        /**
2568
         * {@inheritDoc}
2569
         */
2570
        public InvokeDynamic withByteValue(byte... value) {
2571
            return materialize().withByteValue(value);
×
2572
        }
2573

2574
        /**
2575
         * {@inheritDoc}
2576
         */
2577
        public InvokeDynamic withShortValue(short... value) {
2578
            return materialize().withShortValue(value);
×
2579
        }
2580

2581
        /**
2582
         * {@inheritDoc}
2583
         */
2584
        public InvokeDynamic withCharacterValue(char... value) {
2585
            return materialize().withCharacterValue(value);
×
2586
        }
2587

2588
        /**
2589
         * {@inheritDoc}
2590
         */
2591
        public InvokeDynamic withIntegerValue(int... value) {
2592
            return materialize().withIntegerValue(value);
×
2593
        }
2594

2595
        /**
2596
         * {@inheritDoc}
2597
         */
2598
        public InvokeDynamic withLongValue(long... value) {
2599
            return materialize().withLongValue(value);
×
2600
        }
2601

2602
        /**
2603
         * {@inheritDoc}
2604
         */
2605
        public InvokeDynamic withFloatValue(float... value) {
2606
            return materialize().withFloatValue(value);
×
2607
        }
2608

2609
        /**
2610
         * {@inheritDoc}
2611
         */
2612
        public InvokeDynamic withDoubleValue(double... value) {
2613
            return materialize().withDoubleValue(value);
×
2614
        }
2615

2616
        /**
2617
         * {@inheritDoc}
2618
         */
2619
        public InvokeDynamic withValue(Object... value) {
2620
            return materialize().withValue(value);
1✔
2621
        }
2622

2623
        /**
2624
         * {@inheritDoc}
2625
         */
2626
        public WithImplicitType withReference(Object value) {
2627
            return materialize().withReference(value);
1✔
2628
        }
2629

2630
        /**
2631
         * {@inheritDoc}
2632
         */
2633
        public InvokeDynamic withReference(Object... value) {
2634
            return materialize().withReference(value);
1✔
2635
        }
2636

2637
        /**
2638
         * {@inheritDoc}
2639
         */
2640
        public InvokeDynamic withType(TypeDescription... typeDescription) {
2641
            return materialize().withType(typeDescription);
×
2642
        }
2643

2644
        /**
2645
         * {@inheritDoc}
2646
         */
2647
        public InvokeDynamic withInstance(JavaConstant... javaConstant) {
2648
            return materialize().withInstance(javaConstant);
×
2649
        }
2650

2651
        /**
2652
         * {@inheritDoc}
2653
         */
2654
        public InvokeDynamic withNullValue(Class<?>... type) {
2655
            return materialize().withNullValue(type);
1✔
2656
        }
2657

2658
        /**
2659
         * {@inheritDoc}
2660
         */
2661
        public InvokeDynamic withNullValue(TypeDescription... typeDescription) {
2662
            return materialize().withNullValue(typeDescription);
×
2663
        }
2664

2665
        /**
2666
         * {@inheritDoc}
2667
         */
2668
        public InvokeDynamic withArgument(int... index) {
2669
            return materialize().withArgument(index);
×
2670
        }
2671

2672
        /**
2673
         * {@inheritDoc}
2674
         */
2675
        public WithImplicitType withArgument(int index) {
2676
            return materialize().withArgument(index);
1✔
2677
        }
2678

2679
        /**
2680
         * {@inheritDoc}
2681
         */
2682
        public InvokeDynamic withThis(Class<?>... type) {
2683
            return materialize().withThis(type);
1✔
2684
        }
2685

2686
        /**
2687
         * {@inheritDoc}
2688
         */
2689
        public InvokeDynamic withThis(TypeDescription... typeDescription) {
2690
            return materialize().withThis(typeDescription);
×
2691
        }
2692

2693
        /**
2694
         * {@inheritDoc}
2695
         */
2696
        public InvokeDynamic withMethodArguments() {
2697
            return materialize().withMethodArguments();
1✔
2698
        }
2699

2700
        /**
2701
         * {@inheritDoc}
2702
         */
2703
        public InvokeDynamic withImplicitAndMethodArguments() {
2704
            return materialize().withImplicitAndMethodArguments();
×
2705
        }
2706

2707
        /**
2708
         * {@inheritDoc}
2709
         */
2710
        public InvokeDynamic withField(String... fieldName) {
2711
            return materialize().withField(fieldName);
×
2712
        }
2713

2714
        /**
2715
         * {@inheritDoc}
2716
         */
2717
        public InvokeDynamic withEnumeration(EnumerationDescription... enumerationDescription) {
2718
            return materialize().withEnumeration(enumerationDescription);
×
2719
        }
2720

2721
        /**
2722
         * {@inheritDoc}
2723
         */
2724
        public InvokeDynamic withField(FieldLocator.Factory fieldLocatorFactory, String... name) {
2725
            return materialize().withField(fieldLocatorFactory, name);
×
2726
        }
2727

2728
        /**
2729
         * {@inheritDoc}
2730
         */
2731
        public WithImplicitType withField(String name) {
2732
            return materialize().withField(name);
1✔
2733
        }
2734

2735
        /**
2736
         * {@inheritDoc}
2737
         */
2738
        public WithImplicitType withField(String name, FieldLocator.Factory fieldLocatorFactory) {
2739
            return materialize().withField(name, fieldLocatorFactory);
×
2740
        }
2741

2742
        /**
2743
         * {@inheritDoc}
2744
         */
2745
        public Composable withAssigner(Assigner assigner, Assigner.Typing typing) {
2746
            return materialize().withAssigner(assigner, typing);
1✔
2747
        }
2748

2749
        /**
2750
         * {@inheritDoc}
2751
         */
2752
        public Implementation andThen(Implementation implementation) {
2753
            return materialize().andThen(implementation);
1✔
2754
        }
2755

2756
        /**
2757
         * {@inheritDoc}
2758
         */
2759
        public InstrumentedType prepare(InstrumentedType instrumentedType) {
2760
            return materialize().prepare(instrumentedType);
1✔
2761
        }
2762

2763
        /**
2764
         * {@inheritDoc}
2765
         */
2766
        public ByteCodeAppender appender(Target implementationTarget) {
2767
            return materialize().appender(implementationTarget);
1✔
2768
        }
2769
    }
2770

2771
    /**
2772
     * Representation of an {@link net.bytebuddy.implementation.InvokeDynamic} implementation where the bootstrapped
2773
     * method is passed a {@code this} reference, if available, and any arguments of the instrumented method.
2774
     */
2775
    public static class WithImplicitArguments extends AbstractDelegator {
2776

2777
        /**
2778
         * Creates a new dynamic method invocation with implicit arguments.
2779
         *
2780
         * @param bootstrap          The bootstrap method or constructor.
2781
         * @param arguments          The arguments that are provided to the bootstrap method or constructor.
2782
         * @param invocationProvider The target provided that identifies the method to be bootstrapped.
2783
         * @param terminationHandler A handler that handles the method return.
2784
         * @param assigner           The assigner to be used.
2785
         * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
2786
         */
2787
        protected WithImplicitArguments(MethodDescription.InDefinedShape bootstrap,
2788
                                        List<? extends JavaConstant> arguments,
2789
                                        InvocationProvider invocationProvider,
2790
                                        TerminationHandler terminationHandler,
2791
                                        Assigner assigner,
2792
                                        Assigner.Typing typing) {
2793
            super(bootstrap,
1✔
2794
                    arguments,
2795
                    invocationProvider,
2796
                    terminationHandler,
2797
                    assigner,
2798
                    typing);
2799
        }
1✔
2800

2801
        /**
2802
         * Returns an instance of this instrumentation where the bootstrapped method is not passed any arguments.
2803
         *
2804
         * @return This implementation where the bootstrapped method is not passed any arguments.
2805
         */
2806
        public InvokeDynamic withoutArguments() {
2807
            return new InvokeDynamic(bootstrap,
1✔
2808
                    arguments,
2809
                    invocationProvider.withoutArguments(),
1✔
2810
                    terminationHandler,
2811
                    assigner,
2812
                    typing);
2813
        }
2814

2815
        @Override
2816
        protected InvokeDynamic materialize() {
2817
            return withoutArguments();
1✔
2818
        }
2819

2820
        /**
2821
         * {@inheritDoc}
2822
         */
2823
        public WithImplicitArguments withAssigner(Assigner assigner, Assigner.Typing typing) {
2824
            return new WithImplicitArguments(bootstrap,
×
2825
                    arguments,
2826
                    invocationProvider,
2827
                    terminationHandler,
2828
                    assigner,
2829
                    typing);
2830
        }
2831
    }
2832

2833
    /**
2834
     * Representation of an {@link net.bytebuddy.implementation.InvokeDynamic} implementation where the bootstrapped
2835
     * method is passed a {@code this} reference, if available, and any arguments of the instrumented method and
2836
     * where the invocation target is implicit.
2837
     */
2838
    public static class WithImplicitTarget extends WithImplicitArguments {
2839

2840
        /**
2841
         * Creates a new dynamic method invocation with implicit arguments and an implicit invocation target.
2842
         *
2843
         * @param bootstrap          The bootstrap method or constructor.
2844
         * @param arguments          The arguments that are provided to the bootstrap method.
2845
         * @param invocationProvider The target provided that identifies the method to be bootstrapped.
2846
         * @param terminationHandler A handler that handles the method return.
2847
         * @param assigner           The assigner to be used.
2848
         * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
2849
         */
2850
        protected WithImplicitTarget(MethodDescription.InDefinedShape bootstrap,
2851
                                     List<? extends JavaConstant> arguments,
2852
                                     InvocationProvider invocationProvider,
2853
                                     TerminationHandler terminationHandler,
2854
                                     Assigner assigner,
2855
                                     Assigner.Typing typing) {
2856
            super(bootstrap,
1✔
2857
                    arguments,
2858
                    invocationProvider,
2859
                    terminationHandler,
2860
                    assigner,
2861
                    typing);
2862
        }
1✔
2863

2864
        /**
2865
         * Requests the bootstrap method to bind a method with the given return type. The return type
2866
         * is assigned to the intercepted method's return type.
2867
         *
2868
         * @param returnType The return type to request from the bootstrapping method.
2869
         * @return This implementation where the bootstrap method is requested to bind a method with the given
2870
         * return type.
2871
         */
2872
        public InvokeDynamic.WithImplicitArguments invoke(Class<?> returnType) {
2873
            return invoke(TypeDescription.ForLoadedType.of(returnType));
×
2874
        }
2875

2876
        /**
2877
         * Requests the bootstrap method to bind a method with the given return type. The return type
2878
         * is assigned to the intercepted method's return type.
2879
         *
2880
         * @param returnType The return type to request from the bootstrapping method.
2881
         * @return This implementation where the bootstrap method is requested to bind a method with the given
2882
         * return type.
2883
         */
2884
        public InvokeDynamic.WithImplicitArguments invoke(TypeDescription returnType) {
2885
            return new WithImplicitArguments(bootstrap,
×
2886
                    arguments,
2887
                    invocationProvider.withReturnTypeProvider(new InvocationProvider.ReturnTypeProvider.ForExplicitType(returnType)),
×
2888
                    terminationHandler,
2889
                    assigner,
2890
                    typing);
2891
        }
2892

2893
        /**
2894
         * Requests the bootstrap method is passed the given method name.
2895
         *
2896
         * @param methodName The method name to pass to the bootstrapping method.
2897
         * @return This implementation where the bootstrap method is passed the given method name.
2898
         */
2899
        public InvokeDynamic.WithImplicitArguments invoke(String methodName) {
2900
            return new WithImplicitArguments(bootstrap,
1✔
2901
                    arguments,
2902
                    invocationProvider.withNameProvider(new InvocationProvider.NameProvider.ForExplicitName(methodName)),
1✔
2903
                    terminationHandler,
2904
                    assigner,
2905
                    typing);
2906
        }
2907

2908
        /**
2909
         * Requests the bootstrap method to bind a method with the given return type. The return type
2910
         * is assigned to the intercepted method's return type. Also, the bootstrap method is passed the
2911
         * given method name.
2912
         *
2913
         * @param methodName The method name to pass to the bootstrapping method.
2914
         * @param returnType The return type to request from the bootstrapping method.
2915
         * @return This implementation where the bootstrap method is requested to bind a method with the given
2916
         * return type while being passed the given method name.
2917
         */
2918
        public InvokeDynamic.WithImplicitArguments invoke(String methodName, Class<?> returnType) {
2919
            return invoke(methodName, TypeDescription.ForLoadedType.of(returnType));
1✔
2920
        }
2921

2922
        /**
2923
         * Requests the bootstrap method to bind a method with the given return type. The return type
2924
         * is assigned to the intercepted method's return type. Also, the bootstrap method is passed the
2925
         * given method name.
2926
         *
2927
         * @param methodName The method name to pass to the bootstrapping method.
2928
         * @param returnType The return type to request from the bootstrapping method.
2929
         * @return This implementation where the bootstrap method is requested to bind a method with the given
2930
         * return type while being passed the given method name.
2931
         */
2932
        public InvokeDynamic.WithImplicitArguments invoke(String methodName, TypeDescription returnType) {
2933
            return new WithImplicitArguments(bootstrap,
1✔
2934
                    arguments,
2935
                    invocationProvider
2936
                            .withNameProvider(new InvocationProvider.NameProvider.ForExplicitName(methodName))
1✔
2937
                            .withReturnTypeProvider(new InvocationProvider.ReturnTypeProvider.ForExplicitType(returnType)),
1✔
2938
                    terminationHandler,
2939
                    assigner,
2940
                    typing);
2941
        }
2942
    }
2943

2944
    /**
2945
     * An {@link InvokeDynamic} invocation where the last argument is assigned its implicit type.
2946
     */
2947
    public abstract static class WithImplicitType extends AbstractDelegator {
2948

2949
        /**
2950
         * Creates a new abstract delegator for a dynamic method invocation where the last argument is assigned an implicit type.
2951
         *
2952
         * @param bootstrap          The bootstrap method or constructor.
2953
         * @param arguments          The arguments that are provided to the bootstrap method or constructor.
2954
         * @param invocationProvider The target provided that identifies the method to be bootstrapped.
2955
         * @param terminationHandler A handler that handles the method return.
2956
         * @param assigner           The assigner to be used.
2957
         * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
2958
         */
2959
        protected WithImplicitType(MethodDescription.InDefinedShape bootstrap,
2960
                                   List<? extends JavaConstant> arguments,
2961
                                   InvocationProvider invocationProvider,
2962
                                   TerminationHandler terminationHandler,
2963
                                   Assigner assigner,
2964
                                   Assigner.Typing typing) {
2965
            super(bootstrap, arguments, invocationProvider, terminationHandler, assigner, typing);
1✔
2966
        }
1✔
2967

2968
        /**
2969
         * Represents the last value as an instance of the given type.
2970
         *
2971
         * @param type The type to represent to the dynamic method invocation.
2972
         * @return A new dynamic method invocation where the last argument is represented by the given type.
2973
         */
2974
        public InvokeDynamic as(Class<?> type) {
2975
            return as(TypeDescription.ForLoadedType.of(type));
1✔
2976
        }
2977

2978
        /**
2979
         * Represents the last value as an instance of the given type.
2980
         *
2981
         * @param typeDescription The type to represent to the dynamic method invocation.
2982
         * @return A new dynamic method invocation where the last argument is represented by the given type.
2983
         */
2984
        public abstract InvokeDynamic as(TypeDescription typeDescription);
2985

2986
        /**
2987
         * A step in the invoke dynamic domain specific language that allows to explicitly specify a field type for a reference value.
2988
         */
2989
        @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS", justification = "Super type implementation covers use case")
2990
        protected static class OfInstance extends WithImplicitType {
2991

2992
            /**
2993
             * The value that is supplied as the next argument to the bootstrapped method.
2994
             */
2995
            private final Object value;
2996

2997
            /**
2998
             * An argument provider that represents the argument with an implicit type.
2999
             */
3000
            private final InvocationProvider.ArgumentProvider argumentProvider;
3001

3002
            /**
3003
             * Creates a new invoke dynamic instance with an implicit field type for the provided value.
3004
             *
3005
             * @param bootstrap          The bootstrap method or constructor.
3006
             * @param arguments          The arguments that are provided to the bootstrap method or constructor.
3007
             * @param invocationProvider The target provided that identifies the method to be bootstrapped.
3008
             * @param terminationHandler A handler that handles the method return.
3009
             * @param assigner           The assigner to be used.
3010
             * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
3011
             * @param value              The value that is supplied as the next argument to the bootstrapped method.
3012
             */
3013
            protected OfInstance(MethodDescription.InDefinedShape bootstrap,
3014
                                 List<? extends JavaConstant> arguments,
3015
                                 InvocationProvider invocationProvider,
3016
                                 TerminationHandler terminationHandler,
3017
                                 Assigner assigner,
3018
                                 Assigner.Typing typing,
3019
                                 Object value) {
3020
                super(bootstrap, arguments, invocationProvider, terminationHandler, assigner, typing);
1✔
3021
                this.value = value;
1✔
3022
                this.argumentProvider = InvocationProvider.ArgumentProvider.ForInstance.of(value);
1✔
3023
            }
1✔
3024

3025
            @Override
3026
            public InvokeDynamic as(TypeDescription typeDescription) {
3027
                if (!typeDescription.asBoxed().isInstance(value)) {
1✔
3028
                    throw new IllegalArgumentException(value + " is not of type " + typeDescription);
1✔
3029
                }
3030
                return new InvokeDynamic(bootstrap,
1✔
3031
                        arguments,
3032
                        invocationProvider.appendArgument(new InvocationProvider.ArgumentProvider.ForInstance(value, typeDescription)),
1✔
3033
                        terminationHandler,
3034
                        assigner,
3035
                        typing);
3036
            }
3037

3038
            @Override
3039
            protected InvokeDynamic materialize() {
3040
                return new InvokeDynamic(bootstrap,
1✔
3041
                        arguments,
3042
                        invocationProvider.appendArgument(argumentProvider),
1✔
3043
                        terminationHandler,
3044
                        assigner,
3045
                        typing);
3046
            }
3047
        }
3048

3049
        /**
3050
         * An invoke dynamic implementation where the last argument is an implicitly typed method argument.
3051
         */
3052
        @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS", justification = "Super type implementation covers use case")
3053
        protected static class OfArgument extends WithImplicitType {
3054

3055
            /**
3056
             * The index of the method argument.
3057
             */
3058
            private final int index;
3059

3060
            /**
3061
             * Creates a new invoke dynamic instance with an implicit field type for the provided value.
3062
             *
3063
             * @param bootstrap          The bootstrap method or constructor.
3064
             * @param arguments          The arguments that are provided to the bootstrap method or constructor.
3065
             * @param invocationProvider The target provided that identifies the method to be bootstrapped.
3066
             * @param terminationHandler A handler that handles the method return.
3067
             * @param assigner           The assigner to be used.
3068
             * @param typing             Indicates if dynamic type castings should be attempted for incompatible assignments.
3069
             * @param index              The index of of the argument to supply to the bootstrapped method.
3070
             */
3071
            protected OfArgument(MethodDescription.InDefinedShape bootstrap,
3072
                                 List<? extends JavaConstant> arguments,
3073
                                 InvocationProvider invocationProvider,
3074
                                 TerminationHandler terminationHandler,
3075
                                 Assigner assigner,
3076
                                 Assigner.Typing typing,
3077
                                 int index) {
3078
                super(bootstrap, arguments, invocationProvider, terminationHandler, assigner, typing);
1✔
3079
                this.index = index;
1✔
3080
            }
1✔
3081

3082
            @Override
3083
            public InvokeDynamic as(TypeDescription typeDescription) {
3084
                return new InvokeDynamic(bootstrap,
×
3085
                        arguments,
3086
                        invocationProvider.appendArgument(new InvocationProvider.ArgumentProvider.ForMethodParameter.WithExplicitType(index, typeDescription)),
×
3087
                        terminationHandler,
3088
                        assigner,
3089
                        typing);
3090
            }
3091

3092
            @Override
3093
            protected InvokeDynamic materialize() {
3094
                return new InvokeDynamic(bootstrap,
1✔
3095
                        arguments,
3096
                        invocationProvider.appendArgument(new InvocationProvider.ArgumentProvider.ForMethodParameter(index)),
1✔
3097
                        terminationHandler,
3098
                        assigner,
3099
                        typing);
3100
            }
3101
        }
3102

3103
        /**
3104
         * An invoke dynamic implementation where the last argument is an implicitly typed field value.
3105
         */
3106
        @SuppressFBWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS", justification = "Super type implementation covers use case")
3107
        protected static class OfField extends WithImplicitType {
3108

3109
            /**
3110
             * The field name.
3111
             */
3112
            private final String fieldName;
3113

3114
            /**
3115
             * The field locator factory to use.
3116
             */
3117
            private final FieldLocator.Factory fieldLocatorFactory;
3118

3119
            /**
3120
             * Creates a new abstract delegator for a dynamic method invocation where the last argument is assigned an implicit type.
3121
             *
3122
             * @param bootstrap           The bootstrap method or constructor.
3123
             * @param arguments           The arguments that are provided to the bootstrap method.
3124
             * @param invocationProvider  The target provided that identifies the method to be bootstrapped.
3125
             * @param terminationHandler  A handler that handles the method return.
3126
             * @param assigner            The assigner to be used.
3127
             * @param typing              Indicates if dynamic type castings should be attempted for incompatible assignments.
3128
             * @param fieldName           The field name.
3129
             * @param fieldLocatorFactory The field locator factory to use.
3130
             */
3131
            protected OfField(MethodDescription.InDefinedShape bootstrap,
3132
                              List<? extends JavaConstant> arguments,
3133
                              InvocationProvider invocationProvider,
3134
                              TerminationHandler terminationHandler,
3135
                              Assigner assigner,
3136
                              Assigner.Typing typing,
3137
                              String fieldName,
3138
                              FieldLocator.Factory fieldLocatorFactory) {
3139
                super(bootstrap, arguments, invocationProvider, terminationHandler, assigner, typing);
1✔
3140
                this.fieldName = fieldName;
1✔
3141
                this.fieldLocatorFactory = fieldLocatorFactory;
1✔
3142
            }
1✔
3143

3144
            @Override
3145
            public InvokeDynamic as(TypeDescription typeDescription) {
3146
                return new InvokeDynamic(bootstrap,
1✔
3147
                        arguments,
3148
                        invocationProvider.appendArgument(new InvocationProvider.ArgumentProvider.ForField.WithExplicitType(fieldName, fieldLocatorFactory, typeDescription)),
1✔
3149
                        terminationHandler,
3150
                        assigner,
3151
                        typing);
3152
            }
3153

3154
            @Override
3155
            protected InvokeDynamic materialize() {
3156
                return new InvokeDynamic(bootstrap,
1✔
3157
                        arguments,
3158
                        invocationProvider.appendArgument(new InvocationProvider.ArgumentProvider.ForField(fieldName, fieldLocatorFactory)),
1✔
3159
                        terminationHandler,
3160
                        assigner,
3161
                        typing);
3162
            }
3163
        }
3164
    }
3165

3166
    /**
3167
     * The byte code appender to be used by the {@link net.bytebuddy.implementation.InvokeDynamic} implementation.
3168
     */
3169
    @HashCodeAndEqualsPlugin.Enhance(includeSyntheticFields = true)
3170
    protected class Appender implements ByteCodeAppender {
3171

3172
        /**
3173
         * The instrumented type of the current implementation.
3174
         */
3175
        private final TypeDescription instrumentedType;
3176

3177
        /**
3178
         * Creates a new byte code appender for an invoke dynamic implementation.
3179
         *
3180
         * @param instrumentedType The instrumented type of the current implementation.
3181
         */
3182
        public Appender(TypeDescription instrumentedType) {
1✔
3183
            this.instrumentedType = instrumentedType;
1✔
3184
        }
1✔
3185

3186
        /**
3187
         * {@inheritDoc}
3188
         */
3189
        public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) {
3190
            InvocationProvider.Target.Resolved target = invocationProvider.make(instrumentedMethod).resolve(instrumentedType, assigner, typing);
1✔
3191
            StackManipulation.Size size = new StackManipulation.Compound(
1✔
3192
                    target.getStackManipulation(),
1✔
3193
                    MethodInvocation.invoke(bootstrap).dynamic(target.getInternalName(),
1✔
3194
                            target.getReturnType(),
1✔
3195
                            target.getParameterTypes(),
1✔
3196
                            arguments),
3197
                    terminationHandler.resolve(instrumentedMethod, target.getReturnType(), assigner, typing)
1✔
3198
            ).apply(methodVisitor, implementationContext);
1✔
3199
            return new Size(size.getMaximalSize(), instrumentedMethod.getStackSize());
1✔
3200
        }
3201
    }
3202
}
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