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

raphw / byte-buddy / #802

27 Oct 2025 09:58AM UTC coverage: 84.697% (-0.02%) from 84.715%
#802

push

raphw
Add method to expose possible module information of a type.

3 of 11 new or added lines in 4 files covered. (27.27%)

51 existing lines in 2 files now uncovered.

29589 of 34935 relevant lines covered (84.7%)

0.85 hits per line

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

95.7
/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.module.ModuleDescription;
30
import net.bytebuddy.description.type.PackageDescription;
31
import net.bytebuddy.description.type.RecordComponentDescription;
32
import net.bytebuddy.description.type.RecordComponentList;
33
import net.bytebuddy.description.type.TypeDescription;
34
import net.bytebuddy.description.type.TypeList;
35
import net.bytebuddy.description.type.TypeVariableToken;
36
import net.bytebuddy.dynamic.TargetType;
37
import net.bytebuddy.dynamic.Transformer;
38
import net.bytebuddy.implementation.LoadedTypeInitializer;
39
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
40
import net.bytebuddy.matcher.ElementMatcher;
41
import net.bytebuddy.utility.CompoundList;
42
import net.bytebuddy.utility.JavaType;
43
import net.bytebuddy.utility.nullability.MaybeNull;
44
import org.objectweb.asm.Opcodes;
45

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1446
        /**
1447
         * {@inheritDoc}
1448
         */
1449
        @MaybeNull
1450
        public ModuleDescription toModuleDescription() {
NEW
1451
            return ModuleDescription.UNDEFINED;
×
1452
        }
1453

1454
        /**
1455
         * {@inheritDoc}
1456
         */
1457
        public AnnotationList getDeclaredAnnotations() {
1458
            return new AnnotationList.Explicit(annotationDescriptions);
1✔
1459
        }
1460

1461
        /**
1462
         * {@inheritDoc}
1463
         */
1464
        @MaybeNull
1465
        public TypeDescription getDeclaringType() {
1466
            return declaringType;
1✔
1467
        }
1468

1469
        /**
1470
         * {@inheritDoc}
1471
         */
1472
        @MaybeNull
1473
        public Generic getSuperClass() {
1474
            return superClass == null
1✔
1475
                    ? Generic.UNDEFINED
1476
                    : new Generic.LazyProjection.WithResolvedErasure(superClass, Generic.Visitor.Substitutor.ForAttachment.of(this));
1✔
1477
        }
1478

1479
        /**
1480
         * {@inheritDoc}
1481
         */
1482
        public TypeList.Generic getInterfaces() {
1483
            return new TypeList.Generic.ForDetachedTypes.WithResolvedErasure(interfaceTypes, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
1✔
1484
        }
1485

1486
        /**
1487
         * {@inheritDoc}
1488
         */
1489
        public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
1490
            return new FieldList.ForTokens(this, fieldTokens);
1✔
1491
        }
1492

1493
        /**
1494
         * {@inheritDoc}
1495
         */
1496
        public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
1497
            return new MethodList.ForTokens(this, methodTokens);
1✔
1498
        }
1499

1500
        /**
1501
         * {@inheritDoc}
1502
         */
1503
        public TypeList.Generic getTypeVariables() {
1504
            return TypeList.Generic.ForDetachedTypes.attachVariables(this, typeVariables);
1✔
1505
        }
1506

1507
        /**
1508
         * {@inheritDoc}
1509
         */
1510
        public int getModifiers() {
1511
            return modifiers;
1✔
1512
        }
1513

1514
        /**
1515
         * {@inheritDoc}
1516
         */
1517
        public String getName() {
1518
            return name;
1✔
1519
        }
1520

1521
        /**
1522
         * {@inheritDoc}
1523
         */
1524
        public TypeDescription getNestHost() {
1525
            return nestHost.represents(TargetType.class)
1✔
1526
                    ? this
1527
                    : nestHost;
1528
        }
1529

1530
        /**
1531
         * {@inheritDoc}
1532
         */
