• 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

95.9
/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/InstrumentedType.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.dynamic.scaffold;
17

18
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19
import net.bytebuddy.ClassFileVersion;
20
import net.bytebuddy.description.annotation.AnnotationDescription;
21
import net.bytebuddy.description.annotation.AnnotationList;
22
import net.bytebuddy.description.annotation.AnnotationValue;
23
import net.bytebuddy.description.field.FieldDescription;
24
import net.bytebuddy.description.field.FieldList;
25
import net.bytebuddy.description.method.MethodDescription;
26
import net.bytebuddy.description.method.MethodList;
27
import net.bytebuddy.description.method.ParameterDescription;
28
import net.bytebuddy.description.modifier.ModifierContributor;
29
import net.bytebuddy.description.type.PackageDescription;
30
import net.bytebuddy.description.type.RecordComponentDescription;
31
import net.bytebuddy.description.type.RecordComponentList;
32
import net.bytebuddy.description.type.TypeDescription;
33
import net.bytebuddy.description.type.TypeList;
34
import net.bytebuddy.description.type.TypeVariableToken;
35
import net.bytebuddy.dynamic.TargetType;
36
import net.bytebuddy.dynamic.Transformer;
37
import net.bytebuddy.implementation.LoadedTypeInitializer;
38
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
39
import net.bytebuddy.matcher.ElementMatcher;
40
import net.bytebuddy.utility.CompoundList;
41
import net.bytebuddy.utility.JavaType;
42
import net.bytebuddy.utility.nullability.MaybeNull;
43
import org.objectweb.asm.Opcodes;
44

45
import java.lang.annotation.ElementType;
46
import java.util.ArrayList;
47
import java.util.Arrays;
48
import java.util.Collections;
49
import java.util.HashMap;
50
import java.util.HashSet;
51
import java.util.List;
52
import java.util.Map;
53
import java.util.Set;
54

55
import static net.bytebuddy.matcher.ElementMatchers.is;
56
import static net.bytebuddy.matcher.ElementMatchers.not;
57

58
/**
59
 * Implementations of this interface represent an instrumented type that is subject to change. Implementations
60
 * should however be immutable and return new instance when its builder methods are invoked.
61
 */
62
public interface InstrumentedType extends TypeDescription {
63

64
    /**
65
     * Creates a new instrumented type that includes a new field.
66
     *
67
     * @param token A token that represents the field's shape.
68
     * @return A new instrumented type that is equal to this instrumented type but with the additional field.
69
     */
70
    InstrumentedType withField(FieldDescription.Token token);
71

72
    /**
73
     * Creates a new instrumented type that includes a new field.
74
     *
75
     * @param token A token that represents the field's shape.
76
     * @param value The value that this assigned to this field.
77
     * @return A new instrumented type that is equal to this instrumented type but with the additional field.
78
     */
79
    InstrumentedType withAuxiliaryField(FieldDescription.Token token, Object value);
80

81
    /**
82
     * Creates a new instrumented type that includes a new method or constructor.
83
     *
84
     * @param token A token that represents the method's shape.
85
     * @return A new instrumented type that is equal to this instrumented type but with the additional method.
86
     */
87
    InstrumentedType withMethod(MethodDescription.Token token);
88

89
    /**
90
     * Creates a new instrumented type that includes a new record component.
91
     *
92
     * @param token A token that represents the record component's shape.
93
     * @return A new instrumented type that is equal to this instrumented type but with the additional record component.
94
     */
95
    InstrumentedType withRecordComponent(RecordComponentDescription.Token token);
96

97
    /**
98
     * Creates a new instrumented type with changed modifiers.
99
     *
100
     * @param modifiers The instrumented type's modifiers.
101
     * @return A new instrumented type that is equal to this instrumented type but with the given modifiers.
102
     */
103
    InstrumentedType withModifiers(int modifiers);
104

105
    /**
106
     * Creates a new instrumented type with the given interfaces implemented.
107
     *
108
     * @param interfaceTypes The interface types to implement.
109
     * @return A new instrumented type that is equal to this instrumented type but with the given interfaces implemented.
110
     */
111
    InstrumentedType withInterfaces(TypeList.Generic interfaceTypes);
112

113
    /**
114
     * Creates a new instrumented type with the given type variable defined.
115
     *
116
     * @param typeVariable The type variable to declare.
117
     * @return A new instrumented type that is equal to this instrumented type but with the given type variable declared.
118
     */
119
    InstrumentedType withTypeVariable(TypeVariableToken typeVariable);
120

121
    /**
122
     * Creates a new instrumented type with the given annotations.
123
     *
124
     * @param annotationDescriptions The annotations to add to the instrumented type.
125
     * @return A new instrumented type that is equal to this instrumented type but annotated with the given annotations
126
     */
127
    InstrumentedType withAnnotations(List<? extends AnnotationDescription> annotationDescriptions);
128

129
    /**
130
     * Creates a new instrumented type with the supplied nest host. An instrumented type can be its own nest host.
131
     * Setting a nest host removes all nest members from the instrumented type.
132
     *
133
     * @param nestHost The nest host of the created instrumented type.
134
     * @return A new instrumented type with the supplied type as its nest host.
135
     */
136
    InstrumentedType withNestHost(TypeDescription nestHost);
137

138
    /**
139
     * Creates a new instrumented types with the supplied nest members added to this instrumented type. The instrumented
140
     * type is defined as a nest host if this method is invoked. Any previous nest members are prepended to the supplied types.
141
     *
142
     * @param nestMembers The nest members to add to the created instrumented type.
143
     * @return A new instrumented type that applies the supplied nest members.
144
     */
145
    InstrumentedType withNestMembers(TypeList nestMembers);
146

147
    /**
148
     * Creates a new instrumented type with the supplied enclosing type.
149
     *
150
     * @param enclosingType The type to define as the created instrumented type's enclosing type.
151
     * @return A new instrumented type with the supplied type as its enclosing type.
152
     */
153
    InstrumentedType withEnclosingType(TypeDescription enclosingType);
154

155
    /**
156
     * Creates a new instrumented type with the supplied enclosing method.
157
     *
158
     * @param enclosingMethod The method to define as the created instrumented type's enclosing method.
159
     * @return A new instrumented type with the supplied method as its enclosing method.
160
     */
161
    InstrumentedType withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod);
162

163
    /**
164
     * Creates a new instrumented type that is declared by the supplied type.
165
     *
166
     * @param declaringType The type that declares the instrumented type or {@code null} if no such type exists.
167
     * @return A new instrumented type that is declared by the instrumented type.
168
     */
169
    InstrumentedType withDeclaringType(@MaybeNull TypeDescription declaringType);
170

171
    /**
172
     * Creates a new instrumented type that indicates that it declared the supplied types.
173
     *
174
     * @param declaredTypes The types to add to the created instrumented type as declared types.
175
     * @return A new instrumented type that indicates that it has declared the supplied types.
176
     */
177
    InstrumentedType withDeclaredTypes(TypeList declaredTypes);
178

179
    /**
180
     * Creates a new instrumented type that includes the supplied permitted subclasses or unseals the type.
181
     *
182
     * @param permittedSubclasses A list of permitted subclasses to include or {@code null} to unseal the type.
183
     * @return A new instrumented type that includes the supplied permitted subclasses or unseals the type.
184
     */
185
    InstrumentedType withPermittedSubclasses(@MaybeNull TypeList permittedSubclasses);
186

187
    /**
188
     * Creates a new instrumented type that indicates that is defined as a local class. Setting this property
189
     * resets the anonymous class property.
190
     *
191
     * @param localClass {@code true} if the instrumented type is supposed to be treated as a local class.
192
     * @return A new instrumented type that is treated as a local class.
193
     */
194
    InstrumentedType withLocalClass(boolean localClass);
195

196
    /**
197
     * Creates a new instrumented type that indicates that it is defined as an anonymous class. Setting this property
198
     * resets the local class property.
199
     *
200
     * @param anonymousClass {@code true} if the instrumented type is supposed to be treated as an anonymous class.
201
     * @return A new instrumented type that is treated as an anonymous class.
202
     */
203
    InstrumentedType withAnonymousClass(boolean anonymousClass);
204

205
    /**
206
     * Creates a new instrumented type that indicates that it defined as a record type. Setting this property to false
207
     * removes all record components.
208
     *
209
     * @param record {@code true} if the instrumented type is supposed to be a record.
210
     * @return A new instrumented type that is defined as a record.
211
     */
212
    InstrumentedType withRecord(boolean record);
213

214
    /**
215
     * Creates a new instrumented type that includes the given {@link net.bytebuddy.implementation.LoadedTypeInitializer}.
216
     *
217
     * @param loadedTypeInitializer The type initializer to include.
218
     * @return A new instrumented type that is equal to this instrumented type but with the additional type initializer.
219
     */
220
    InstrumentedType withInitializer(LoadedTypeInitializer loadedTypeInitializer);
221

222
    /**
223
     * Creates a new instrumented type that executes the given initializer in the instrumented type's
224
     * type initializer.
225
     *
226
     * @param byteCodeAppender The byte code to add to the type initializer.
227
     * @return A new instrumented type that is equal to this instrumented type but with the given stack manipulation
228
     * attached to its type initializer.
229
     */
230
    InstrumentedType withInitializer(ByteCodeAppender byteCodeAppender);
231

232
    /**
233
     * Returns the {@link net.bytebuddy.implementation.LoadedTypeInitializer}s that were registered
234
     * for this instrumented type.
235
     *
236
     * @return The registered loaded type initializers for this instrumented type.
237
     */
238
    LoadedTypeInitializer getLoadedTypeInitializer();
239

240
    /**
241
     * Returns this instrumented type's type initializer.
242
     *
243
     * @return This instrumented type's type initializer.
244
     */
245
    TypeInitializer getTypeInitializer();
246

247
    /**
248
     * Validates the instrumented type to define a legal Java type.
249
     *
250
     * @return This instrumented type as a non-modifiable type description.
251
     */
252
    TypeDescription validated();
253

254
    /**
255
     * Implementations represent an {@link InstrumentedType} with a flexible name.
256
     */
257
    interface WithFlexibleName extends InstrumentedType {
258

259
        /**
260
         * {@inheritDoc}
261
         */
262
        WithFlexibleName withField(FieldDescription.Token token);
263

264
        /**
265
         * {@inheritDoc}
266
         */
267
        WithFlexibleName withAuxiliaryField(FieldDescription.Token token, Object value);
268

269
        /**
270
         * {@inheritDoc}
271
         */
272
        WithFlexibleName withMethod(MethodDescription.Token token);
273

274
        /**
275
         * {@inheritDoc}
276
         */
277
        WithFlexibleName withRecordComponent(RecordComponentDescription.Token token);
278

279
        /**
280
         * {@inheritDoc}
281
         */
282
        WithFlexibleName withModifiers(int modifiers);
283

284
        /**
285
         * {@inheritDoc}
286
         */
287
        WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes);
288

289
        /**
290
         * {@inheritDoc}
291
         */
292
        WithFlexibleName withNestHost(TypeDescription nestHost);
293

294
        /**
295
         * {@inheritDoc}
296
         */
297
        WithFlexibleName withNestMembers(TypeList nestMembers);
298

299
        /**
300
         * {@inheritDoc}
301
         */
302
        WithFlexibleName withEnclosingType(@MaybeNull TypeDescription enclosingType);
303

304
        /**
305
         * {@inheritDoc}
306
         */
307
        WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod);
308

309
        /**
310
         * {@inheritDoc}
311
         */
312
        WithFlexibleName withDeclaringType(@MaybeNull TypeDescription declaringType);