1533
        public TypeList getNestMembers() {
1534
            return nestHost.represents(TargetType.class)
1✔
1535
                    ? new TypeList.Explicit(CompoundList.of(this, nestMembers))
1✔
1536
                    : nestHost.getNestMembers();
×
1537
        }
1538

1539
        /**
1540
         * {@inheritDoc}
1541
         */
1542
        public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
1543
            return new RecordComponentList.ForTokens(this, recordComponentTokens);
1✔
1544
        }
1545

1546
        /**
1547
         * {@inheritDoc}
1548
         */
1549
        @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE", justification = "Assuming super class for given instance.")
1550
        public boolean isRecord() {
1551
            return record
1✔
1552
                    && superClass != null
1553
                    && getSuperClass().asErasure().equals(JavaType.RECORD.getTypeStub());
1✔
1554
        }
1555

1556
        @Override
1557
        public boolean isSealed() {
1558
            return permittedSubclasses != null;
1✔
1559
        }
1560

1561
        /**
1562
         * {@inheritDoc}
1563
         */
1564
        public TypeList getPermittedSubtypes() {
1565
            return permittedSubclasses == null
1✔
1566
                    ? new TypeList.Empty()
1567
                    : new TypeList.Explicit(permittedSubclasses);
1568
        }
1569

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

1844
        /**
1845
         * Checks if an array of identifiers is a valid compound Java identifier.
1846
         *
1847
         * @param identifier an array of potentially invalid Java identifiers.
1848
         * @return {@code true} if all identifiers are valid and the array is not empty.
1849
         */
1850
        private static boolean isValidIdentifier(String[] identifier) {
1851
            if (identifier.length == 0) {
1✔
1852
                return false;
×
1853
            }
1854
            for (String part : identifier) {
1✔
1855
                if (!isValidIdentifier(part)) {
1✔
1856
                    return false;
1✔
1857
                }
1858
            }
1859
            return true;
1✔
1860
        }
1861

1862
        /**
1863
         * Checks if a Java identifier is valid.
1864
         *
1865
         * @param identifier The identifier to check for validity.
1866
         * @return {@code true} if the given identifier is valid.
1867
         */
1868
        private static boolean isValidIdentifier(String identifier) {
1869
            if (KEYWORDS.contains(identifier)
1✔
1870
                    || identifier.length() == 0
1✔
1871
                    || !(Character.isJavaIdentifierStart(identifier.charAt(0))
1✔
1872
                    || Character.isUnicodeIdentifierStart(identifier.charAt(0)))) {
×
1873
                return false;
1✔
1874
            } else if (identifier.equals(PackageDescription.PACKAGE_CLASS_NAME)) {
1✔
1875
                return true;
1✔
1876
            }
1877
            for (int index = 1; index < identifier.length(); index++) {
1✔
1878
                if (!(Character.isJavaIdentifierPart(identifier.charAt(index)) || Character.isUnicodeIdentifierPart(identifier.charAt(index)))) {
1✔
1879
                    return false;
1✔
1880
                }
1881
            }
1882
            return true;
1✔
1883
        }
1884

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

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

1937
    /**
1938
     * A frozen representation of an instrumented type of which the structure must not be modified.
1939
     */
1940
    class Frozen extends AbstractBase.OfSimpleType implements InstrumentedType.WithFlexibleName {
1941

1942
        /**
1943
         * The represented type description.
1944
         */
1945
        private final TypeDescription typeDescription;
1946

1947
        /**
1948
         * The type's loaded type initializer.
1949
         */
1950
        private final LoadedTypeInitializer loadedTypeInitializer;
1951

1952
        /**
1953
         * Creates a new frozen representation of an instrumented type.
1954
         *
1955
         * @param typeDescription       The represented type description.
1956
         * @param loadedTypeInitializer The type's loaded type initializer.
1957
         */
1958
        protected Frozen(TypeDescription typeDescription, LoadedTypeInitializer loadedTypeInitializer) {
1✔
1959
            this.typeDescription = typeDescription;
1✔
1960
            this.loadedTypeInitializer = loadedTypeInitializer;
1✔
1961
        }
1✔
1962

1963
        /**
1964
         * {@inheritDoc}
1965
         */
1966
        public AnnotationList getDeclaredAnnotations() {
1967
            return typeDescription.getDeclaredAnnotations();
1✔
1968
        }
1969

1970
        /**
1971
         * {@inheritDoc}
1972
         */
1973
        public int getModifiers() {
1974
            return typeDescription.getModifiers();
1✔
1975
        }
1976

1977
        /**
1978
         * {@inheritDoc}
1979
         */
1980
        public TypeList.Generic getTypeVariables() {
1981
            return typeDescription.getTypeVariables();
1✔
1982
        }
1983

1984
        /**
1985
         * {@inheritDoc}
1986
         */
1987
        public String getName() {
1988
            return typeDescription.getName();
1✔
1989
        }
1990

1991
        /**
1992
         * {@inheritDoc}
1993
         */
1994
        @MaybeNull
1995
        public Generic getSuperClass() {
1996
            return typeDescription.getSuperClass();
1✔
1997
        }
1998

1999
        /**
2000
         * {@inheritDoc}
2001
         */
2002
        public TypeList.Generic getInterfaces() {
2003
            return typeDescription.getInterfaces();
1✔
2004
        }
2005

2006
        /**
2007
         * {@inheritDoc}
2008
         */
2009
        public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
2010
            return typeDescription.getDeclaredFields();
1✔
2011
        }
2012

2013
        /**
2014
         * {@inheritDoc}
2015
         */
2016
        public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
2017
            return typeDescription.getDeclaredMethods();
1✔
2018
        }
2019

2020
        /**
2021
         * {@inheritDoc}
2022
         */
2023
        public boolean isAnonymousType() {
2024
            return typeDescription.isAnonymousType();
1✔
2025
        }
2026

2027
        /**
2028
         * {@inheritDoc}
2029
         */
2030
        public boolean isLocalType() {
2031
            return typeDescription.isLocalType();
1✔
2032
        }
2033

2034
        /**
2035
         * {@inheritDoc}
2036
         */
2037
        @MaybeNull
2038
        public PackageDescription getPackage() {
2039
            return typeDescription.getPackage();
1✔
2040
        }
2041

2042
        /**
2043
         * {@inheritDoc}
2044
         */
2045
        @MaybeNull
2046
        public ModuleDescription toModuleDescription() {
2047
            return typeDescription.toModuleDescription();
1✔
2048
        }
2049

2050
        /**
2051
         * {@inheritDoc}
2052
         */
2053
        @MaybeNull
2054
        public TypeDescription getEnclosingType() {
2055
            return typeDescription.getEnclosingType();
1✔
2056
        }
2057

2058
        /**
2059
         * {@inheritDoc}
2060
         */
2061
        @MaybeNull
2062
        public TypeDescription getDeclaringType() {
2063
            return typeDescription.getDeclaringType();
1✔
2064
        }
2065

2066
        /**
2067
         * {@inheritDoc}
2068
         */
2069
        public TypeList getDeclaredTypes() {
2070
            return typeDescription.getDeclaredTypes();
1✔
2071
        }
2072

2073
        /**
2074
         * {@inheritDoc}
2075
         */
2076
        @MaybeNull
2077
        public MethodDescription.InDefinedShape getEnclosingMethod() {
2078
            return typeDescription.getEnclosingMethod();
1✔
2079
        }
2080

2081
        /**
2082
         * {@inheritDoc}
2083
         */
2084
        @MaybeNull
2085
        public String getGenericSignature() {
2086
            // Embrace use of native generic signature by direct delegation.
2087
            return typeDescription.getGenericSignature();
1✔
2088
        }
2089

2090
        /**
2091
         * {@inheritDoc}
2092
         */
2093
        public int getActualModifiers(boolean superFlag) {
2094
            // Embrace use of native actual modifiers by direct delegation.
2095
            return typeDescription.getActualModifiers(superFlag);
1✔
2096
        }
2097

2098
        /**
2099
         * {@inheritDoc}
2100
         */