313

314
        /**
315
         * {@inheritDoc}
316
         */
317
        WithFlexibleName withDeclaredTypes(TypeList declaredTypes);
318

319
        /**
320
         * {@inheritDoc}
321
         */
322
        WithFlexibleName withPermittedSubclasses(@MaybeNull TypeList permittedSubclasses);
323

324
        /**
325
         * {@inheritDoc}
326
         */
327
        WithFlexibleName withLocalClass(boolean localClass);
328

329
        /**
330
         * {@inheritDoc}
331
         */
332
        WithFlexibleName withAnonymousClass(boolean anonymousClass);
333

334
        /**
335
         * {@inheritDoc}
336
         */
337
        WithFlexibleName withRecord(boolean record);
338

339
        /**
340
         * {@inheritDoc}
341
         */
342
        WithFlexibleName withTypeVariable(TypeVariableToken typeVariable);
343

344
        /**
345
         * {@inheritDoc}
346
         */
347
        WithFlexibleName withAnnotations(List<? extends AnnotationDescription> annotationDescriptions);
348

349
        /**
350
         * {@inheritDoc}
351
         */
352
        WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitializer);
353

354
        /**
355
         * {@inheritDoc}
356
         */
357
        WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender);
358

359
        /**
360
         * Creates a new instrumented type with a changed name.
361
         *
362
         * @param name The name of the instrumented type.
363
         * @return A new instrumented type that has the given name.
364
         */
365
        WithFlexibleName withName(String name);
366

367
        /**
368
         * Applies a transformation onto all existing type variables of this instrumented type. A transformation is potentially unsafe
369
         * and it is the responsibility of the supplier to return a valid type variable token from the transformer.
370
         *
371
         * @param matcher     The matcher to decide what type variables to transform.
372
         * @param transformer The transformer to apply on all matched type variables.
373
         * @return A new instrumented type with all matched type variables transformed.
374
         */
375
        WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matcher, Transformer<TypeVariableToken> transformer);
376
    }
377

378
    /**
379
     * Implementations are able to prepare an {@link InstrumentedType}.
380
     */
381
    interface Prepareable {
382

383
        /**
384
         * Prepares a given instrumented type.
385
         *
386
         * @param instrumentedType The instrumented type in its current form.
387
         * @return The prepared instrumented type.
388
         */
389
        InstrumentedType prepare(InstrumentedType instrumentedType);
390

391
        /**
392
         * A prepareable that does not alter the instrumented type.
393
         */
394
        enum NoOp implements Prepareable {
1✔
395

396
            /**
397
             * The singleton instance.
398
             */
399
            INSTANCE;
1✔
400

401
            /**
402
             * {@inheritDoc}
403
             */
404
            public InstrumentedType prepare(InstrumentedType instrumentedType) {
405
                return instrumentedType;
1✔
406
            }
407
        }
408
    }
409

410
    /**
411
     * A factory for creating an {@link InstrumentedType}.
412
     */
413
    interface Factory {
414

415
        /**
416
         * Creates an instrumented type that represents the provided type.
417
         *
418
         * @param typeDescription The type to represent.
419
         * @return An appropriate instrumented type.
420
         */
421
        InstrumentedType.WithFlexibleName represent(TypeDescription typeDescription);
422

423
        /**
424
         * Creates a new instrumented type as a subclass.
425
         *
426
         * @param name       The type's name.
427
         * @param modifiers  The type's modifiers.
428
         * @param superClass The type's super class.
429
         * @return A new instrumented type representing a subclass of the given parameters.
430
         */
431
        InstrumentedType.WithFlexibleName subclass(String name, int modifiers, TypeDescription.Generic superClass);
432

433
        /**
434
         * Default implementations of instrumented type factories.
435
         */
436
        enum Default implements Factory {
1✔
437

438
            /**
439
             * A factory for an instrumented type that allows to modify represented types.
440
             */
441
            MODIFIABLE {
1✔
442
                /** {@inheritDoc} */
443
                public InstrumentedType.WithFlexibleName represent(TypeDescription typeDescription) {
444
                    return new InstrumentedType.Default(typeDescription.getName(),
1✔
445
                            typeDescription.getModifiers(),
1✔
446
                            typeDescription.getSuperClass(),
1✔
447
                            typeDescription.getTypeVariables().asTokenList(is(typeDescription)),
1✔
448
                            typeDescription.getInterfaces().accept(Generic.Visitor.Substitutor.ForDetachment.of(typeDescription)),
1✔
449
                            typeDescription.getDeclaredFields().asTokenList(is(typeDescription)),
1✔
450
                            Collections.<String, Object>emptyMap(),
1✔
451
                            typeDescription.getDeclaredMethods().asTokenList(is(typeDescription)),
1✔
452
                            typeDescription.getRecordComponents().asTokenList(is(typeDescription)),
1✔
453
                            typeDescription.getDeclaredAnnotations(),
1✔
454
                            TypeInitializer.None.INSTANCE,
455
                            LoadedTypeInitializer.NoOp.INSTANCE,
456
                            typeDescription.getDeclaringType(),
1✔
457
                            typeDescription.getEnclosingMethod(),
1✔
458
                            typeDescription.getEnclosingType(),
1✔
459
                            typeDescription.getDeclaredTypes(),
1✔
460
                            typeDescription.isSealed()
1✔
461
                                    ? typeDescription.getPermittedSubtypes()
1✔
462
                                    : TypeList.UNDEFINED,
463
                            typeDescription.isAnonymousType(),
1✔
464
                            typeDescription.isLocalType(),
1✔
465
                            typeDescription.isRecord(),
1✔
466
                            typeDescription.isNestHost()
1✔
467
                                    ? TargetType.DESCRIPTION
468
                                    : typeDescription.getNestHost(),
1✔
469
                            typeDescription.isNestHost()
1✔
470
                                    ? typeDescription.getNestMembers().filter(not(is(typeDescription)))
1✔
471
                                    : Collections.<TypeDescription>emptyList());
1✔
472
                }
473
            },
474

475
            /**
476
             * A factory for an instrumented type that does not allow to modify represented types.
477
             */
478
            FROZEN {
1✔
479
                /** {@inheritDoc} */
480
                public InstrumentedType.WithFlexibleName represent(TypeDescription typeDescription) {
481
                    return new Frozen(typeDescription, LoadedTypeInitializer.NoOp.INSTANCE);
1✔
482
                }
483
            };
484

485
            /**
486
             * {@inheritDoc}
487
             */
488
            public InstrumentedType.WithFlexibleName subclass(String name, int modifiers, TypeDescription.Generic superClass) {
489
                return new InstrumentedType.Default(name,
1✔
490
                        modifiers,
491
                        superClass,
492
                        Collections.<TypeVariableToken>emptyList(),
1✔
493
                        Collections.<Generic>emptyList(),
1✔
494
                        Collections.<FieldDescription.Token>emptyList(),
1✔
495
                        Collections.<String, Object>emptyMap(),
1✔
496
                        Collections.<MethodDescription.Token>emptyList(),
1✔
497
                        Collections.<RecordComponentDescription.Token>emptyList(),
1✔
498
                        Collections.<AnnotationDescription>emptyList(),
1✔
499
                        TypeInitializer.None.INSTANCE,
500
                        LoadedTypeInitializer.NoOp.INSTANCE,
501
                        TypeDescription.UNDEFINED,
502
                        MethodDescription.UNDEFINED,
503
                        TypeDescription.UNDEFINED,
504
                        Collections.<TypeDescription>emptyList(),
1✔
505
                        TypeList.UNDEFINED,
506
                        false,
507
                        false,
508
                        false,
509
                        TargetType.DESCRIPTION,
510
                        Collections.<TypeDescription>emptyList());
1✔
511
            }
512
        }
513
    }
514

515
    /**
516
     * A default implementation of an instrumented type.
517
     */