2101
        public TypeDescription getNestHost() {
2102
            return typeDescription.getNestHost();
1✔
2103
        }
2104

2105
        /**
2106
         * {@inheritDoc}
2107
         */
2108
        public TypeList getNestMembers() {
2109
            return typeDescription.getNestMembers();
1✔
2110
        }
2111

2112
        /**
2113
         * {@inheritDoc}
2114
         */
2115
        public RecordComponentList<RecordComponentDescription.InDefinedShape> getRecordComponents() {
2116
            return typeDescription.getRecordComponents();
1✔
2117
        }
2118

2119
        /**
2120
         * {@inheritDoc}
2121
         */
2122
        public boolean isRecord() {
2123
            return typeDescription.isRecord();
×
2124
        }
2125

2126
        @Override
2127
        public boolean isSealed() {
2128
            return typeDescription.isSealed();
1✔
2129
        }
2130

2131
        /**
2132
         * {@inheritDoc}
2133
         */
2134
        public TypeList getPermittedSubtypes() {
2135
            return typeDescription.getPermittedSubtypes();
1✔
2136
        }
2137

2138
        /**
2139
         * {@inheritDoc}
2140
         */
2141
        public WithFlexibleName withField(FieldDescription.Token token) {
2142
            throw new IllegalStateException("Cannot define field for frozen type: " + typeDescription);
1✔
2143
        }
2144

2145
        /**
2146
         * {@inheritDoc}
2147
         */
2148
        public WithFlexibleName withAuxiliaryField(FieldDescription.Token token, Object value) {
2149
            throw new IllegalStateException("Cannot define auxiliary field for frozen type: " + typeDescription);
1✔
2150
        }
2151

2152
        /**
2153
         * {@inheritDoc}
2154
         */
2155
        public WithFlexibleName withMethod(MethodDescription.Token token) {
2156
            throw new IllegalStateException("Cannot define method for frozen type: " + typeDescription);
1✔
2157
        }
2158

2159
        /**
2160
         * {@inheritDoc}
2161
         */
2162
        public WithFlexibleName withRecordComponent(RecordComponentDescription.Token token) {
2163
            throw new IllegalStateException("Cannot define record component for frozen type: " + typeDescription);
1✔
2164
        }
2165

2166
        /**
2167
         * {@inheritDoc}
2168
         */
2169
        public WithFlexibleName withModifiers(int modifiers) {
2170
            throw new IllegalStateException("Cannot change modifiers for frozen type: " + typeDescription);
×
2171
        }
2172

2173
        /**
2174
         * {@inheritDoc}
2175
         */
2176
        public WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes) {
2177
            throw new IllegalStateException("Cannot add interfaces for frozen type: " + typeDescription);
×
2178
        }
2179

2180
        /**
2181
         * {@inheritDoc}
2182
         */
2183
        public WithFlexibleName withTypeVariable(TypeVariableToken typeVariable) {
2184
            throw new IllegalStateException("Cannot define type variable for frozen type: " + typeDescription);
1✔
2185
        }
2186

2187
        /**
2188
         * {@inheritDoc}
2189
         */
2190
        public WithFlexibleName withAnnotations(List<? extends AnnotationDescription> annotationDescriptions) {
2191
            throw new IllegalStateException("Cannot add annotation to frozen type: " + typeDescription);
1✔
2192
        }
2193

2194
        /**
2195
         * {@inheritDoc}
2196
         */
2197
        public WithFlexibleName withNestHost(TypeDescription nestHost) {
2198
            throw new IllegalStateException("Cannot set nest host of frozen type: " + typeDescription);
1✔
2199
        }
2200

2201
        /**
2202
         * {@inheritDoc}
2203
         */
2204
        public WithFlexibleName withNestMembers(TypeList nestMembers) {
2205
            throw new IllegalStateException("Cannot add nest members to frozen type: " + typeDescription);
1✔
2206
        }
2207

2208
        /**
2209
         * {@inheritDoc}
2210
         */