518
    class Default extends AbstractBase.OfSimpleType implements InstrumentedType.WithFlexibleName {
519

520
        /**
521
         * A set containing all keywords of the Java programming language.
522
         */
523
        private static final Set<String> KEYWORDS = new HashSet<String>(Arrays.asList(
1✔
524
                "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean",
525
                "do", "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import",
526
                "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", "short",
527
                "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile",
528
                "const", "float", "native", "super", "while"
529
        ));
530

531
        /**
532
         * The binary name of the instrumented type.
533
         */
534
        private final String name;
535

536
        /**
537
         * The modifiers of the instrumented type.
538
         */
539
        private final int modifiers;
540

541
        /**
542
         * The generic super type of the instrumented type.
543
         */
544
        @MaybeNull
545
        private final Generic superClass;
546

547
        /**
548
         * The instrumented type's type variables in their tokenized form.
549
         */
550
        private final List<? extends TypeVariableToken> typeVariables;
551

552
        /**
553
         * A list of interfaces of the instrumented type.
554
         */
555
        private final List<? extends Generic> interfaceTypes;
556

557
        /**
558
         * A list of field tokens describing the fields of the instrumented type.
559
         */
560
        private final List<? extends FieldDescription.Token> fieldTokens;
561

562
        /**
563
         * A mapping of auxiliary field names to their mapped values.
564
         */
565
        private final Map<String, Object> auxiliaryFields;
566

567
        /**
568
         * A list of method tokens describing the methods of the instrumented type.
569
         */
570
        private final List<? extends MethodDescription.Token> methodTokens;
571

572
        /**
573
         * A list of record component tokens describing the record components of the instrumented type.
574
         */
575
        private final List<? extends RecordComponentDescription.Token> recordComponentTokens;
576

577
        /**
578
         * A list of annotations of the annotated type.
579
         */
580
        private final List<? extends AnnotationDescription> annotationDescriptions;
581

582
        /**
583
         * The type initializer of the instrumented type.
584
         */
585
        private final TypeInitializer typeInitializer;
586

587
        /**
588
         * The loaded type initializer of the instrumented type.
589
         */
590
        private final LoadedTypeInitializer loadedTypeInitializer;
591

592
        /**
593
         * The declaring type of the instrumented type or {@code null} if no such type exists.
594
         */
595
        @MaybeNull
596
        private final TypeDescription declaringType;
597

598
        /**
599
         * The enclosing method of the instrumented type or {@code null} if no such type exists.
600
         */
601
        @MaybeNull
602
        private final MethodDescription.InDefinedShape enclosingMethod;
603

604
        /**
605
         * The enclosing type of the instrumented type or {@code null} if no such type exists.
606
         */
607
        @MaybeNull
608
        private final TypeDescription enclosingType;
609

610
        /**
611
         * A list of types that are declared by this type.
612
         */
613
        private final List<? extends TypeDescription> declaredTypes;
614

615
        /**
616
         * A list of permitted subclasses or {@code null} if this type is not sealed.
617
         */
618
        @MaybeNull
619
        private final List<? extends TypeDescription> permittedSubclasses;
620

621
        /**
622
         * {@code true} if this type is an anonymous class.
623
         */
624
        private final boolean anonymousClass;
625

626
        /**
627
         * {@code true} if this type is a local class.
628
         */
629
        private final boolean localClass;
630

631
        /**
632
         * {@code true} if this class is a record class.
633
         */
634
        private final boolean record;
635

636
        /**
637
         * The nest host of this instrumented type or a description of {@link TargetType} if this type is its own nest host.
638
         */
639
        private final TypeDescription nestHost;
640

641
        /**
642
         * A list of all members of this types nest group excluding this type.
643
         */
644
        private final List<? extends TypeDescription> nestMembers;
645

646
        /**
647
         * Creates a new instrumented type.
648
         *
649
         * @param name                   The binary name of the instrumented type.
650
         * @param modifiers              The modifiers of the instrumented type.
651
         * @param typeVariables          The instrumented type's type variables in their tokenized form.
652
         * @param superClass             The generic super type of the instrumented type.
653
         * @param interfaceTypes         A list of interfaces of the instrumented type.
654
         * @param fieldTokens            A list of field tokens describing the fields of the instrumented type.
655
         * @param auxiliaryFieldValues   A mapping of auxiliary field names to their mapped values.
656
         * @param methodTokens           A list of method tokens describing the methods of the instrumented type.
657
         * @param recordComponentTokens  A list of record component tokens describing the record components of the instrumented type.
658
         * @param annotationDescriptions A list of annotations of the annotated type.
659
         * @param typeInitializer        The type initializer of the instrumented type.
660
         * @param loadedTypeInitializer  The loaded type initializer of the instrumented type.
661
         * @param declaringType          The declaring type of the instrumented type or {@code null} if no such type exists.
662
         * @param enclosingMethod        The enclosing method of the instrumented type or {@code null} if no such type exists.
663
         * @param enclosingType          The enclosing type of the instrumented type or {@code null} if no such type exists.
664
         * @param declaredTypes          A list of types that are declared by this type.
665
         * @param permittedSubclasses    A list of permitted subclasses or {@code null} if this type is not sealed.
666
         * @param anonymousClass         {@code true} if this type is an anonymous class.
667
         * @param localClass             {@code true} if this type is a local class.
668
         * @param record                 {@code true} if this type is a record class.
669
         * @param nestHost               The nest host of this instrumented type or a description of {@link TargetType} if this type is its own nest host.
670
         * @param nestMembers            A list of all members of this types nest group excluding this type.
671
         */
672
        protected Default(String name,
673
                          int modifiers,
674
                          @MaybeNull Generic superClass,
675
                          List<? extends TypeVariableToken> typeVariables,
676
                          List<? extends Generic> interfaceTypes,
677
                          List<? extends FieldDescription.Token> fieldTokens,
678
                          Map<String, Object> auxiliaryFieldValues,
679
                          List<? extends MethodDescription.Token> methodTokens,
680
                          List<? extends RecordComponentDescription.Token> recordComponentTokens,
681
                          List<? extends AnnotationDescription> annotationDescriptions,
682
                          TypeInitializer typeInitializer,
683
                          LoadedTypeInitializer loadedTypeInitializer,
684
                          @MaybeNull TypeDescription declaringType,
685
                          @MaybeNull MethodDescription.InDefinedShape enclosingMethod,
686
                          @MaybeNull TypeDescription enclosingType,
687
                          List<? extends TypeDescription> declaredTypes,
688
                          @MaybeNull List<? extends TypeDescription> permittedSubclasses,
689
                          boolean anonymousClass,
690
                          boolean localClass,
691
                          boolean record,
692
                          TypeDescription nestHost,
693
                          List<? extends TypeDescription> nestMembers) {
1✔
694
            this.name = name;
1✔
695
            this.modifiers = modifiers;
1✔
696
            this.typeVariables = typeVariables;
1✔
697
            this.superClass = superClass;
1✔
698
            this.interfaceTypes = interfaceTypes;
1✔
699
            this.fieldTokens = fieldTokens;
1✔
700
            this.auxiliaryFields = auxiliaryFieldValues;
1✔
701
            this.methodTokens = methodTokens;
1✔
702
            this.recordComponentTokens = recordComponentTokens;
1✔
703
            this.annotationDescriptions = annotationDescriptions;
1✔
704
            this.typeInitializer = typeInitializer;
1✔
705
            this.loadedTypeInitializer = loadedTypeInitializer;
1✔
706
            this.declaringType = declaringType;
1✔
707
            this.enclosingMethod = enclosingMethod;
1✔
708
            this.enclosingType = enclosingType;
1✔
709
            this.declaredTypes = declaredTypes;
1✔
710
            this.permittedSubclasses = permittedSubclasses;
1✔
711
            this.anonymousClass = anonymousClass;
1✔
712
            this.localClass = localClass;
1✔
713
            this.record = record;
1✔
714
            this.nestHost = nestHost;
1✔
715
            this.nestMembers = nestMembers;
1✔
716
        }
1✔
717

718
        /**
719
         * Creates a new instrumented type.
720
         *
721
         * @param name                The type's name.
722
         * @param superClass          The type's super class.
723
         * @param modifierContributor The type's modifiers.
724
         * @return An appropriate instrumented type.
725
         */
726
        public static InstrumentedType of(String name, TypeDescription.Generic superClass, ModifierContributor.ForType... modifierContributor) {
727
            return of(name, superClass, ModifierContributor.Resolver.of(modifierContributor).resolve());
1✔
728
        }
729

730
        /**
731
         * Creates a new instrumented type.
732
         *
733
         * @param name       The type's name.
734
         * @param superClass The type's super class.
735
         * @param modifiers  The type's modifiers.
736
         * @return An appropriate instrumented type.
737
         */
738
        public static InstrumentedType of(String name, TypeDescription.Generic superClass, int modifiers) {
739
            return Factory.Default.MODIFIABLE.subclass(name, modifiers, superClass);
1✔
740
        }
741

742
        /**
743
         * {@inheritDoc}
744
         */
745
        public WithFlexibleName withModifiers(int modifiers) {
746
            return new Default(name,
1✔
747
                    modifiers,
748
                    superClass,
749
                    typeVariables,
750
                    interfaceTypes,
751
                    fieldTokens,
752
                    auxiliaryFields,
753
                    methodTokens,
754
                    recordComponentTokens,
755
                    annotationDescriptions,
756
                    typeInitializer,
757
                    loadedTypeInitializer,
758
                    declaringType,
759
                    enclosingMethod,
760
                    enclosingType,
761
                    declaredTypes,
762
                    permittedSubclasses,
763
                    anonymousClass,
764
                    localClass,
765
                    record,
766
                    nestHost,
767
                    nestMembers);
768
        }
769

770
        /**
771
         * {@inheritDoc}
772
         */
773
        public WithFlexibleName withField(FieldDescription.Token token) {
774
            return new Default(name,
1✔
775
                    modifiers,
776
                    superClass,
777
                    typeVariables,
778
                    interfaceTypes,
779
                    CompoundList.of(fieldTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
1✔
780
                    auxiliaryFields,
781
                    methodTokens,
782
                    recordComponentTokens,
783
                    annotationDescriptions,
784
                    typeInitializer,
785
                    loadedTypeInitializer,
786
                    declaringType,
787
                    enclosingMethod,
788
                    enclosingType,
789
                    declaredTypes,
790
                    permittedSubclasses,
791
                    anonymousClass,
792
                    localClass,
793
                    record,
794
                    nestHost,
795
                    nestMembers);
796
        }
797

798
        /**
799
         * {@inheritDoc}
800
         */
801
        public WithFlexibleName withAuxiliaryField(FieldDescription.Token token, Object value) {
802
            Map<String, Object> auxiliaryFields = new HashMap<String, Object>(this.auxiliaryFields);
1✔
803
            Object previous = auxiliaryFields.put(token.getName(), value);
1✔
804
            if (previous != null) {
1✔
805
                if (previous == value) {
1✔
806
                    return this;
1✔
807
                } else {
808
                    throw new IllegalStateException("Field " + token.getName()
1✔
809
                            + " for " + this
810
                            + " already mapped to " + previous
811
                            + " and not " + value);
812
                }
813
            }
814
            return new Default(name,
1✔
815
                    modifiers,
816
                    superClass,
817
                    typeVariables,
818
                    interfaceTypes,
819
                    CompoundList.of(fieldTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
1✔
820
                    auxiliaryFields,
821
                    methodTokens,
822
                    recordComponentTokens,
823
                    annotationDescriptions,
824
                    typeInitializer,
825
                    new LoadedTypeInitializer.Compound(loadedTypeInitializer, new LoadedTypeInitializer.ForStaticField(token.getName(), value)),
1✔
826
                    declaringType,
827
                    enclosingMethod,
828
                    enclosingType,
829
                    declaredTypes,
830
                    permittedSubclasses,
831
                    anonymousClass,
832
                    localClass,
833
                    record,
834
                    nestHost,
835
                    nestMembers);
836
        }
837

838
        /**
839
         * {@inheritDoc}
840
         */
841
        public WithFlexibleName withMethod(MethodDescription.Token token) {
842
            return new Default(name,
1✔
843
                    modifiers,
844
                    superClass,
845
                    typeVariables,
846
                    interfaceTypes,
847
                    fieldTokens,
848
                    auxiliaryFields,
849
                    CompoundList.of(methodTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
1✔
850
                    recordComponentTokens,
851
                    annotationDescriptions,
852
                    typeInitializer,
853
                    loadedTypeInitializer,
854
                    declaringType,
855
                    enclosingMethod,
856
                    enclosingType,
857
                    declaredTypes,
858
                    permittedSubclasses,
859
                    anonymousClass,
860
                    localClass,
861
                    record,
862
                    nestHost,
863
                    nestMembers);
864
        }
865

866
        /**
867
         * {@inheritDoc}
868
         */
869
        public WithFlexibleName withRecordComponent(RecordComponentDescription.Token token) {
870
            return new Default(name,
1✔
871
                    modifiers,
872
                    superClass,
873
                    typeVariables,
874
                    interfaceTypes,
875
                    fieldTokens,
876
                    auxiliaryFields,
877
                    methodTokens,
878
                    CompoundList.of(recordComponentTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
1✔
879
                    annotationDescriptions,
880
                    typeInitializer,
881
                    loadedTypeInitializer,
882
                    declaringType,
883
                    enclosingMethod,
884
                    enclosingType,
885
                    declaredTypes,
886
                    permittedSubclasses,
887
                    anonymousClass,
888
                    localClass,
889
                    true,
890
                    nestHost,
891
                    nestMembers);
892
        }
893

894
        /**
895
         * {@inheritDoc}
896
         */
897
        public WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes) {
898
            return new Default(name,
1✔
899
                    modifiers,
900
                    superClass,
901
                    typeVariables,
902
                    CompoundList.of(this.interfaceTypes, interfaceTypes.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
1✔
903
                    fieldTokens,
904
                    auxiliaryFields,
905
                    methodTokens,
906
                    recordComponentTokens,
907
                    annotationDescriptions,
908
                    typeInitializer,
909
                    loadedTypeInitializer,
910
                    declaringType,
911
                    enclosingMethod,
912
                    enclosingType,
913
                    declaredTypes,
914
                    permittedSubclasses,
915
                    anonymousClass,
916
                    localClass,
917
                    record,
918
                    nestHost,
919
                    nestMembers);
920
        }
921

922
        /**
923
         * {@inheritDoc}
924
         */
925
        public WithFlexibleName withAnnotations(List<? extends AnnotationDescription> annotationDescriptions) {
926
            return new Default(name,
1✔
927
                    modifiers,
928
                    superClass,
929
                    typeVariables,
930
                    interfaceTypes,
931
                    fieldTokens,
932
                    auxiliaryFields,
933
                    methodTokens,
934
                    recordComponentTokens,
935
                    CompoundList.of(this.annotationDescriptions, annotationDescriptions),
1✔
936
                    typeInitializer,
937
                    loadedTypeInitializer,
938
                    declaringType,
939
                    enclosingMethod,
940
                    enclosingType,
941
                    declaredTypes,
942
                    permittedSubclasses,
943
                    anonymousClass,
944
                    localClass,
945
                    record,
946
                    nestHost,
947
                    nestMembers);
948
        }
949

950
        /**
951
         * {@inheritDoc}
952
         */
953
        public WithFlexibleName withNestHost(TypeDescription nestHost) {
954
            return new Default(name,
1✔
955
                    modifiers,
956
                    superClass,
957
                    typeVariables,
958
                    interfaceTypes,
959
                    fieldTokens,
960
                    auxiliaryFields,
961
                    methodTokens,
962
                    recordComponentTokens,
963
                    annotationDescriptions,
964
                    typeInitializer,
965
                    loadedTypeInitializer,
966
                    declaringType,
967
                    enclosingMethod,
968
                    enclosingType,
969
                    declaredTypes,
970
                    permittedSubclasses,
971
                    anonymousClass,
972
                    localClass,
973
                    record,
974
                    nestHost.equals(this)
1✔
975
                            ? TargetType.DESCRIPTION
976
                            : nestHost,
977
                    Collections.<TypeDescription>emptyList());
1✔
978
        }
979

980
        /**
981
         * {@inheritDoc}
982
         */
983
        public WithFlexibleName withNestMembers(TypeList nestMembers) {
984
            return new Default(name,
1✔
985
                    modifiers,
986
                    superClass,
987
                    typeVariables,
988
                    interfaceTypes,
989
                    fieldTokens,
990
                    auxiliaryFields,
991
                    methodTokens,
992
                    recordComponentTokens,
993
                    annotationDescriptions,
994
                    typeInitializer,
995
                    loadedTypeInitializer,
996
                    declaringType,
997
                    enclosingMethod,
998
                    enclosingType,
999
                    declaredTypes,
1000
                    permittedSubclasses,
1001
                    anonymousClass,
1002
                    localClass,
1003
                    record,
1004
                    TargetType.DESCRIPTION,
1005
                    CompoundList.of(this.nestMembers, nestMembers));
1✔
1006
        }
1007

1008
        /**
1009
         * {@inheritDoc}
1010
         */
1011
        public WithFlexibleName withEnclosingType(@MaybeNull TypeDescription enclosingType) {
1012
            return new Default(name,
1✔
1013
                    modifiers,
1014
                    superClass,
1015
                    typeVariables,
1016
                    interfaceTypes,
1017
                    fieldTokens,
1018
                    auxiliaryFields,
1019
                    methodTokens,
1020
                    recordComponentTokens,
1021
                    annotationDescriptions,
1022
                    typeInitializer,
1023
                    loadedTypeInitializer,
1024
                    declaringType,
1025
                    MethodDescription.UNDEFINED,
1026
                    enclosingType,
1027
                    declaredTypes,
1028
                    permittedSubclasses,
1029
                    anonymousClass,
1030
                    localClass,
1031
                    record,
1032
                    nestHost,
1033
                    nestMembers);
1034
        }
1035

1036
        /**
1037
         * {@inheritDoc}
1038
         */
1039
        public WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod) {
1040
            return new Default(name,
1✔
1041
                    modifiers,
1042
                    superClass,
1043
                    typeVariables,
1044
                    interfaceTypes,
1045
                    fieldTokens,
1046
                    auxiliaryFields,
1047
                    methodTokens,
1048
                    recordComponentTokens,
1049
                    annotationDescriptions,
1050
                    typeInitializer,
1051
                    loadedTypeInitializer,
1052
                    declaringType,
1053
                    enclosingMethod,
1054
                    enclosingMethod.getDeclaringType(),
1✔
1055
                    declaredTypes,
1056
                    permittedSubclasses,
1057
                    anonymousClass,
1058
                    localClass,
1059
                    record,
1060
                    nestHost,
1061
                    nestMembers);
1062
        }
1063

1064
        /**
1065
         * {@inheritDoc}
1066
         */
1067
        public WithFlexibleName withDeclaringType(@MaybeNull TypeDescription declaringType) {
1068
            return new Default(name,
1✔
1069
                    modifiers,
1070
                    superClass,
1071
                    typeVariables,
1072
                    interfaceTypes,
1073
                    fieldTokens,
1074
                    auxiliaryFields,
1075
                    methodTokens,
1076
                    recordComponentTokens,
1077
                    annotationDescriptions,
1078
                    typeInitializer,
1079
                    loadedTypeInitializer,
1080
                    declaringType,
1081
                    enclosingMethod,
1082
                    enclosingType,
1083
                    declaredTypes,
1084
                    permittedSubclasses,
1085
                    anonymousClass,
1086
                    localClass,
1087
                    record,
1088
                    nestHost,
1089
                    nestMembers);
1090
        }
1091

1092
        /**
1093
         * {@inheritDoc}
1094
         */
1095
        public WithFlexibleName withDeclaredTypes(TypeList declaredTypes) {
1096
            return new Default(name,
1✔
1097
                    modifiers,
1098
                    superClass,
1099
                    typeVariables,
1100
                    interfaceTypes,
1101
                    fieldTokens,
1102
                    auxiliaryFields,
1103
                    methodTokens,
1104
                    recordComponentTokens,
1105
                    annotationDescriptions,
1106
                    typeInitializer,
1107
                    loadedTypeInitializer,
1108
                    declaringType,
1109
                    enclosingMethod,
1110
                    enclosingType,
1111
                    CompoundList.of(this.declaredTypes, declaredTypes),
1✔
1112
                    permittedSubclasses,
1113
                    anonymousClass,
1114
                    localClass,
1115
                    record,
1116
                    nestHost,
1117
                    nestMembers);
1118
        }
1119

1120
        /**
1121
         * {@inheritDoc}
1122
         */
1123
        public WithFlexibleName withPermittedSubclasses(@MaybeNull TypeList permittedSubclasses) {
1124
            return new Default(name,
1✔
1125
                    modifiers,
1126
                    superClass,
1127
                    typeVariables,
1128
                    interfaceTypes,
1129
                    fieldTokens,
1130
                    auxiliaryFields,
1131
                    methodTokens,
1132
                    recordComponentTokens,
1133
                    annotationDescriptions,
1134
                    typeInitializer,
1135
                    loadedTypeInitializer,
1136
                    declaringType,
1137
                    enclosingMethod,
1138
                    enclosingType,
1139
                    declaredTypes,
1140
                    permittedSubclasses == null || this.permittedSubclasses == null
1141
                            ? permittedSubclasses
1142
                            : CompoundList.of(this.permittedSubclasses, permittedSubclasses),
1✔
1143
                    anonymousClass,
1144
                    localClass,
1145
                    record,
1146
                    nestHost,
1147
                    nestMembers);
1148
        }
1149

1150
        /**
1151
         * {@inheritDoc}
1152
         */
1153
        public WithFlexibleName withTypeVariable(TypeVariableToken typeVariable) {
1154
            return new Default(name,
1✔
1155
                    modifiers,
1156
                    superClass,
1157
                    CompoundList.of(typeVariables, typeVariable.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
1✔
1158
                    interfaceTypes,
1159
                    fieldTokens,
1160
                    auxiliaryFields,
1161
                    methodTokens,
1162
                    recordComponentTokens,
1163
                    annotationDescriptions,
1164
                    typeInitializer,
1165
                    loadedTypeInitializer,
1166
                    declaringType,
1167
                    enclosingMethod,
1168
                    enclosingType,
1169
                    declaredTypes,
1170
                    permittedSubclasses,
1171
                    anonymousClass,
1172
                    localClass,
1173
                    record,
1174
                    nestHost,
1175
                    nestMembers);
1176
        }
1177

1178
        /**
1179
         * {@inheritDoc}
1180
         */
1181
        public WithFlexibleName withName(String name) {
1182
            return new Default(name,
1✔
1183
                    modifiers,
1184
                    superClass,
1185
                    typeVariables,
1186
                    interfaceTypes,
1187
                    fieldTokens,
1188
                    auxiliaryFields,
1189
                    methodTokens,
1190
                    recordComponentTokens,
1191
                    annotationDescriptions,
1192
                    typeInitializer,
1193
                    loadedTypeInitializer,
1194
                    declaringType,
1195
                    enclosingMethod,
1196
                    enclosingType,
1197
                    declaredTypes,
1198
                    permittedSubclasses,
1199
                    anonymousClass,
1200
                    localClass,
1201
                    record,
1202
                    nestHost,
1203
                    nestMembers);
1204
        }
1205

1206
        /**
1207
         * {@inheritDoc}
1208
         */
1209
        public WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matcher, Transformer<TypeVariableToken> transformer) {
1210
            List<TypeVariableToken> typeVariables = new ArrayList<TypeVariableToken>(this.typeVariables.size());
1✔
1211
            int index = 0;
1✔
1212
            for (TypeVariableToken typeVariableToken : this.typeVariables) {
1✔
1213
                typeVariables.add(matcher.matches(getTypeVariables().get(index++))
1✔
1214
                        ? transformer.transform(this, typeVariableToken)
1✔
1215
                        : typeVariableToken);
1216
            }
1✔
1217
            return new Default(name,
1✔
1218
                    modifiers,
1219
                    superClass,
1220
                    typeVariables,
1221
                    interfaceTypes,
1222
                    fieldTokens,
1223
                    auxiliaryFields,
1224
                    methodTokens,
1225
                    recordComponentTokens,
1226
                    annotationDescriptions,
1227
                    typeInitializer,
1228
                    loadedTypeInitializer,
1229
                    declaringType,
1230
                    enclosingMethod,
1231
                    enclosingType,
1232
                    declaredTypes,
1233
                    permittedSubclasses,
1234
                    anonymousClass,
1235
                    localClass,
1236
                    record,
1237
                    nestHost,
1238
                    nestMembers);
1239
        }
1240

1241
        /**
1242
         * {@inheritDoc}
1243
         */
1244
        public WithFlexibleName withLocalClass(boolean localClass) {
1245
            return new Default(name,
1✔
1246
                    modifiers,
1247
                    superClass,
1248
                    typeVariables,
1249
                    interfaceTypes,
1250
                    fieldTokens,
1251
                    auxiliaryFields,
1252
                    methodTokens,
1253
                    recordComponentTokens,
1254
                    annotationDescriptions,
1255
                    typeInitializer,
1256
                    loadedTypeInitializer,
1257
                    declaringType,
1258
                    enclosingMethod,
1259
                    enclosingType,
1260
                    declaredTypes,
1261
                    permittedSubclasses,
1262
                    false,
1263
                    localClass,
1264
                    record,
1265
                    nestHost,
1266
                    nestMembers);
1267
        }
1268

1269
        /**
1270
         * {@inheritDoc}
1271
         */
1272
        public WithFlexibleName withAnonymousClass(boolean anonymousClass) {
1273
            return new Default(name,
1✔
1274
                    modifiers,
1275
                    superClass,
1276
                    typeVariables,
1277
                    interfaceTypes,
1278
                    fieldTokens,
1279
                    auxiliaryFields,
1280
                    methodTokens,
1281
                    recordComponentTokens,
1282
                    annotationDescriptions,
1283
                    typeInitializer,
1284
                    loadedTypeInitializer,
1285
                    declaringType,
1286
                    enclosingMethod,
1287
                    enclosingType,
1288
                    declaredTypes,
1289
                    permittedSubclasses,
1290
                    anonymousClass,
1291
                    false,
1292
                    record,
1293
                    nestHost,
1294
                    nestMembers);
1295
        }
1296

1297
        /**
1298
         * {@inheritDoc}
1299
         */
1300
        public WithFlexibleName withRecord(boolean record) {
1301
            return new Default(name,
1✔
1302
                    modifiers,
1303
                    superClass,
1304
                    typeVariables,
1305
                    interfaceTypes,
1306
                    fieldTokens,
1307
                    auxiliaryFields,
1308
                    methodTokens,
1309
                    record
1310
                            ? recordComponentTokens
1311
                            : Collections.<RecordComponentDescription.Token>emptyList(),
1✔
1312
                    annotationDescriptions,
1313
                    typeInitializer,
1314
                    loadedTypeInitializer,
1315
                    declaringType,
1316
                    enclosingMethod,
1317
                    enclosingType,
1318
                    declaredTypes,
1319
                    permittedSubclasses,
1320
                    anonymousClass,
1321
                    localClass,
1322
                    record,
1323
                    nestHost,
1324
                    nestMembers);
1325
        }
1326

1327
        /**
1328
         * {@inheritDoc}
1329
         */
1330
        public WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitializer) {
1331
            return new Default(name,
1✔
1332
                    modifiers,
1333
                    superClass,
1334
                    typeVariables,
1335
                    interfaceTypes,
1336
                    fieldTokens,
1337
                    auxiliaryFields,
1338
                    methodTokens,
1339
                    recordComponentTokens,
1340
                    annotationDescriptions,
1341
                    typeInitializer,
1342
                    new LoadedTypeInitializer.Compound(this.loadedTypeInitializer, loadedTypeInitializer),
1343
                    declaringType,
1344
                    enclosingMethod,
1345
                    enclosingType,
1346
                    declaredTypes,
1347
                    permittedSubclasses,
1348
                    anonymousClass,
1349
                    localClass,
1350
                    record,
1351
                    nestHost,
1352
                    nestMembers);
1353
        }
1354

1355
        /**
1356
         * {@inheritDoc}
1357
         */
1358
        public WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender) {
1359
            return new Default(name,
1✔
1360
                    modifiers,
1361
                    superClass,
1362
                    typeVariables,
1363
                    interfaceTypes,
1364
                    fieldTokens,
1365
                    auxiliaryFields,
1366
                    methodTokens,
1367
                    recordComponentTokens,
1368
                    annotationDescriptions,
1369
                    typeInitializer.expandWith(byteCodeAppender),
1✔
1370
                    loadedTypeInitializer,
1371
                    declaringType,
1372
                    enclosingMethod,
1373
                    enclosingType,
1374
                    declaredTypes,
1375
                    permittedSubclasses,
1376
                    anonymousClass,
1377
                    localClass,
1378
                    record,
1379
                    nestHost,
1380
                    nestMembers);
1381
        }
1382

1383
        /**
1384
         * {@inheritDoc}
1385
         */
1386
        public LoadedTypeInitializer getLoadedTypeInitializer() {
1387
            return loadedTypeInitializer;
1✔
1388
        }
1389

1390
        /**
1391
         * {@inheritDoc}
1392
         */
1393
        public TypeInitializer getTypeInitializer() {
1394
            return typeInitializer;
1✔
1395
        }
1396

1397
        /**
1398
         * {@inheritDoc}
1399
         */
1400
        @MaybeNull
1401
        public MethodDescription.InDefinedShape getEnclosingMethod() {
1402
            return enclosingMethod;
1✔
1403
        }
1404

1405
        /**
1406
         * {@inheritDoc}
1407
         */
1408
        @MaybeNull
1409
        public TypeDescription getEnclosingType() {
1410
            return enclosingType;
1✔
1411
        }
1412

1413
        /**
1414
         * {@inheritDoc}
1415
         */
1416
        public TypeList getDeclaredTypes() {
1417
            return new TypeList.Explicit(declaredTypes);
1✔
1418
        }
1419

1420
        /**
1421
         * {@inheritDoc}
1422
         */
1423
        public boolean isAnonymousType() {
1424
            return anonymousClass;
1✔
1425
        }
1426

1427
        /**
1428
         * {@inheritDoc}
1429
         */
1430
        public boolean isLocalType() {
1431
            return localClass;
1✔
1432
        }
1433

1434
        /**
1435
         * {@inheritDoc}
1436
         */
1437
        @MaybeNull
1438
        public PackageDescription getPackage() {
1439
            int packageIndex = name.lastIndexOf('.');
1✔
1440
            return packageIndex == -1
1✔
1441
                    ? PackageDescription.DEFAULT
1442
                    : new PackageDescription.Simple(name.substring(0, packageIndex));
1✔
1443
        }
1444

1445
        /**
1446
         * {@inheritDoc}
1447
         */
1448
        public AnnotationList getDeclaredAnnotations() {
1449
            return new AnnotationList.Explicit(annotationDescriptions);
1✔
1450
        }
1451

1452
        /**
1453
         * {@inheritDoc}
1454
         */
1455
        @MaybeNull
1456
        public TypeDescription getDeclaringType() {
1457
            return declaringType;
1✔
1458
        }
1459

1460
        /**
1461
         * {@inheritDoc}
1462
         */
1463
        @MaybeNull
1464
        public Generic getSuperClass() {
1465
            return superClass == null
1✔
1466
                    ? Generic.UNDEFINED
1467
                    : new Generic.LazyProjection.WithResolvedErasure(superClass, Generic.Visitor.Substitutor.ForAttachment.of(this));
1✔
1468
        }
1469

1470
        /**
1471
         * {@inheritDoc}
1472
         */
1473
        public TypeList.Generic getInterfaces() {
1474
            return new TypeList.Generic.ForDetachedTypes.WithResolvedErasure(interfaceTypes, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
1✔
1475
        }
1476

1477
        /**
1478
         * {@inheritDoc}
1479
         */
1480
        public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
1481
            return new FieldList.ForTokens(this, fieldTokens);
1✔
1482
        }
1483

1484
        /**
1485
         * {@inheritDoc}
1486
         */
1487
        public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
1488
            return new MethodList.ForTokens(this, methodTokens);
1✔
1489
        }
1490

1491
        /**
1492
         * {@inheritDoc}
1493
         */
1494
        public TypeList.Generic getTypeVariables() {
1495
            return TypeList.Generic.ForDetachedTypes.attachVariables(this, typeVariables);
1✔
1496
        }
1497

1498
        /**
1499
         * {@inheritDoc}
1500
         */
1501
        public int getModifiers() {
1502
            return modifiers;
1✔
1503
        }
1504

1505
        /**
1506
         * {@inheritDoc}
1507
         */
1508
        public String getName() {
1509
            return name;
1✔
1510
        }
1511

1512
        /**
1513
         * {@inheritDoc}
1514
         */
1515
        public TypeDescription getNestHost() {
1516
            return nestHost.represents(TargetType.class)
1✔
1517
                    ? this
1518
                    : nestHost;
1519
        }
1520

1521
        /**
1522
         * {@inheritDoc}
1523
         */
1524
        public TypeList getNestMembers() {
1525
            return nestHost.represents(TargetType.class)
1✔
1526
                    ? new TypeList.Explicit(CompoundList.of(this, nestMembers))
1✔
1527
                    : nestHost.getNestMembers();
×
1528
        }
1529

1530
        /**
1531
         * {@inheritDoc}
1532
         */
1533
        public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
1534
            return new RecordComponentList.ForTokens(this, recordComponentTokens);
1✔
1535
        }
1536

1537
        /**
1538
         * {@inheritDoc}
1539
         */
1540
        @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming super class for given instance.")
1541
        public boolean isRecord() {
1542
            return record
1✔
1543
                    && superClass != null
1544
                    && getSuperClass().asErasure().equals(JavaType.RECORD.getTypeStub());
1✔
1545
        }
1546

1547
        @Override
1548
        public boolean isSealed() {
1549
            return permittedSubclasses != null;
1✔
1550
        }
1551

1552
        /**
1553
         * {@inheritDoc}
1554
         */
1555
        public TypeList getPermittedSubtypes() {
1556
            return permittedSubclasses == null
1✔
1557
                    ? new TypeList.Empty()
1558
                    : new TypeList.Explicit(permittedSubclasses);
1559
        }
1560

1561
        /**
1562
         * {@inheritDoc}
1563
         */
1564
        public TypeDescription validated() {
1565
            if (!isValidIdentifier(getName().split("\\."))) {
1✔
1566
                throw new IllegalStateException("Illegal type name: " + getName() + " for " + this);
1✔
1567
            } else if ((getModifiers() & ~ModifierContributor.ForType.MASK) != EMPTY_MASK) {
1✔
1568
                throw new IllegalStateException("Illegal modifiers " + getModifiers() + " for " + this);
1✔
1569
            } else if (isPackageType() && getModifiers() != PackageDescription.PACKAGE_MODIFIERS) {
1✔
1570
                throw new IllegalStateException("Illegal modifiers " + getModifiers() + " for package " + this);
1✔
1571
            }
1572
            TypeDescription.Generic superClass = getSuperClass();
1✔
1573
            if (superClass != null) {
1✔
1574
                if (!superClass.accept(Generic.Visitor.Validator.SUPER_CLASS)) {
1✔
1575
                    throw new IllegalStateException("Illegal super class " + superClass + " for " + this);
1✔
1576
                } else if (!superClass.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1577
                    throw new IllegalStateException("Illegal type annotations on super class " + superClass + " for " + this);
1✔
1578
                } else if (!superClass.asErasure().isVisibleTo(this)) {
1✔
1579
                    throw new IllegalStateException("Invisible super type " + superClass + " for " + this);
1✔
1580
                }
1581
            }
1582
            Set<TypeDescription> interfaceErasures = new HashSet<TypeDescription>();
1✔
1583
            for (TypeDescription.Generic interfaceType : getInterfaces()) {
1✔
1584
                if (!interfaceType.accept(Generic.Visitor.Validator.INTERFACE)) {
1✔
1585
                    throw new IllegalStateException("Illegal interface " + interfaceType + " for " + this);
1✔
1586
                } else if (!interfaceType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1587
                    throw new IllegalStateException("Illegal type annotations on interface " + interfaceType + " for " + this);
1✔
1588
                } else if (!interfaceErasures.add(interfaceType.asErasure())) {
1✔
1589
                    throw new IllegalStateException("Already implemented interface " + interfaceType + " for " + this);
1✔
1590
                } else if (!interfaceType.asErasure().isVisibleTo(this)) {
1✔
1591
                    throw new IllegalStateException("Invisible interface type " + interfaceType + " for " + this);
1✔
1592
                }
1593
            }
1✔
1594
            TypeList.Generic typeVariables = getTypeVariables();
1✔
1595
            if (!typeVariables.isEmpty() && isAssignableTo(Throwable.class)) {
1✔
1596
                throw new IllegalStateException("Cannot define throwable " + this + " to be generic");
1✔
1597
            }
1598
            Set<String> typeVariableNames = new HashSet<String>();
1✔
1599
            for (TypeDescription.Generic typeVariable : typeVariables) {
1✔
1600
                String variableSymbol = typeVariable.getSymbol();
1✔
1601
                if (!typeVariableNames.add(variableSymbol)) {
1✔
1602
                    throw new IllegalStateException("Duplicate type variable symbol '" + typeVariable + "' for " + this);
1✔
1603
                } else if (!isValidIdentifier(variableSymbol)) {
1✔
1604
                    throw new IllegalStateException("Illegal type variable name '" + typeVariable + "' for " + this);
1✔
1605
                } else if (!Generic.Visitor.Validator.ForTypeAnnotations.ofFormalTypeVariable(typeVariable)) {
1✔
1606
                    throw new IllegalStateException("Illegal type annotation on '" + typeVariable + "' for " + this);
1✔
1607
                }
1608
                boolean interfaceBound = false;
1✔
1609
                Set<TypeDescription.Generic> bounds = new HashSet<Generic>();
1✔
1610
                for (TypeDescription.Generic bound : typeVariable.getUpperBounds()) {
1✔
1611
                    if (!bound.accept(Generic.Visitor.Validator.TYPE_VARIABLE)) {
1✔
1612
                        throw new IllegalStateException("Illegal type variable bound " + bound + " of " + typeVariable + " for " + this);
1✔
1613
                    } else if (!bound.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1614
                        throw new IllegalStateException("Illegal type annotations on type variable " + bound + " for " + this);
1✔
1615
                    } else if (!bounds.add(bound)) {
1✔
1616
                        throw new IllegalStateException("Duplicate bound " + bound + " of " + typeVariable + " for " + this);
1✔
1617
                    } else if (interfaceBound && (bound.getSort().isTypeVariable() || !bound.isInterface())) {
1✔
1618
                        throw new IllegalStateException("Illegal interface bound " + bound + " of " + typeVariable + " for " + this);
1✔
1619
                    }
1620
                    interfaceBound = true;
1✔
1621
                }
1✔
1622
                if (!interfaceBound) {
1✔
1623
                    throw new IllegalStateException("Type variable " + typeVariable + " for " + this + " does not define at least one bound");
1✔
1624
                }
1625
            }
1✔
1626
            TypeDescription enclosingType = getEnclosingType();
1✔
1627
            if (enclosingType != null && (enclosingType.isArray() || enclosingType.isPrimitive())) {
1✔
1628
                throw new IllegalStateException("Cannot define array type or primitive type " + enclosingType + " + as enclosing type for " + this);
1✔
1629
            }
1630
            MethodDescription.InDefinedShape enclosingMethod = getEnclosingMethod();
1✔
1631
            if (enclosingMethod != null && enclosingMethod.isTypeInitializer()) {
1✔
1632
                throw new IllegalStateException("Cannot enclose type declaration in class initializer " + enclosingMethod);
×
1633
            }
1634
            TypeDescription declaringType = getDeclaringType();
1✔
1635
            if (declaringType != null) {
1✔
1636
                if (declaringType.isPrimitive() || declaringType.isArray()) {
1✔
1637
                    throw new IllegalStateException("Cannot define array type or primitive type " + declaringType + " as declaring type for " + this);
1✔
1638
                }
1639
            } else if (enclosingType == null && enclosingMethod == null && (isLocalType() || isAnonymousType())) {
1✔
1640
                throw new IllegalStateException("Cannot define an anonymous or local class without a declaring type for " + this);
1✔
1641
            }
1642
            Set<TypeDescription> declaredTypes = new HashSet<TypeDescription>();
1✔
1643
            for (TypeDescription declaredType : getDeclaredTypes()) {
1✔
1644
                if (declaredType.isArray() || declaredType.isPrimitive()) {
1✔
1645
                    throw new IllegalStateException("Cannot define array type or primitive type " + declaredType + " + as declared type for " + this);
1✔
1646
                } else if (!declaredTypes.add(declaredType)) {
1✔
1647
                    throw new IllegalStateException("Duplicate definition of declared type " + declaredType);
1✔
1648
                }
1649
            }
1✔
1650
            TypeDescription nestHost = getNestHost();
1✔
1651
            if (nestHost.equals(this)) {
1✔
1652
                Set<TypeDescription> nestMembers = new HashSet<TypeDescription>();
1✔
1653
                for (TypeDescription nestMember : getNestMembers()) {
1✔
1654
                    if (nestMember.isArray() || nestMember.isPrimitive()) {
1✔
1655
                        throw new IllegalStateException("Cannot define array type or primitive type " + nestMember + " + as nest member of " + this);
1✔
1656
                    } else if (!nestMember.isSamePackage(this)) {
1✔
1657
                        throw new IllegalStateException("Cannot define nest member " + nestMember + " + within different package then " + this);
1✔
1658
                    } else if (!nestMembers.add(nestMember)) {
1✔
1659
                        throw new IllegalStateException("Duplicate definition of nest member " + nestMember);
1✔
1660
                    }
1661
                }
1✔
1662
            } else if (nestHost.isArray() || nestHost.isPrimitive()) {
1✔
1663
                throw new IllegalStateException("Cannot define array type or primitive type " + nestHost + " + as nest host for " + this);
1✔
1664
            } else if (!nestHost.isSamePackage(this)) {
1✔
1665
                throw new IllegalStateException("Cannot define nest host " + nestHost + " within different package then " + this);
1✔
1666
            }
1667
            for (TypeDescription permittedSubclass : getPermittedSubtypes()) {
1✔
1668
                if (!permittedSubclass.isAssignableTo(this) || permittedSubclass.equals(this)) {
1✔
1669
                    throw new IllegalStateException("Cannot assign permitted subclass " + permittedSubclass + " to " + this);
1✔
1670
                }
1671
            }
×
1672
            Set<TypeDescription> typeAnnotationTypes = new HashSet<TypeDescription>();
1✔
1673
            for (AnnotationDescription annotationDescription : getDeclaredAnnotations()) {
1✔
1674
                if (!annotationDescription.isSupportedOn(ElementType.TYPE)
1✔
1675
                        && !(isAnnotation() && annotationDescription.isSupportedOn(ElementType.ANNOTATION_TYPE))
1✔
1676
                        && !(isPackageType() && annotationDescription.isSupportedOn(ElementType.PACKAGE))) {
1✔
1677
                    throw new IllegalStateException("Cannot add " + annotationDescription + " on " + this);
1✔
1678
                } else if (!typeAnnotationTypes.add(annotationDescription.getAnnotationType())) {
1✔
1679
                    throw new IllegalStateException("Duplicate annotation " + annotationDescription + " for " + this);
1✔
1680
                }
1681
            }
1✔
1682
            Set<FieldDescription.SignatureToken> fieldSignatureTokens = new HashSet<FieldDescription.SignatureToken>();
1✔
1683
            for (FieldDescription.InDefinedShape fieldDescription : getDeclaredFields()) {
1✔
1684
                String fieldName = fieldDescription.getName();
1✔
1685
                if (!fieldSignatureTokens.add(fieldDescription.asSignatureToken())) {
1✔
1686
                    throw new IllegalStateException("Duplicate field definition for " + fieldDescription);
1✔
1687
                } else if (!isValidUnqualifiedNameIdentifier(fieldName)) {
1✔
1688
                    throw new IllegalStateException("Illegal field name for " + fieldDescription);
1✔
1689
                } else if ((fieldDescription.getModifiers() & ~ModifierContributor.ForField.MASK) != EMPTY_MASK) {
1✔
1690
                    throw new IllegalStateException("Illegal field modifiers " + fieldDescription.getModifiers() + " for " + fieldDescription);
1✔
1691
                }
1692
                Generic fieldType = fieldDescription.getType();
1✔
1693
                if (!fieldType.accept(Generic.Visitor.Validator.FIELD)) {
1✔
1694
                    throw new IllegalStateException("Illegal field type " + fieldType + " for " + fieldDescription);
×
1695
                } else if (!fieldType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1696
                    throw new IllegalStateException("Illegal type annotations on " + fieldType + " for " + this);
1✔
1697
                } else if (!fieldDescription.isSynthetic() && !fieldType.asErasure().isVisibleTo(this)) {
1✔
1698
                    throw new IllegalStateException("Invisible field type " + fieldDescription.getType() + " for " + fieldDescription);
1✔
1699
                }
1700
                Set<TypeDescription> fieldAnnotationTypes = new HashSet<TypeDescription>();
1✔
1701
                for (AnnotationDescription annotationDescription : fieldDescription.getDeclaredAnnotations()) {
1✔
1702
                    if (!annotationDescription.isSupportedOn(ElementType.FIELD)) {
1✔
1703
                        throw new IllegalStateException("Cannot add " + annotationDescription + " on " + fieldDescription);
1✔
1704
                    } else if (!fieldAnnotationTypes.add(annotationDescription.getAnnotationType())) {
1✔
1705
                        throw new IllegalStateException("Duplicate annotation " + annotationDescription + " for " + fieldDescription);
1✔
1706
                    }
1707
                }
1✔
1708
            }
1✔
1709
            Set<MethodDescription.SignatureToken> methodSignatureTokens = new HashSet<MethodDescription.SignatureToken>();
1✔
1710
            for (MethodDescription.InDefinedShape methodDescription : getDeclaredMethods()) {
1✔
1711
                if (!methodSignatureTokens.add(methodDescription.asSignatureToken())) {
1✔
1712
                    throw new IllegalStateException("Duplicate method signature for " + methodDescription);
1✔
1713
                } else if ((methodDescription.getModifiers() & ~ModifierContributor.ForMethod.MASK) != 0) {
1✔
1714
                    throw new IllegalStateException("Illegal modifiers " + methodDescription.getModifiers() + " for " + methodDescription);
1✔
1715
                } else if (methodDescription.isAbstract() && (methodDescription.getModifiers() & Opcodes.ACC_STRICT) != 0) {
1✔
1716
                    throw new IllegalStateException("Cannot declare strict computations for " + methodDescription);
×
1717
                } else if (isInterface() && !methodDescription.isPublic() && !methodDescription.isPrivate()) {
1✔
1718
                    throw new IllegalStateException("Methods declared by an interface must be public or private " + methodDescription);
1✔
1719
                }
1720
                Set<String> methodTypeVariableNames = new HashSet<String>();
1✔
1721
                for (TypeDescription.Generic typeVariable : methodDescription.getTypeVariables()) {
1✔
1722
                    String variableSymbol = typeVariable.getSymbol();
1✔
1723
                    if (!methodTypeVariableNames.add(variableSymbol)) {
1✔
1724
                        throw new IllegalStateException("Duplicate type variable symbol '" + typeVariable + "' for " + methodDescription);
1✔
1725
                    } else if (!isValidIdentifier(variableSymbol)) {
1✔
1726
                        throw new IllegalStateException("Illegal type variable name '" + typeVariable + "' for " + methodDescription);
1✔
1727
                    } else if (!Generic.Visitor.Validator.ForTypeAnnotations.ofFormalTypeVariable(typeVariable)) {
1✔
1728
                        throw new IllegalStateException("Illegal type annotation on '" + typeVariable + "' for " + methodDescription);
1✔
1729
                    }
1730
                    boolean interfaceBound = false;
1✔
1731
                    Set<TypeDescription.Generic> bounds = new HashSet<Generic>();
1✔
1732
                    for (TypeDescription.Generic bound : typeVariable.getUpperBounds()) {
1✔
1733
                        if (!bound.accept(Generic.Visitor.Validator.TYPE_VARIABLE)) {
1✔
1734
                            throw new IllegalStateException("Illegal type variable bound " + bound + " of " + typeVariable + " for " + methodDescription);
1✔
1735
                        } else if (!bound.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1736
                            throw new IllegalStateException("Illegal type annotations on bound " + bound + " of " + typeVariable + " for " + this);
1✔
1737
                        } else if (!bounds.add(bound)) {
1✔
1738
                            throw new IllegalStateException("Duplicate bound " + bound + " of " + typeVariable + " for " + methodDescription);
1✔
1739
                        } else if (interfaceBound && (bound.getSort().isTypeVariable() || !bound.isInterface())) {
1✔
1740
                            throw new IllegalStateException("Illegal interface bound " + bound + " of " + typeVariable + " for " + methodDescription);
1✔
1741
                        }
1742
                        interfaceBound = true;
1✔
1743
                    }
1✔
1744
                    if (!interfaceBound) {
1✔
1745
                        throw new IllegalStateException("Type variable " + typeVariable + " for " + methodDescription + " does not define at least one bound");
1✔
1746
                    }
1747
                }
1✔
1748
                Generic returnType = methodDescription.getReturnType();
1✔
1749
                if (methodDescription.isTypeInitializer()) {
1✔
1750
                    throw new IllegalStateException("Illegal explicit declaration of a type initializer by " + this);
1✔
1751
                } else if (methodDescription.isConstructor()) {
1✔
1752
                    if (!returnType.represents(void.class)) {
1✔
1753
                        throw new IllegalStateException("A constructor must return void " + methodDescription);
1✔
1754
                    } else if (!returnType.getDeclaredAnnotations().isEmpty()) {
1✔
1755
                        throw new IllegalStateException("The void non-type must not be annotated for " + methodDescription);
×
1756
                    }
1757
                } else if (!isValidMethodIdentifier(methodDescription.getInternalName())) {
1✔
1758
                    throw new IllegalStateException("Illegal method name " + returnType + " for " + methodDescription);
1✔
1759
                } else if (!returnType.accept(Generic.Visitor.Validator.METHOD_RETURN)) {
1✔
1760
                    throw new IllegalStateException("Illegal return type " + returnType + " for " + methodDescription);
×
1761
                } else if (!returnType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1762
                    throw new IllegalStateException("Illegal type annotations on return type " + returnType + " for " + methodDescription);
1✔
1763
                } else if (!methodDescription.isSynthetic() && !methodDescription.getReturnType().asErasure().isVisibleTo(this)) {
1✔
1764
                    throw new IllegalStateException("Invisible return type " + methodDescription.getReturnType() + " for " + methodDescription);
1✔
1765
                }
1766
                Set<String> parameterNames = new HashSet<String>();
1✔
1767
                for (ParameterDescription.InDefinedShape parameterDescription : methodDescription.getParameters()) {
1✔
1768
                    Generic parameterType = parameterDescription.getType();
1✔
1769
                    if (!parameterType.accept(Generic.Visitor.Validator.METHOD_PARAMETER)) {
1✔
1770
                        throw new IllegalStateException("Illegal parameter type of " + parameterDescription + " for " + methodDescription);
1✔
1771
                    } else if (!parameterType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1772
                        throw new IllegalStateException("Illegal type annotations on parameter " + parameterDescription + " for " + methodDescription);
×
1773
                    } else if (!methodDescription.isSynthetic() && !parameterType.asErasure().isVisibleTo(this)) {
1✔
1774
                        throw new IllegalStateException("Invisible parameter type of " + parameterDescription + " for " + methodDescription);
1✔
1775
                    }
1776
                    if (parameterDescription.isNamed()) {
1✔
1777
                        String parameterName = parameterDescription.getName();
1✔
1778
                        if (!parameterNames.add(parameterName)) {
1✔
1779
                            throw new IllegalStateException("Duplicate parameter name of " + parameterDescription + " for " + methodDescription);
1✔
1780
                        } else if (!isValidUnqualifiedNameIdentifier(parameterName)) {
1✔
1781
                            throw new IllegalStateException("Illegal parameter name of " + parameterDescription + " for " + methodDescription);
1✔
1782
                        }
1783
                    }
1784
                    if (parameterDescription.hasModifiers() && (parameterDescription.getModifiers() & ~ModifierContributor.ForParameter.MASK) != EMPTY_MASK) {
1✔
1785
                        throw new IllegalStateException("Illegal modifiers of " + parameterDescription + " for " + methodDescription);
1✔
1786
                    }
1787
                    Set<TypeDescription> parameterAnnotationTypes = new HashSet<TypeDescription>();
1✔
1788
                    for (AnnotationDescription annotationDescription : parameterDescription.getDeclaredAnnotations()) {
1✔
1789
                        if (!annotationDescription.isSupportedOn(ElementType.PARAMETER)) {
1✔
1790
                            throw new IllegalStateException("Cannot add " + annotationDescription + " on " + parameterDescription);
1✔
1791
                        } else if (!parameterAnnotationTypes.add(annotationDescription.getAnnotationType())) {
1✔
1792
                            throw new IllegalStateException("Duplicate annotation " + annotationDescription + " of " + parameterDescription + " for " + methodDescription);
1✔
1793
                        }
1794
                    }
1✔
1795
                }
1✔
1796
                for (TypeDescription.Generic exceptionType : methodDescription.getExceptionTypes()) {
1✔
1797
                    if (!exceptionType.accept(Generic.Visitor.Validator.EXCEPTION)) {
1✔
1798
                        throw new IllegalStateException("Illegal exception type " + exceptionType + " for " + methodDescription);
1✔
1799
                    } else if (!exceptionType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
1✔
1800
                        throw new IllegalStateException("Illegal type annotations on " + exceptionType + " for " + methodDescription);
1✔
1801
                    } else if (!methodDescription.isSynthetic() && !exceptionType.asErasure().isVisibleTo(this)) {
1✔
1802
                        throw new IllegalStateException("Invisible exception type " + exceptionType + " for " + methodDescription);
1✔
1803
                    }
1804
                }
1✔
1805
                Set<TypeDescription> methodAnnotationTypes = new HashSet<TypeDescription>();
1✔
1806
                for (AnnotationDescription annotationDescription : methodDescription.getDeclaredAnnotations()) {
1✔
1807
                    if (!annotationDescription.isSupportedOn(methodDescription.isMethod() ? ElementType.METHOD : ElementType.CONSTRUCTOR)) {
1✔
1808
                        throw new IllegalStateException("Cannot add " + annotationDescription + " on " + methodDescription);
1✔
1809
                    } else if (!methodAnnotationTypes.add(annotationDescription.getAnnotationType())) {
1✔
1810
                        throw new IllegalStateException("Duplicate annotation " + annotationDescription + " for " + methodDescription);
1✔
1811
                    }
1812
                }
1✔
1813
                AnnotationValue<?, ?> defaultValue = methodDescription.getDefaultValue();
1✔
1814
                if (defaultValue != null && !methodDescription.isDefaultValue(defaultValue)) {
1✔
1815
                    throw new IllegalStateException("Illegal default value " + defaultValue + "for " + methodDescription);
1✔
1816
                }
1817
                Generic receiverType = methodDescription.getReceiverType();
1✔
1818
                if (receiverType != null && !receiverType.accept(Generic.Visitor.Validator.RECEIVER)) {
1✔
1819
                    throw new IllegalStateException("Illegal receiver type " + receiverType + " for " + methodDescription);
×
1820
                } else if (methodDescription.isStatic()) {
1✔
1821
                    if (receiverType != null) {
1✔
1822
                        throw new IllegalStateException("Static method " + methodDescription + " defines a non-null receiver " + receiverType);
1✔
1823
                    }
1824
                } else if (methodDescription.isConstructor()) {
1✔
1825
                    if (receiverType == null || !receiverType.asErasure().equals(enclosingType == null ? this : enclosingType)) {
1✔
1826
                        throw new IllegalStateException("Constructor " + methodDescription + " defines an illegal receiver " + receiverType);
×
1827
                    }
1828
                } else if (/* methodDescription.isMethod() */ receiverType == null || !equals(receiverType.asErasure())) {
1✔
1829
                    throw new IllegalStateException("Method " + methodDescription + " defines an illegal receiver " + receiverType);
1✔
1830
                }
1831
            }
1✔
1832
            return this;
1✔
1833
        }