2211
        public WithFlexibleName withEnclosingType(@MaybeNull TypeDescription enclosingType) {
2212
            throw new IllegalStateException("Cannot set enclosing type of frozen type: " + typeDescription);
1✔
2213
        }
2214

2215
        /**
2216
         * {@inheritDoc}
2217
         */
2218
        public WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod) {
2219
            throw new IllegalStateException("Cannot set enclosing method of frozen type: " + typeDescription);
1✔
2220
        }
2221

2222
        /**
2223
         * {@inheritDoc}
2224
         */
2225
        public WithFlexibleName withDeclaringType(@MaybeNull TypeDescription declaringType) {
2226
            throw new IllegalStateException("Cannot add declaring type to frozen type: " + typeDescription);
1✔
2227
        }
2228

2229
        /**
2230
         * {@inheritDoc}
2231
         */
2232
        public WithFlexibleName withDeclaredTypes(TypeList declaredTypes) {
2233
            throw new IllegalStateException("Cannot add declared types to frozen type: " + typeDescription);
1✔
2234
        }
2235

2236
        /**
2237
         * {@inheritDoc}
2238
         */
2239
        public WithFlexibleName withPermittedSubclasses(@MaybeNull TypeList permittedSubclasses) {
2240
            throw new IllegalStateException("Cannot add permitted subclasses to frozen type: " + typeDescription);
1✔
2241
        }
2242

2243
        /**
2244
         * {@inheritDoc}
2245
         */
2246
        public WithFlexibleName withLocalClass(boolean localClass) {
2247
            throw new IllegalStateException("Cannot define local class state for frozen type: " + typeDescription);
1✔
2248
        }
2249

2250
        /**
2251
         * {@inheritDoc}
2252
         */
2253
        public WithFlexibleName withAnonymousClass(boolean anonymousClass) {
2254
            throw new IllegalStateException("Cannot define anonymous class state for frozen type: " + typeDescription);
1✔
2255
        }
2256

2257
        /**
2258
         * {@inheritDoc}
2259
         */
2260
        public WithFlexibleName withRecord(boolean record) {
2261
            throw new IllegalStateException("Cannot define record state for frozen type: " + typeDescription);
1✔
2262
        }
2263

2264
        /**
2265
         * {@inheritDoc}
2266
         */
2267
        public WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitializer) {
2268
            return new Frozen(typeDescription, new LoadedTypeInitializer.Compound(this.loadedTypeInitializer, loadedTypeInitializer));
×
2269
        }
2270

2271
        /**
2272
         * {@inheritDoc}
2273
         */
2274
        public WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender) {
2275
            throw new IllegalStateException("Cannot add initializer to frozen type: " + typeDescription);
1✔
2276
        }
2277

2278
        /**
2279
         * {@inheritDoc}
2280
         */
2281
        public WithFlexibleName withName(String name) {
2282
            throw new IllegalStateException("Cannot change name of frozen type: " + typeDescription);
1✔
2283
        }
2284

2285
        /**
2286
         * {@inheritDoc}
2287
         */
2288
        public WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matcher, Transformer<TypeVariableToken> transformer) {
2289
            throw new IllegalStateException("Cannot add type variables of frozen type: " + typeDescription);
1✔
2290
        }
2291

2292
        /**
2293
         * {@inheritDoc}
2294
         */
2295
        public LoadedTypeInitializer getLoadedTypeInitializer() {
2296
            return loadedTypeInitializer;
1✔
2297
        }
2298

2299
        /**
2300
         * {@inheritDoc}
2301
         */
2302
        public TypeInitializer getTypeInitializer() {
2303
            return TypeInitializer.None.INSTANCE;
1✔
2304
        }
2305

2306
        @MaybeNull
2307
        @Override
2308
        public ClassFileVersion getClassFileVersion() {
2309
            return typeDescription.getClassFileVersion();
1✔
2310
        }
2311

2312
        /**
2313
         * {@inheritDoc}
2314
         */
2315
        public TypeDescription validated() {
2316
            return typeDescription;
1✔
2317
        }
2318
    }
2319
}
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