1834

1835
        /**
1836
         * Checks if an array of identifiers is a valid compound Java identifier.
1837
         *
1838
         * @param identifier an array of potentially invalid Java identifiers.
1839
         * @return {@code true} if all identifiers are valid and the array is not empty.
1840
         */
1841
        private static boolean isValidIdentifier(String[] identifier) {
1842
            if (identifier.length == 0) {
1✔
1843
                return false;
×
1844
            }
1845
            for (String part : identifier) {
1✔
1846
                if (!isValidIdentifier(part)) {
1✔
1847
                    return false;
1✔
1848
                }
1849
            }
1850
            return true;
1✔
1851
        }
1852

1853
        /**
1854
         * Checks if a Java identifier is valid.
1855
         *
1856
         * @param identifier The identifier to check for validity.
1857
         * @return {@code true} if the given identifier is valid.
1858
         */
1859
        private static boolean isValidIdentifier(String identifier) {
1860
            if (KEYWORDS.contains(identifier)
1✔
1861
                    || identifier.length() == 0
1✔
1862
                    || !(Character.isJavaIdentifierStart(identifier.charAt(0))
1✔
1863
                    || Character.isUnicodeIdentifierStart(identifier.charAt(0)))) {
×
1864
                return false;
1✔
1865
            } else if (identifier.equals(PackageDescription.PACKAGE_CLASS_NAME)) {
1✔
1866
                return true;
1✔
1867
            }
1868
            for (int index = 1; index < identifier.length(); index++) {
1✔
1869
                if (!(Character.isJavaIdentifierPart(identifier.charAt(index)) || Character.isUnicodeIdentifierPart(identifier.charAt(index)))) {
1✔
1870
                    return false;
1✔
1871
                }
1872
            }
1873
            return true;
1✔
1874
        }
1875

1876
        /**
1877
         * Checks if an identifier is a valid "Unqualified Name" for a field, a local variable or a formal parameter,
1878
         * per JVMS 4.2.2.
1879
         *
1880
         * @param identifier The identifier to check for validity.
1881
         * @return {@code true} if the given identifier is valid.
1882
         */
1883
        private static boolean isValidUnqualifiedNameIdentifier(String identifier) {
1884
            if (identifier.length() == 0) {
1✔
1885
                return false;
×
1886
            }
1887
            for (int index = 0; index < identifier.length(); index++) {
1✔
1888
                switch (identifier.charAt(index)) {
1✔
1889
                    case '.':
1890
                    case ';':
1891
                    case '[':
1892
                    case '/':
1893
                        return false;
1✔
1894
                }
1895
            }
1896
            return true;
1✔
1897
        }
1898

1899
        /**
1900
         * Checks if an identifier is a valid "Unqualified Name" for a method, per JVMS 4.2.2.
1901
         *
1902
         * @param identifier The identifier to check for validity.
1903
         * @return {@code true} if the given identifier is valid.
1904
         */
1905
        private static boolean isValidMethodIdentifier(String identifier) {
1906
            if (identifier.length() == 0) {
1✔
1907
                return false;
×
1908
            }
1909
            if (identifier.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)
1✔
1910
                    || identifier.equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME)) {
1✔
1911
                return true;
×
1912
            }
1913
            for (int index = 0; index < identifier.length(); index++) {
1✔
1914
                switch (identifier.charAt(index)) {
1✔
1915
                    case '.':
1916
                    case ';':
1917
                    case '[':
1918
                    case '/':
1919
                    case '<':
1920
                    case '>':
1921
                        return false;
1✔
1922
                }
1923
            }
1924
            return true;
1✔
1925
        }
1926
    }
1927

1928
    /**
1929
     * A frozen representation of an instrumented type of which the structure must not be modified.
1930
     */
1931
    class Frozen extends AbstractBase.OfSimpleType implements InstrumentedType.WithFlexibleName {
1932

1933
        /**
1934
         * The represented type description.
1935
         */
1936
        private final TypeDescription typeDescription;
1937

1938
        /**
1939
         * The type's loaded type initializer.
1940
         */
1941
        private final LoadedTypeInitializer loadedTypeInitializer;
1942

1943
        /**
1944
         * Creates a new frozen representation of an instrumented type.
1945
         *
1946
         * @param typeDescription       The represented type description.
1947
         * @param loadedTypeInitializer The type's loaded type initializer.
1948
         */
1949
        protected Frozen(TypeDescription typeDescription, LoadedTypeInitializer loadedTypeInitializer) {
1✔
1950
            this.typeDescription = typeDescription;
1✔
1951
            this.loadedTypeInitializer = loadedTypeInitializer;
1✔
1952
        }
1✔
1953

1954
        /**
1955
         * {@inheritDoc}
1956
         */
1957
        public AnnotationList getDeclaredAnnotations() {
1958
            return typeDescription.getDeclaredAnnotations();
1✔
1959
        }
1960

1961
        /**
1962
         * {@inheritDoc}
1963
         */
1964
        public int getModifiers() {
1965
            return typeDescription.getModifiers();
1✔
1966
        }
1967

1968
        /**
1969
         * {@inheritDoc}
1970
         */
1971
        public TypeList.Generic getTypeVariables() {
1972
            return typeDescription.getTypeVariables();
1✔
1973
        }
1974

1975
        /**
1976
         * {@inheritDoc}
1977
         */
1978
        public String getName() {
1979
            return typeDescription.getName();
1✔
1980
        }
1981

1982
        /**
1983
         * {@inheritDoc}
1984
         */
1985
        @MaybeNull
1986
        public Generic getSuperClass() {
1987
            return typeDescription.getSuperClass();
1✔
1988
        }
1989

1990
        /**
1991
         * {@inheritDoc}
1992
         */
1993
        public TypeList.Generic getInterfaces() {
1994
            return typeDescription.getInterfaces();
1✔
1995
        }
1996

1997
        /**
1998
         * {@inheritDoc}
1999
         */
2000
        public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
2001
            return typeDescription.getDeclaredFields();
1✔
2002
        }
2003

2004
        /**
2005
         * {@inheritDoc}
2006
         */
2007
        public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
2008
            return typeDescription.getDeclaredMethods();
1✔
2009
        }
2010

2011
        /**
2012
         * {@inheritDoc}
2013
         */
2014
        public boolean isAnonymousType() {
2015
            return typeDescription.isAnonymousType();
1✔
2016
        }
2017

2018
        /**
2019
         * {@inheritDoc}
2020
         */
2021
        public boolean isLocalType() {
2022
            return typeDescription.isLocalType();
1✔
2023
        }
2024

2025
        /**
2026
         * {@inheritDoc}
2027
         */
2028
        @MaybeNull
2029
        public PackageDescription getPackage() {
2030
            return typeDescription.getPackage();
1✔
2031
        }
2032

2033
        /**
2034
         * {@inheritDoc}
2035
         */
2036
        @MaybeNull
2037
        public TypeDescription getEnclosingType() {
2038
            return typeDescription.getEnclosingType();
1✔
2039
        }
2040

2041
        /**
2042
         * {@inheritDoc}
2043
         */
2044
        @MaybeNull
2045
        public TypeDescription getDeclaringType() {
2046
            return typeDescription.getDeclaringType();
1✔
2047
        }
2048

2049
        /**
2050
         * {@inheritDoc}
2051
         */
2052
        public TypeList getDeclaredTypes() {
2053
            return typeDescription.getDeclaredTypes();
1✔
2054
        }
2055

2056
        /**
2057
         * {@inheritDoc}
2058
         */
2059
        @MaybeNull
2060
        public MethodDescription.InDefinedShape getEnclosingMethod() {
2061
            return typeDescription.getEnclosingMethod();
1✔
2062
        }
2063

2064
        /**
2065
         * {@inheritDoc}
2066
         */
2067
        @MaybeNull
2068
        public String getGenericSignature() {
2069
            // Embrace use of native generic signature by direct delegation.
2070
            return typeDescription.getGenericSignature();
1✔
2071
        }
2072

2073
        /**
2074
         * {@inheritDoc}
2075
         */
2076
        public int getActualModifiers(boolean superFlag) {
2077
            // Embrace use of native actual modifiers by direct delegation.
2078
            return typeDescription.getActualModifiers(superFlag);
1✔
2079
        }
2080

2081
        /**
2082
         * {@inheritDoc}
2083
         */
2084
        public TypeDescription getNestHost() {
2085
            return typeDescription.getNestHost();
1✔
2086
        }
2087

2088
        /**
2089
         * {@inheritDoc}
2090
         */
2091
        public TypeList getNestMembers() {
2092
            return typeDescription.getNestMembers();
1✔
2093
        }
2094

2095
        /**
2096
         * {@inheritDoc}
2097
         */
2098
        public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
2099
            return typeDescription.getRecordComponents();
1✔
2100
        }
2101

2102
        /**
2103
         * {@inheritDoc}
2104
         */
2105
        public boolean isRecord() {
2106
            return typeDescription.isRecord();
×
2107
        }
2108

2109
        @Override
2110
        public boolean isSealed() {
2111
            return typeDescription.isSealed();
1✔
2112
        }
2113

2114
        /**
2115
         * {@inheritDoc}
2116
         */
2117
        public TypeList getPermittedSubtypes() {
2118
            return typeDescription.getPermittedSubtypes();
1✔
2119
        }
2120

2121
        /**
2122
         * {@inheritDoc}
2123
         */
2124
        public WithFlexibleName withField(FieldDescription.Token token) {
2125
            throw new IllegalStateException("Cannot define field for frozen type: " + typeDescription);
1✔
2126
        }
2127

2128
        /**
2129
         * {@inheritDoc}
2130
         */
2131
        public WithFlexibleName withAuxiliaryField(FieldDescription.Token token, Object value) {
2132
            throw new IllegalStateException("Cannot define auxiliary field for frozen type: " + typeDescription);
1✔
2133
        }
2134

2135
        /**
2136
         * {@inheritDoc}
2137
         */
2138
        public WithFlexibleName withMethod(MethodDescription.Token token) {
2139
            throw new IllegalStateException("Cannot define method for frozen type: " + typeDescription);
1✔
2140
        }
2141

2142
        /**
2143
         * {@inheritDoc}
2144
         */
2145
        public WithFlexibleName withRecordComponent(RecordComponentDescription.Token token) {
2146
            throw new IllegalStateException("Cannot define record component for frozen type: " + typeDescription);
1✔
2147
        }
2148

2149
        /**
2150
         * {@inheritDoc}
2151
         */
2152
        public WithFlexibleName withModifiers(int modifiers) {
2153
            throw new IllegalStateException("Cannot change modifiers for frozen type: " + typeDescription);
×
2154
        }
2155

2156
        /**
2157
         * {@inheritDoc}
2158
         */
2159
        public WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes) {
2160
            throw new IllegalStateException("Cannot add interfaces for frozen type: " + typeDescription);
×
2161
        }
2162

2163
        /**
2164
         * {@inheritDoc}
2165
         */
2166
        public WithFlexibleName withTypeVariable(TypeVariableToken typeVariable) {
2167
            throw new IllegalStateException("Cannot define type variable for frozen type: " + typeDescription);
1✔
2168
        }
2169

2170
        /**
2171
         * {@inheritDoc}
2172
         */
2173
        public WithFlexibleName withAnnotations(List<? extends AnnotationDescription> annotationDescriptions) {
2174
            throw new IllegalStateException("Cannot add annotation to frozen type: " + typeDescription);
1✔
2175
        }
2176

2177
        /**
2178
         * {@inheritDoc}
2179
         */
2180
        public WithFlexibleName withNestHost(TypeDescription nestHost) {
2181
            throw new IllegalStateException("Cannot set nest host of frozen type: " + typeDescription);
1✔
2182
        }
2183

2184
        /**
2185
         * {@inheritDoc}
2186
         */
2187
        public WithFlexibleName withNestMembers(TypeList nestMembers) {
2188
            throw new IllegalStateException("Cannot add nest members to frozen type: " + typeDescription);
1✔
2189
        }
2190

2191
        /**
2192
         * {@inheritDoc}
2193
         */
2194
        public WithFlexibleName withEnclosingType(@MaybeNull TypeDescription enclosingType) {
2195
            throw new IllegalStateException("Cannot set enclosing type of frozen type: " + typeDescription);
1✔
2196
        }
2197

2198
        /**
2199
         * {@inheritDoc}
2200
         */
2201
        public WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod) {
2202
            throw new IllegalStateException("Cannot set enclosing method of frozen type: " + typeDescription);
1✔
2203
        }
2204

2205
        /**
2206
         * {@inheritDoc}
2207
         */
2208
        public WithFlexibleName withDeclaringType(@MaybeNull TypeDescription declaringType) {
2209
            throw new IllegalStateException("Cannot add declaring type to frozen type: " + typeDescription);
1✔
2210
        }
2211

2212
        /**
2213
         * {@inheritDoc}
2214
         */
2215
        public WithFlexibleName withDeclaredTypes(TypeList declaredTypes) {
2216
            throw new IllegalStateException("Cannot add declared types to frozen type: " + typeDescription);
1✔
2217
        }
2218

2219
        /**
2220
         * {@inheritDoc}
2221
         */
2222
        public WithFlexibleName withPermittedSubclasses(@MaybeNull TypeList permittedSubclasses) {
2223
            throw new IllegalStateException("Cannot add permitted subclasses to frozen type: " + typeDescription);
1✔
2224
        }
2225

2226
        /**
2227
         * {@inheritDoc}
2228
         */
2229
        public WithFlexibleName withLocalClass(boolean localClass) {
2230
            throw new IllegalStateException("Cannot define local class state for frozen type: " + typeDescription);
1✔
2231
        }
2232

2233
        /**
2234
         * {@inheritDoc}
2235
         */
2236
        public WithFlexibleName withAnonymousClass(boolean anonymousClass) {
2237
            throw new IllegalStateException("Cannot define anonymous class state for frozen type: " + typeDescription);
1✔
2238
        }
2239

2240
        /**
2241
         * {@inheritDoc}
2242
         */
2243
        public WithFlexibleName withRecord(boolean record) {
2244
            throw new IllegalStateException("Cannot define record state for frozen type: " + typeDescription);
1✔
2245
        }
2246

2247
        /**
2248
         * {@inheritDoc}
2249
         */
2250
        public WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitializer) {
2251
            return new Frozen(typeDescription, new LoadedTypeInitializer.Compound(this.loadedTypeInitializer, loadedTypeInitializer));
×
2252
        }
2253

2254
        /**
2255
         * {@inheritDoc}
2256
         */
2257
        public WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender) {
2258
            throw new IllegalStateException("Cannot add initializer to frozen type: " + typeDescription);
1✔
2259
        }
2260

2261
        /**
2262
         * {@inheritDoc}
2263
         */
2264
        public WithFlexibleName withName(String name) {
2265
            throw new IllegalStateException("Cannot change name of frozen type: " + typeDescription);
1✔
2266
        }
2267

2268
        /**
2269
         * {@inheritDoc}
2270
         */
2271
        public WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matcher, Transformer<TypeVariableToken> transformer) {
2272
            throw new IllegalStateException("Cannot add type variables of frozen type: " + typeDescription);
1✔
2273
        }
2274

2275
        /**
2276
         * {@inheritDoc}
2277
         */
2278
        public LoadedTypeInitializer getLoadedTypeInitializer() {
2279
            return loadedTypeInitializer;
1✔
2280
        }
2281

2282
        /**
2283
         * {@inheritDoc}
2284
         */
2285
        public TypeInitializer getTypeInitializer() {
2286
            return TypeInitializer.None.INSTANCE;
1✔
2287
        }
2288

2289
        @MaybeNull
2290
        @Override
2291
        public ClassFileVersion getClassFileVersion() {
2292
            return typeDescription.getClassFileVersion();
1✔
2293
        }
2294

2295
        /**
2296
         * {@inheritDoc}
2297
         */
2298
        public TypeDescription validated() {
2299
            return typeDescription;
1✔
2300
        }
2301
    }
2302
}
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