/*
* Copyright 2014 - 2019 Rafael Winterhalter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.bytebuddy.dynamic.scaffold;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationList;
import net.bytebuddy.description.annotation.AnnotationValue;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.method.ParameterDescription;
import net.bytebuddy.description.modifier.ModifierContributor;
import net.bytebuddy.description.type.PackageDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import net.bytebuddy.description.type.TypeVariableToken;
import net.bytebuddy.dynamic.TargetType;
import net.bytebuddy.dynamic.Transformer;
import net.bytebuddy.implementation.LoadedTypeInitializer;
import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.CompoundList;
import java.lang.annotation.ElementType;
import java.util.*;
import static net.bytebuddy.matcher.ElementMatchers.is;
import static net.bytebuddy.matcher.ElementMatchers.not;
Implementations of this interface represent an instrumented type that is subject to change. Implementations
should however be immutable and return new instance when its builder methods are invoked.
/**
* Implementations of this interface represent an instrumented type that is subject to change. Implementations
* should however be immutable and return new instance when its builder methods are invoked.
*/
public interface InstrumentedType extends TypeDescription {
Creates a new instrumented type that includes a new field.
Params: - token – A token that represents the field's shape. This token must represent types in their detached state.
Returns: A new instrumented type that is equal to this instrumented type but with the additional field.
/**
* Creates a new instrumented type that includes a new field.
*
* @param token A token that represents the field's shape. This token must represent types in their detached state.
* @return A new instrumented type that is equal to this instrumented type but with the additional field.
*/
InstrumentedType withField(FieldDescription.Token token);
Creates a new instrumented type that includes a new method or constructor.
Params: - token – A token that represents the method's shape. This token must represent types in their detached state.
Returns: A new instrumented type that is equal to this instrumented type but with the additional method.
/**
* Creates a new instrumented type that includes a new method or constructor.
*
* @param token A token that represents the method's shape. This token must represent types in their detached state.
* @return A new instrumented type that is equal to this instrumented type but with the additional method.
*/
InstrumentedType withMethod(MethodDescription.Token token);
Creates a new instrumented type with changed modifiers.
Params: - modifiers – The instrumented type's modifiers.
Returns: A new instrumented type that is equal to this instrumented type but with the given modifiers.
/**
* Creates a new instrumented type with changed modifiers.
*
* @param modifiers The instrumented type's modifiers.
* @return A new instrumented type that is equal to this instrumented type but with the given modifiers.
*/
InstrumentedType withModifiers(int modifiers);
Creates a new instrumented type with the given interfaces implemented.
Params: - interfaceTypes – The interface types to implement.
Returns: A new instrumented type that is equal to this instrumented type but with the given interfaces implemented.
/**
* Creates a new instrumented type with the given interfaces implemented.
*
* @param interfaceTypes The interface types to implement.
* @return A new instrumented type that is equal to this instrumented type but with the given interfaces implemented.
*/
InstrumentedType withInterfaces(TypeList.Generic interfaceTypes);
Creates a new instrumented type with the given type variable defined.
Params: - typeVariable – The type variable to declare.
Returns: A new instrumented type that is equal to this instrumented type but with the given type variable declared.
/**
* Creates a new instrumented type with the given type variable defined.
*
* @param typeVariable The type variable to declare.
* @return A new instrumented type that is equal to this instrumented type but with the given type variable declared.
*/
InstrumentedType withTypeVariable(TypeVariableToken typeVariable);
Creates a new instrumented type with the given annotations.
Params: - annotationDescriptions – The annotations to add to the instrumented type.
Returns: A new instrumented type that is equal to this instrumented type but annotated with the given annotations
/**
* Creates a new instrumented type with the given annotations.
*
* @param annotationDescriptions The annotations to add to the instrumented type.
* @return A new instrumented type that is equal to this instrumented type but annotated with the given annotations
*/
InstrumentedType withAnnotations(List<? extends AnnotationDescription> annotationDescriptions);
Creates a new instrumented type with the supplied nest host. An instrumented type can be its own nest host.
Setting a nest host removes all nest members from the instrumented type.
Params: - nestHost – The nest host of the created instrumented type.
Returns: A new instrumented type with the supplied type as its nest host.
/**
* Creates a new instrumented type with the supplied nest host. An instrumented type can be its own nest host.
* Setting a nest host removes all nest members from the instrumented type.
*
* @param nestHost The nest host of the created instrumented type.
* @return A new instrumented type with the supplied type as its nest host.
*/
InstrumentedType withNestHost(TypeDescription nestHost);
Creates a new instrumented types with the supplied nest members added to this instrumented type. The instrumented
type is defined as a nest host if this method is invoked. Any previous nest members are prepended to the supplied types.
Params: - nestMembers – The nest members to add to the created instrumented type.
Returns: A new instrumented type that applies the supplied nest members.
/**
* Creates a new instrumented types with the supplied nest members added to this instrumented type. The instrumented
* type is defined as a nest host if this method is invoked. Any previous nest members are prepended to the supplied types.
*
* @param nestMembers The nest members to add to the created instrumented type.
* @return A new instrumented type that applies the supplied nest members.
*/
InstrumentedType withNestMembers(TypeList nestMembers);
Creates a new instrumented type with the supplied enclosing type.
Params: - enclosingType – The type to define as the created instrumented type's enclosing type.
Returns: A new instrumented type with the supplied type as its enclosing type.
/**
* Creates a new instrumented type with the supplied enclosing type.
*
* @param enclosingType The type to define as the created instrumented type's enclosing type.
* @return A new instrumented type with the supplied type as its enclosing type.
*/
InstrumentedType withEnclosingType(TypeDescription enclosingType);
Creates a new instrumented type with the supplied enclosing method.
Params: - enclosingMethod – The method to define as the created instrumented type's enclosing method.
Returns: A new instrumented type with the supplied method as its enclosing method.
/**
* Creates a new instrumented type with the supplied enclosing method.
*
* @param enclosingMethod The method to define as the created instrumented type's enclosing method.
* @return A new instrumented type with the supplied method as its enclosing method.
*/
InstrumentedType withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod);
Creates a new instrumented type that is declared by the supplied type..
Params: - declaringType – The type that declares the instrumented type.
Returns: A new instrumented type that is declared by the instrumented type.
/**
* Creates a new instrumented type that is declared by the supplied type..
*
* @param declaringType The type that declares the instrumented type.
* @return A new instrumented type that is declared by the instrumented type.
*/
InstrumentedType withDeclaringType(TypeDescription declaringType);
Creates a new instrumented type that indicates that it declared the supplied types.
Params: - declaredTypes – The types to add to the created instrumented type as declared types.
Returns: A new instrumented type that indicates that it has declared the supplied types.
/**
* Creates a new instrumented type that indicates that it declared the supplied types.
*
* @param declaredTypes The types to add to the created instrumented type as declared types.
* @return A new instrumented type that indicates that it has declared the supplied types.
*/
InstrumentedType withDeclaredTypes(TypeList declaredTypes);
Creates a new instrumented type that indicates that is defined as a local class. Setting this property
resets the anonymous class property.
Params: - localClass –
true
if the instrumented type is supposed to be treated as a local class.
Returns: A new instrumented type that is treated as a local class.
/**
* Creates a new instrumented type that indicates that is defined as a local class. Setting this property
* resets the anonymous class property.
*
* @param localClass {@code true} if the instrumented type is supposed to be treated as a local class.
* @return A new instrumented type that is treated as a local class.
*/
InstrumentedType withLocalClass(boolean localClass);
Creates a new instrumented type that indicates that is defined as an anonymous class. Setting this property
resets the local class property.
Params: - anonymousClass –
true
if the instrumented type is supposed to be treated as an anonymous class.
Returns: A new instrumented type that is treated as an anonymous class.
/**
* Creates a new instrumented type that indicates that is defined as an anonymous class. Setting this property
* resets the local class property.
*
* @param anonymousClass {@code true} if the instrumented type is supposed to be treated as an anonymous class.
* @return A new instrumented type that is treated as an anonymous class.
*/
InstrumentedType withAnonymousClass(boolean anonymousClass);
Creates a new instrumented type that includes the given LoadedTypeInitializer
. Params: - loadedTypeInitializer – The type initializer to include.
Returns: A new instrumented type that is equal to this instrumented type but with the additional type initializer.
/**
* Creates a new instrumented type that includes the given {@link net.bytebuddy.implementation.LoadedTypeInitializer}.
*
* @param loadedTypeInitializer The type initializer to include.
* @return A new instrumented type that is equal to this instrumented type but with the additional type initializer.
*/
InstrumentedType withInitializer(LoadedTypeInitializer loadedTypeInitializer);
Creates a new instrumented type that executes the given initializer in the instrumented type's
type initializer.
Params: - byteCodeAppender – The byte code to add to the type initializer.
Returns: A new instrumented type that is equal to this instrumented type but with the given stack manipulation
attached to its type initializer.
/**
* Creates a new instrumented type that executes the given initializer in the instrumented type's
* type initializer.
*
* @param byteCodeAppender The byte code to add to the type initializer.
* @return A new instrumented type that is equal to this instrumented type but with the given stack manipulation
* attached to its type initializer.
*/
InstrumentedType withInitializer(ByteCodeAppender byteCodeAppender);
Returns the LoadedTypeInitializer
s that were registered for this instrumented type. Returns: The registered loaded type initializers for this instrumented type.
/**
* Returns the {@link net.bytebuddy.implementation.LoadedTypeInitializer}s that were registered
* for this instrumented type.
*
* @return The registered loaded type initializers for this instrumented type.
*/
LoadedTypeInitializer getLoadedTypeInitializer();
Returns this instrumented type's type initializer.
Returns: This instrumented type's type initializer.
/**
* Returns this instrumented type's type initializer.
*
* @return This instrumented type's type initializer.
*/
TypeInitializer getTypeInitializer();
Validates the instrumented type to define a legal Java type.
Returns: This instrumented type as a non-modifiable type description.
/**
* Validates the instrumented type to define a legal Java type.
*
* @return This instrumented type as a non-modifiable type description.
*/
TypeDescription validated();
Implementations represent an InstrumentedType
with a flexible name. /**
* Implementations represent an {@link InstrumentedType} with a flexible name.
*/
interface WithFlexibleName extends InstrumentedType {
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withField(FieldDescription.Token token);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withMethod(MethodDescription.Token token);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withModifiers(int modifiers);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withNestHost(TypeDescription nestHost);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withNestMembers(TypeList nestMembers);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withEnclosingType(TypeDescription enclosingType);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withDeclaringType(TypeDescription declaringType);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withDeclaredTypes(TypeList declaredTypes);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withLocalClass(boolean localClass);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withAnonymousClass(boolean anonymousClass);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withTypeVariable(TypeVariableToken typeVariable);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withAnnotations(List<? extends AnnotationDescription> annotationDescriptions);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitializer);
{@inheritDoc}
/**
* {@inheritDoc}
*/
WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender);
Creates a new instrumented type with a changed name.
Params: - name – The name of the instrumented type.
Returns: A new instrumented type that has the given name.
/**
* Creates a new instrumented type with a changed name.
*
* @param name The name of the instrumented type.
* @return A new instrumented type that has the given name.
*/
WithFlexibleName withName(String name);
Applies a transformation onto all existing type variables of this instrumented type. A transformation is potentially unsafe
and it is the responsibility of the supplier to return a valid type variable token from the transformer.
Params: - matcher – The matcher to decide what type variables to transform.
- transformer – The transformer to apply on all matched type variables.
Returns: A new instrumented type with all matched type variables transformed.
/**
* Applies a transformation onto all existing type variables of this instrumented type. A transformation is potentially unsafe
* and it is the responsibility of the supplier to return a valid type variable token from the transformer.
*
* @param matcher The matcher to decide what type variables to transform.
* @param transformer The transformer to apply on all matched type variables.
* @return A new instrumented type with all matched type variables transformed.
*/
WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matcher, Transformer<TypeVariableToken> transformer);
}
Implementations are able to prepare an InstrumentedType
. /**
* Implementations are able to prepare an {@link InstrumentedType}.
*/
interface Prepareable {
Prepares a given instrumented type.
Params: - instrumentedType – The instrumented type in its current form.
Returns: The prepared instrumented type.
/**
* Prepares a given instrumented type.
*
* @param instrumentedType The instrumented type in its current form.
* @return The prepared instrumented type.
*/
InstrumentedType prepare(InstrumentedType instrumentedType);
}
A factory for creating an InstrumentedType
. /**
* A factory for creating an {@link InstrumentedType}.
*/
interface Factory {
Creates an instrumented type that represents the provided type.
Params: - typeDescription – The type to represent.
Returns: An appropriate instrumented type.
/**
* Creates an instrumented type that represents the provided type.
*
* @param typeDescription The type to represent.
* @return An appropriate instrumented type.
*/
InstrumentedType.WithFlexibleName represent(TypeDescription typeDescription);
Creates a new instrumented type as a subclass.
Params: - name – The type's name.
- modifiers – The type's modifiers.
- superClass – The type's super class.
Returns: A new instrumented type representing a subclass of the given parameters.
/**
* Creates a new instrumented type as a subclass.
*
* @param name The type's name.
* @param modifiers The type's modifiers.
* @param superClass The type's super class.
* @return A new instrumented type representing a subclass of the given parameters.
*/
InstrumentedType.WithFlexibleName subclass(String name, int modifiers, TypeDescription.Generic superClass);
Default implementations of instrumented type factories.
/**
* Default implementations of instrumented type factories.
*/
enum Default implements Factory {
A factory for an instrumented type that allows to modify represented types.
/**
* A factory for an instrumented type that allows to modify represented types.
*/
MODIFIABLE {
{@inheritDoc} /** {@inheritDoc} */
public InstrumentedType.WithFlexibleName represent(TypeDescription typeDescription) {
return new InstrumentedType.Default(typeDescription.getName(),
typeDescription.getModifiers(),
typeDescription.getSuperClass(),
typeDescription.getTypeVariables().asTokenList(is(typeDescription)),
typeDescription.getInterfaces().accept(Generic.Visitor.Substitutor.ForDetachment.of(typeDescription)),
typeDescription.getDeclaredFields().asTokenList(is(typeDescription)),
typeDescription.getDeclaredMethods().asTokenList(is(typeDescription)),
typeDescription.getDeclaredAnnotations(),
TypeInitializer.None.INSTANCE,
LoadedTypeInitializer.NoOp.INSTANCE,
typeDescription.getDeclaringType(),
typeDescription.getEnclosingMethod(),
typeDescription.getEnclosingType(),
typeDescription.getDeclaredTypes(),
typeDescription.isAnonymousType(),
typeDescription.isLocalType(),
typeDescription.isNestHost()
? TargetType.DESCRIPTION
: typeDescription.getNestHost(),
typeDescription.isNestHost()
? typeDescription.getNestMembers().filter(not(is(typeDescription)))
: Collections.<TypeDescription>emptyList());
}
},
A factory for an instrumented type that does not allow to modify represented types.
/**
* A factory for an instrumented type that does not allow to modify represented types.
*/
FROZEN {
{@inheritDoc} /** {@inheritDoc} */
public InstrumentedType.WithFlexibleName represent(TypeDescription typeDescription) {
return new Frozen(typeDescription, LoadedTypeInitializer.NoOp.INSTANCE);
}
};
{@inheritDoc}
/**
* {@inheritDoc}
*/
public InstrumentedType.WithFlexibleName subclass(String name, int modifiers, TypeDescription.Generic superClass) {
return new InstrumentedType.Default(name,
modifiers,
superClass,
Collections.<TypeVariableToken>emptyList(),
Collections.<Generic>emptyList(),
Collections.<FieldDescription.Token>emptyList(),
Collections.<MethodDescription.Token>emptyList(),
Collections.<AnnotationDescription>emptyList(),
TypeInitializer.None.INSTANCE,
LoadedTypeInitializer.NoOp.INSTANCE,
TypeDescription.UNDEFINED,
MethodDescription.UNDEFINED,
TypeDescription.UNDEFINED,
Collections.<TypeDescription>emptyList(),
false,
false,
TargetType.DESCRIPTION,
Collections.<TypeDescription>emptyList());
}
}
}
A default implementation of an instrumented type.
/**
* A default implementation of an instrumented type.
*/
class Default extends AbstractBase.OfSimpleType implements InstrumentedType.WithFlexibleName {
A set containing all keywords of the Java programming language.
/**
* A set containing all keywords of the Java programming language.
*/
private static final Set<String> KEYWORDS = new HashSet<String>(Arrays.asList(
"abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", "boolean",
"do", "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte", "else", "import",
"public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", "short",
"try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile",
"const", "float", "native", "super", "while"
));
The binary name of the instrumented type.
/**
* The binary name of the instrumented type.
*/
private final String name;
The modifiers of the instrumented type.
/**
* The modifiers of the instrumented type.
*/
private final int modifiers;
The generic super type of the instrumented type.
/**
* The generic super type of the instrumented type.
*/
private final Generic superClass;
The instrumented type's type variables in their tokenized form.
/**
* The instrumented type's type variables in their tokenized form.
*/
private final List<? extends TypeVariableToken> typeVariables;
A list of interfaces of the instrumented type.
/**
* A list of interfaces of the instrumented type.
*/
private final List<? extends Generic> interfaceTypes;
A list of field tokens describing the fields of the instrumented type.
/**
* A list of field tokens describing the fields of the instrumented type.
*/
private final List<? extends FieldDescription.Token> fieldTokens;
A list of method tokens describing the methods of the instrumented type.
/**
* A list of method tokens describing the methods of the instrumented type.
*/
private final List<? extends MethodDescription.Token> methodTokens;
A list of annotations of the annotated type.
/**
* A list of annotations of the annotated type.
*/
private final List<? extends AnnotationDescription> annotationDescriptions;
The type initializer of the instrumented type.
/**
* The type initializer of the instrumented type.
*/
private final TypeInitializer typeInitializer;
The loaded type initializer of the instrumented type.
/**
* The loaded type initializer of the instrumented type.
*/
private final LoadedTypeInitializer loadedTypeInitializer;
The declaring type of the instrumented type or null
if no such type exists. /**
* The declaring type of the instrumented type or {@code null} if no such type exists.
*/
private final TypeDescription declaringType;
The enclosing method of the instrumented type or null
if no such type exists. /**
* The enclosing method of the instrumented type or {@code null} if no such type exists.
*/
private final MethodDescription.InDefinedShape enclosingMethod;
The enclosing type of the instrumented type or null
if no such type exists. /**
* The enclosing type of the instrumented type or {@code null} if no such type exists.
*/
private final TypeDescription enclosingType;
A list of types that are declared by this type.
/**
* A list of types that are declared by this type.
*/
private final List<? extends TypeDescription> declaredTypes;
true
if this type is a anonymous class. /**
* {@code true} if this type is a anonymous class.
*/
private final boolean anonymousClass;
true
if this type is a local class. /**
* {@code true} if this type is a local class.
*/
private final boolean localClass;
The nest host of this instrumented type or a description of TargetType
if this type is its own nest host. /**
* The nest host of this instrumented type or a description of {@link TargetType} if this type is its own nest host.
*/
private final TypeDescription nestHost;
A list of all members of this types nest group excluding this type.
/**
* A list of all members of this types nest group excluding this type.
*/
private final List<? extends TypeDescription> nestMembers;
Creates a new instrumented type.
Params: - name – The binary name of the instrumented type.
- modifiers – The modifiers of the instrumented type.
- typeVariables – The instrumented type's type variables in their tokenized form.
- superClass – The generic super type of the instrumented type.
- interfaceTypes – A list of interfaces of the instrumented type.
- fieldTokens – A list of field tokens describing the fields of the instrumented type.
- methodTokens – A list of method tokens describing the methods of the instrumented type.
- annotationDescriptions – A list of annotations of the annotated type.
- typeInitializer – The type initializer of the instrumented type.
- loadedTypeInitializer – The loaded type initializer of the instrumented type.
- declaringType – The declaring type of the instrumented type or
null
if no such type exists. - enclosingMethod – The enclosing method of the instrumented type or
null
if no such type exists. - enclosingType – The enclosing type of the instrumented type or
null
if no such type exists. - declaredTypes – A list of types that are declared by this type.
- anonymousClass –
true
if this type is a anonymous class. - localClass –
true
if this type is a local class. - nestHost – The nest host of this instrumented type or a description of
TargetType
if this type is its own nest host. - nestMembers – A list of all members of this types nest group excluding this type.
/**
* Creates a new instrumented type.
*
* @param name The binary name of the instrumented type.
* @param modifiers The modifiers of the instrumented type.
* @param typeVariables The instrumented type's type variables in their tokenized form.
* @param superClass The generic super type of the instrumented type.
* @param interfaceTypes A list of interfaces of the instrumented type.
* @param fieldTokens A list of field tokens describing the fields of the instrumented type.
* @param methodTokens A list of method tokens describing the methods of the instrumented type.
* @param annotationDescriptions A list of annotations of the annotated type.
* @param typeInitializer The type initializer of the instrumented type.
* @param loadedTypeInitializer The loaded type initializer of the instrumented type.
* @param declaringType The declaring type of the instrumented type or {@code null} if no such type exists.
* @param enclosingMethod The enclosing method of the instrumented type or {@code null} if no such type exists.
* @param enclosingType The enclosing type of the instrumented type or {@code null} if no such type exists.
* @param declaredTypes A list of types that are declared by this type.
* @param anonymousClass {@code true} if this type is a anonymous class.
* @param localClass {@code true} if this type is a local class.
* @param nestHost The nest host of this instrumented type or a description of {@link TargetType} if this type is its own nest host.
* @param nestMembers A list of all members of this types nest group excluding this type.
*/
protected Default(String name,
int modifiers,
Generic superClass,
List<? extends TypeVariableToken> typeVariables,
List<? extends Generic> interfaceTypes,
List<? extends FieldDescription.Token> fieldTokens,
List<? extends MethodDescription.Token> methodTokens,
List<? extends AnnotationDescription> annotationDescriptions,
TypeInitializer typeInitializer,
LoadedTypeInitializer loadedTypeInitializer,
TypeDescription declaringType,
MethodDescription.InDefinedShape enclosingMethod,
TypeDescription enclosingType,
List<? extends TypeDescription> declaredTypes,
boolean anonymousClass,
boolean localClass,
TypeDescription nestHost,
List<? extends TypeDescription> nestMembers) {
this.name = name;
this.modifiers = modifiers;
this.typeVariables = typeVariables;
this.superClass = superClass;
this.interfaceTypes = interfaceTypes;
this.fieldTokens = fieldTokens;
this.methodTokens = methodTokens;
this.annotationDescriptions = annotationDescriptions;
this.typeInitializer = typeInitializer;
this.loadedTypeInitializer = loadedTypeInitializer;
this.declaringType = declaringType;
this.enclosingMethod = enclosingMethod;
this.enclosingType = enclosingType;
this.declaredTypes = declaredTypes;
this.anonymousClass = anonymousClass;
this.localClass = localClass;
this.nestHost = nestHost;
this.nestMembers = nestMembers;
}
Creates a new instrumented type.
Params: - name – The type's name.
- superClass – The type's super class.
- modifierContributor – The type's modifiers.
Returns: An appropriate instrumented type.
/**
* Creates a new instrumented type.
*
* @param name The type's name.
* @param superClass The type's super class.
* @param modifierContributor The type's modifiers.
* @return An appropriate instrumented type.
*/
public static InstrumentedType of(String name, TypeDescription.Generic superClass, ModifierContributor.ForType... modifierContributor) {
return of(name, superClass, ModifierContributor.Resolver.of(modifierContributor).resolve());
}
Creates a new instrumented type.
Params: - name – The type's name.
- superClass – The type's super class.
- modifiers – The type's modifiers.
Returns: An appropriate instrumented type.
/**
* Creates a new instrumented type.
*
* @param name The type's name.
* @param superClass The type's super class.
* @param modifiers The type's modifiers.
* @return An appropriate instrumented type.
*/
public static InstrumentedType of(String name, TypeDescription.Generic superClass, int modifiers) {
return Factory.Default.MODIFIABLE.subclass(name, modifiers, superClass);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withModifiers(int modifiers) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withField(FieldDescription.Token token) {
return new Default(this.name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
CompoundList.of(fieldTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withMethod(MethodDescription.Token token) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
CompoundList.of(methodTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes) {
return new Default(name,
modifiers,
superClass,
typeVariables,
CompoundList.of(this.interfaceTypes, interfaceTypes.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withAnnotations(List<? extends AnnotationDescription> annotationDescriptions) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
CompoundList.of(this.annotationDescriptions, annotationDescriptions),
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withNestHost(TypeDescription nestHost) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost.equals(this)
? TargetType.DESCRIPTION
: nestHost,
Collections.<TypeDescription>emptyList());
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withNestMembers(TypeList nestMembers) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
TargetType.DESCRIPTION,
CompoundList.of(this.nestMembers, nestMembers));
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withEnclosingType(TypeDescription enclosingType) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
MethodDescription.UNDEFINED,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingMethod.getDeclaringType(),
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withDeclaringType(TypeDescription declaringType) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withDeclaredTypes(TypeList declaredTypes) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
CompoundList.of(this.declaredTypes, declaredTypes),
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withTypeVariable(TypeVariableToken typeVariable) {
return new Default(name,
modifiers,
superClass,
CompoundList.of(typeVariables, typeVariable.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withName(String name) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matcher, Transformer<TypeVariableToken> transformer) {
List<TypeVariableToken> typeVariables = new ArrayList<TypeVariableToken>(this.typeVariables.size());
int index = 0;
for (TypeVariableToken typeVariableToken : this.typeVariables) {
typeVariables.add(matcher.matches(getTypeVariables().get(index++))
? transformer.transform(this, typeVariableToken)
: typeVariableToken);
}
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withLocalClass(boolean localClass) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
false,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withAnonymousClass(boolean anonymousClass) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
false,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitializer) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer,
new LoadedTypeInitializer.Compound(this.loadedTypeInitializer, loadedTypeInitializer),
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender) {
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
fieldTokens,
methodTokens,
annotationDescriptions,
typeInitializer.expandWith(byteCodeAppender),
loadedTypeInitializer,
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
anonymousClass,
localClass,
nestHost,
nestMembers);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public LoadedTypeInitializer getLoadedTypeInitializer() {
return loadedTypeInitializer;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeInitializer getTypeInitializer() {
return typeInitializer;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public MethodDescription.InDefinedShape getEnclosingMethod() {
return enclosingMethod;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription getEnclosingType() {
return enclosingType;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList getDeclaredTypes() {
return new TypeList.Explicit(declaredTypes);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean isAnonymousType() {
return anonymousClass;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean isLocalType() {
return localClass;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public PackageDescription getPackage() {
int packageIndex = name.lastIndexOf('.');
return new PackageDescription.Simple(packageIndex == -1
? EMPTY_NAME
: name.substring(0, packageIndex));
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public AnnotationList getDeclaredAnnotations() {
return new AnnotationList.Explicit(annotationDescriptions);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription getDeclaringType() {
return declaringType;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public Generic getSuperClass() {
return superClass == null
? Generic.UNDEFINED
: new Generic.LazyProjection.WithResolvedErasure(superClass, Generic.Visitor.Substitutor.ForAttachment.of(this));
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList.Generic getInterfaces() {
return new TypeList.Generic.ForDetachedTypes.WithResolvedErasure(interfaceTypes, TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this));
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
return new FieldList.ForTokens(this, fieldTokens);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
return new MethodList.ForTokens(this, methodTokens);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList.Generic getTypeVariables() {
return TypeList.Generic.ForDetachedTypes.attachVariables(this, typeVariables);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public int getModifiers() {
return modifiers;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public String getName() {
return name;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription getNestHost() {
return nestHost.represents(TargetType.class)
? this
: nestHost;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList getNestMembers() {
return nestHost.represents(TargetType.class)
? new TypeList.Explicit(CompoundList.of(this, nestMembers))
: nestHost.getNestMembers();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription validated() {
if (!isValidIdentifier(getName().split("\\."))) {
throw new IllegalStateException("Illegal type name: " + getName() + " for " + this);
} else if ((getModifiers() & ~ModifierContributor.ForType.MASK) != EMPTY_MASK) {
throw new IllegalStateException("Illegal modifiers " + getModifiers() + " for " + this);
} else if (isPackageType() && getModifiers() != PackageDescription.PACKAGE_MODIFIERS) {
throw new IllegalStateException("Illegal modifiers " + getModifiers() + " for package " + this);
}
TypeDescription.Generic superClass = getSuperClass();
if (superClass != null) {
if (!superClass.accept(Generic.Visitor.Validator.SUPER_CLASS)) {
throw new IllegalStateException("Illegal super class " + superClass + " for " + this);
} else if (!superClass.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on super class " + superClass + " for " + this);
} else if (!superClass.asErasure().isVisibleTo(this)) {
throw new IllegalStateException("Invisible super type " + superClass + " for " + this);
}
}
Set<TypeDescription> interfaceErasures = new HashSet<TypeDescription>();
for (TypeDescription.Generic interfaceType : getInterfaces()) {
if (!interfaceType.accept(Generic.Visitor.Validator.INTERFACE)) {
throw new IllegalStateException("Illegal interface " + interfaceType + " for " + this);
} else if (!interfaceType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on interface " + interfaceType + " for " + this);
} else if (!interfaceErasures.add(interfaceType.asErasure())) {
throw new IllegalStateException("Already implemented interface " + interfaceType + " for " + this);
} else if (!interfaceType.asErasure().isVisibleTo(this)) {
throw new IllegalStateException("Invisible interface type " + interfaceType + " for " + this);
}
}
TypeList.Generic typeVariables = getTypeVariables();
if (!typeVariables.isEmpty() && isAssignableTo(Throwable.class)) {
throw new IllegalStateException("Cannot define throwable " + this + " to be generic");
}
Set<String> typeVariableNames = new HashSet<String>();
for (TypeDescription.Generic typeVariable : typeVariables) {
String variableSymbol = typeVariable.getSymbol();
if (!typeVariableNames.add(variableSymbol)) {
throw new IllegalStateException("Duplicate type variable symbol '" + typeVariable + "' for " + this);
} else if (!isValidIdentifier(variableSymbol)) {
throw new IllegalStateException("Illegal type variable name '" + typeVariable + "' for " + this);
} else if (!Generic.Visitor.Validator.ForTypeAnnotations.ofFormalTypeVariable(typeVariable)) {
throw new IllegalStateException("Illegal type annotation on '" + typeVariable + "' for " + this);
}
boolean interfaceBound = false;
Set<TypeDescription.Generic> bounds = new HashSet<Generic>();
for (TypeDescription.Generic bound : typeVariable.getUpperBounds()) {
if (!bound.accept(Generic.Visitor.Validator.TYPE_VARIABLE)) {
throw new IllegalStateException("Illegal type variable bound " + bound + " of " + typeVariable + " for " + this);
} else if (!bound.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on type variable " + bound + " for " + this);
} else if (!bounds.add(bound)) {
throw new IllegalStateException("Duplicate bound " + bound + " of " + typeVariable + " for " + this);
} else if (interfaceBound && (bound.getSort().isTypeVariable() || !bound.isInterface())) {
throw new IllegalStateException("Illegal interface bound " + bound + " of " + typeVariable + " for " + this);
}
interfaceBound = true;
}
if (!interfaceBound) {
throw new IllegalStateException("Type variable " + typeVariable + " for " + this + " does not define at least one bound");
}
}
TypeDescription enclosingType = getEnclosingType();
if (enclosingType != null && (enclosingType.isArray() || enclosingType.isPrimitive())) {
throw new IllegalStateException("Cannot define array type or primitive type " + enclosingType + " + as enclosing type for " + this);
}
MethodDescription.InDefinedShape enclosingMethod = getEnclosingMethod();
if (enclosingMethod != null && enclosingMethod.isTypeInitializer()) {
throw new IllegalStateException("Cannot enclose type declaration in class initializer " + enclosingMethod);
}
TypeDescription declaringType = getDeclaringType();
if (declaringType != null) {
if (declaringType.isPrimitive() || declaringType.isArray()) {
throw new IllegalStateException("Cannot define array type or primitive type " + declaringType + " as declaring type for " + this);
}
} else if (enclosingType == null && enclosingMethod == null && (isLocalType() || isAnonymousType())) {
throw new IllegalStateException("Cannot define an anonymous or local class without a declaring type for " + this);
}
Set<TypeDescription> declaredTypes = new HashSet<TypeDescription>();
for (TypeDescription declaredType : getDeclaredTypes()) {
if (declaredType.isArray() || declaredType.isPrimitive()) {
throw new IllegalStateException("Cannot define array type or primitive type " + declaredType + " + as declared type for " + this);
} else if (!declaredTypes.add(declaredType)) {
throw new IllegalStateException("Duplicate definition of declared type " + declaredType);
}
}
TypeDescription nestHost = getNestHost();
if (nestHost.equals(this)) {
Set<TypeDescription> nestMembers = new HashSet<TypeDescription>();
for (TypeDescription nestMember : getNestMembers()) {
if (nestMember.isArray() || nestMember.isPrimitive()) {
throw new IllegalStateException("Cannot define array type or primitive type " + nestMember + " + as nest member of " + this);
} else if (!nestMember.isSamePackage(this)) {
throw new IllegalStateException("Cannot define nest member " + nestMember + " + within different package then " + this);
} else if (!nestMembers.add(nestMember)) {
throw new IllegalStateException("Duplicate definition of nest member " + nestMember);
}
}
} else if (nestHost.isArray() || nestHost.isPrimitive()) {
throw new IllegalStateException("Cannot define array type or primitive type " + nestHost + " + as nest host for " + this);
} else if (!nestHost.isSamePackage(this)) {
throw new IllegalStateException("Cannot define nest host " + nestHost + " + within different package then " + this);
}
Set<TypeDescription> typeAnnotationTypes = new HashSet<TypeDescription>();
for (AnnotationDescription annotationDescription : getDeclaredAnnotations()) {
if (!annotationDescription.getElementTypes().contains(ElementType.TYPE)
&& !(isAnnotation() && annotationDescription.getElementTypes().contains(ElementType.ANNOTATION_TYPE))
&& !(isPackageType() && annotationDescription.getElementTypes().contains(ElementType.PACKAGE))) {
throw new IllegalStateException("Cannot add " + annotationDescription + " on " + this);
} else if (!typeAnnotationTypes.add(annotationDescription.getAnnotationType())) {
throw new IllegalStateException("Duplicate annotation " + annotationDescription + " for " + this);
}
}
Set<FieldDescription.SignatureToken> fieldSignatureTokens = new HashSet<FieldDescription.SignatureToken>();
for (FieldDescription.InDefinedShape fieldDescription : getDeclaredFields()) {
String fieldName = fieldDescription.getName();
if (!fieldSignatureTokens.add(fieldDescription.asSignatureToken())) {
throw new IllegalStateException("Duplicate field definition for " + fieldDescription);
} else if (!isValidIdentifier(fieldName)) {
throw new IllegalStateException("Illegal field name for " + fieldDescription);
} else if ((fieldDescription.getModifiers() & ~ModifierContributor.ForField.MASK) != EMPTY_MASK) {
throw new IllegalStateException("Illegal field modifiers " + fieldDescription.getModifiers() + " for " + fieldDescription);
}
Generic fieldType = fieldDescription.getType();
if (!fieldType.accept(Generic.Visitor.Validator.FIELD)) {
throw new IllegalStateException("Illegal field type " + fieldType + " for " + fieldDescription);
} else if (!fieldType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on " + fieldType + " for " + this);
} else if (!fieldDescription.isSynthetic() && !fieldType.asErasure().isVisibleTo(this)) {
throw new IllegalStateException("Invisible field type " + fieldDescription.getType() + " for " + fieldDescription);
}
Set<TypeDescription> fieldAnnotationTypes = new HashSet<TypeDescription>();
for (AnnotationDescription annotationDescription : fieldDescription.getDeclaredAnnotations()) {
if (!annotationDescription.getElementTypes().contains(ElementType.FIELD)) {
throw new IllegalStateException("Cannot add " + annotationDescription + " on " + fieldDescription);
} else if (!fieldAnnotationTypes.add(annotationDescription.getAnnotationType())) {
throw new IllegalStateException("Duplicate annotation " + annotationDescription + " for " + fieldDescription);
}
}
}
Set<MethodDescription.SignatureToken> methodSignatureTokens = new HashSet<MethodDescription.SignatureToken>();
for (MethodDescription.InDefinedShape methodDescription : getDeclaredMethods()) {
if (!methodSignatureTokens.add(methodDescription.asSignatureToken())) {
throw new IllegalStateException("Duplicate method signature for " + methodDescription);
} else if ((methodDescription.getModifiers() & ~ModifierContributor.ForMethod.MASK) != 0) {
throw new IllegalStateException("Illegal modifiers " + methodDescription.getModifiers() + " for " + methodDescription);
}
Set<String> methodTypeVariableNames = new HashSet<String>();
for (TypeDescription.Generic typeVariable : methodDescription.getTypeVariables()) {
String variableSymbol = typeVariable.getSymbol();
if (!methodTypeVariableNames.add(variableSymbol)) {
throw new IllegalStateException("Duplicate type variable symbol '" + typeVariable + "' for " + methodDescription);
} else if (!isValidIdentifier(variableSymbol)) {
throw new IllegalStateException("Illegal type variable name '" + typeVariable + "' for " + methodDescription);
} else if (!Generic.Visitor.Validator.ForTypeAnnotations.ofFormalTypeVariable(typeVariable)) {
throw new IllegalStateException("Illegal type annotation on '" + typeVariable + "' for " + methodDescription);
}
boolean interfaceBound = false;
Set<TypeDescription.Generic> bounds = new HashSet<Generic>();
for (TypeDescription.Generic bound : typeVariable.getUpperBounds()) {
if (!bound.accept(Generic.Visitor.Validator.TYPE_VARIABLE)) {
throw new IllegalStateException("Illegal type variable bound " + bound + " of " + typeVariable + " for " + methodDescription);
} else if (!bound.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on bound " + bound + " of " + typeVariable + " for " + this);
} else if (!bounds.add(bound)) {
throw new IllegalStateException("Duplicate bound " + bound + " of " + typeVariable + " for " + methodDescription);
} else if (interfaceBound && (bound.getSort().isTypeVariable() || !bound.isInterface())) {
throw new IllegalStateException("Illegal interface bound " + bound + " of " + typeVariable + " for " + methodDescription);
}
interfaceBound = true;
}
if (!interfaceBound) {
throw new IllegalStateException("Type variable " + typeVariable + " for " + methodDescription + " does not define at least one bound");
}
}
Generic returnType = methodDescription.getReturnType();
if (methodDescription.isTypeInitializer()) {
throw new IllegalStateException("Illegal explicit declaration of a type initializer by " + this);
} else if (methodDescription.isConstructor()) {
if (!returnType.represents(void.class)) {
throw new IllegalStateException("A constructor must return void " + methodDescription);
} else if (!returnType.getDeclaredAnnotations().isEmpty()) {
throw new IllegalStateException("The void non-type must not be annotated for " + methodDescription);
}
} else if (!isValidIdentifier(methodDescription.getInternalName())) {
throw new IllegalStateException("Illegal method name " + returnType + " for " + methodDescription);
} else if (!returnType.accept(Generic.Visitor.Validator.METHOD_RETURN)) {
throw new IllegalStateException("Illegal return type " + returnType + " for " + methodDescription);
} else if (!returnType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on return type " + returnType + " for " + methodDescription);
} else if (!methodDescription.isSynthetic() && !methodDescription.getReturnType().asErasure().isVisibleTo(this)) {
throw new IllegalStateException("Invisible return type " + methodDescription.getReturnType() + " for " + methodDescription);
}
Set<String> parameterNames = new HashSet<String>();
for (ParameterDescription.InDefinedShape parameterDescription : methodDescription.getParameters()) {
Generic parameterType = parameterDescription.getType();
if (!parameterType.accept(Generic.Visitor.Validator.METHOD_PARAMETER)) {
throw new IllegalStateException("Illegal parameter type of " + parameterDescription + " for " + methodDescription);
} else if (!parameterType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on parameter " + parameterDescription + " for " + methodDescription);
} else if (!methodDescription.isSynthetic() && !parameterType.asErasure().isVisibleTo(this)) {
throw new IllegalStateException("Invisible parameter type of " + parameterDescription + " for " + methodDescription);
}
if (parameterDescription.isNamed()) {
String parameterName = parameterDescription.getName();
if (!parameterNames.add(parameterName)) {
throw new IllegalStateException("Duplicate parameter name of " + parameterDescription + " for " + methodDescription);
} else if (!isValidIdentifier(parameterName)) {
throw new IllegalStateException("Illegal parameter name of " + parameterDescription + " for " + methodDescription);
}
}
if (parameterDescription.hasModifiers() && (parameterDescription.getModifiers() & ~ModifierContributor.ForParameter.MASK) != EMPTY_MASK) {
throw new IllegalStateException("Illegal modifiers of " + parameterDescription + " for " + methodDescription);
}
Set<TypeDescription> parameterAnnotationTypes = new HashSet<TypeDescription>();
for (AnnotationDescription annotationDescription : parameterDescription.getDeclaredAnnotations()) {
if (!annotationDescription.getElementTypes().contains(ElementType.PARAMETER)) {
throw new IllegalStateException("Cannot add " + annotationDescription + " on " + parameterDescription);
} else if (!parameterAnnotationTypes.add(annotationDescription.getAnnotationType())) {
throw new IllegalStateException("Duplicate annotation " + annotationDescription + " of " + parameterDescription + " for " + methodDescription);
}
}
}
for (TypeDescription.Generic exceptionType : methodDescription.getExceptionTypes()) {
if (!exceptionType.accept(Generic.Visitor.Validator.EXCEPTION)) {
throw new IllegalStateException("Illegal exception type " + exceptionType + " for " + methodDescription);
} else if (!exceptionType.accept(Generic.Visitor.Validator.ForTypeAnnotations.INSTANCE)) {
throw new IllegalStateException("Illegal type annotations on " + exceptionType + " for " + methodDescription);
} else if (!methodDescription.isSynthetic() && !exceptionType.asErasure().isVisibleTo(this)) {
throw new IllegalStateException("Invisible exception type " + exceptionType + " for " + methodDescription);
}
}
Set<TypeDescription> methodAnnotationTypes = new HashSet<TypeDescription>();
for (AnnotationDescription annotationDescription : methodDescription.getDeclaredAnnotations()) {
if (!annotationDescription.getElementTypes().contains(methodDescription.isMethod() ? ElementType.METHOD : ElementType.CONSTRUCTOR)) {
throw new IllegalStateException("Cannot add " + annotationDescription + " on " + methodDescription);
} else if (!methodAnnotationTypes.add(annotationDescription.getAnnotationType())) {
throw new IllegalStateException("Duplicate annotation " + annotationDescription + " for " + methodDescription);
}
}
AnnotationValue<?, ?> defaultValue = methodDescription.getDefaultValue();
if (defaultValue != null && !methodDescription.isDefaultValue(defaultValue)) {
throw new IllegalStateException("Illegal default value " + defaultValue + "for " + methodDescription);
}
Generic receiverType = methodDescription.getReceiverType();
if (receiverType != null && !receiverType.accept(Generic.Visitor.Validator.RECEIVER)) {
throw new IllegalStateException("Illegal receiver type " + receiverType + " for " + methodDescription);
} else if (methodDescription.isStatic()) {
if (receiverType != null) {
throw new IllegalStateException("Static method " + methodDescription + " defines a non-null receiver " + receiverType);
}
} else if (methodDescription.isConstructor()) {
if (receiverType == null || !receiverType.asErasure().equals(enclosingType == null ? this : enclosingType)) {
throw new IllegalStateException("Constructor " + methodDescription + " defines an illegal receiver " + receiverType);
}
} else if (/* methodDescription.isMethod() */ receiverType == null || !equals(receiverType.asErasure())) {
throw new IllegalStateException("Method " + methodDescription + " defines an illegal receiver " + receiverType);
}
}
return this;
}
Checks if an array of identifiers is a valid compound Java identifier.
Params: - identifier – an array of potentially invalid Java identifiers.
Returns: true
if all identifiers are valid and the array is not empty.
/**
* Checks if an array of identifiers is a valid compound Java identifier.
*
* @param identifier an array of potentially invalid Java identifiers.
* @return {@code true} if all identifiers are valid and the array is not empty.
*/
private static boolean isValidIdentifier(String[] identifier) {
if (identifier.length == 0) {
return false;
}
for (String part : identifier) {
if (!isValidIdentifier(part)) {
return false;
}
}
return true;
}
Checks if a Java identifier is valid.
Params: - identifier – The identifier to check for validity.
Returns: true
if the given identifier is valid.
/**
* Checks if a Java identifier is valid.
*
* @param identifier The identifier to check for validity.
* @return {@code true} if the given identifier is valid.
*/
private static boolean isValidIdentifier(String identifier) {
if (KEYWORDS.contains(identifier) || identifier.length() == 0 || !Character.isJavaIdentifierStart(identifier.charAt(0))) {
return false;
} else if (identifier.equals(PackageDescription.PACKAGE_CLASS_NAME)) {
return true;
}
for (int index = 1; index < identifier.length(); index++) {
if (!Character.isJavaIdentifierPart(identifier.charAt(index))) {
return false;
}
}
return true;
}
}
A frozen representation of an instrumented type of which the structure must not be modified.
/**
* A frozen representation of an instrumented type of which the structure must not be modified.
*/
class Frozen extends AbstractBase.OfSimpleType implements InstrumentedType.WithFlexibleName {
The represented type description.
/**
* The represented type description.
*/
private final TypeDescription typeDescription;
The type's loaded type initializer.
/**
* The type's loaded type initializer.
*/
private final LoadedTypeInitializer loadedTypeInitializer;
Creates a new frozen representation of an instrumented type.
Params: - typeDescription – The represented type description.
- loadedTypeInitializer – The type's loaded type initializer.
/**
* Creates a new frozen representation of an instrumented type.
*
* @param typeDescription The represented type description.
* @param loadedTypeInitializer The type's loaded type initializer.
*/
protected Frozen(TypeDescription typeDescription, LoadedTypeInitializer loadedTypeInitializer) {
this.typeDescription = typeDescription;
this.loadedTypeInitializer = loadedTypeInitializer;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public AnnotationList getDeclaredAnnotations() {
return typeDescription.getDeclaredAnnotations();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public int getModifiers() {
return typeDescription.getModifiers();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList.Generic getTypeVariables() {
return typeDescription.getTypeVariables();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public String getName() {
return typeDescription.getName();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public Generic getSuperClass() {
return typeDescription.getSuperClass();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList.Generic getInterfaces() {
return typeDescription.getInterfaces();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public FieldList<FieldDescription.InDefinedShape> getDeclaredFields() {
return typeDescription.getDeclaredFields();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public MethodList<MethodDescription.InDefinedShape> getDeclaredMethods() {
return typeDescription.getDeclaredMethods();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean isAnonymousType() {
return typeDescription.isAnonymousType();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public boolean isLocalType() {
return typeDescription.isLocalType();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public PackageDescription getPackage() {
return typeDescription.getPackage();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription getEnclosingType() {
return typeDescription.getEnclosingType();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription getDeclaringType() {
return typeDescription.getDeclaringType();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList getDeclaredTypes() {
return typeDescription.getDeclaredTypes();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public MethodDescription.InDefinedShape getEnclosingMethod() {
return typeDescription.getEnclosingMethod();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public String getGenericSignature() {
// Embrace use of native generic signature by direct delegation.
return typeDescription.getGenericSignature();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public int getActualModifiers(boolean superFlag) {
// Embrace use of native actual modifiers by direct delegation.
return typeDescription.getActualModifiers(superFlag);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription getNestHost() {
return typeDescription.getNestHost();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeList getNestMembers() {
return typeDescription.getNestMembers();
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withField(FieldDescription.Token token) {
throw new IllegalStateException("Cannot define field for frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withMethod(MethodDescription.Token token) {
throw new IllegalStateException("Cannot define method for frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withModifiers(int modifiers) {
throw new IllegalStateException("Cannot change modifiers for frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes) {
throw new IllegalStateException("Cannot add interfaces for frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withTypeVariable(TypeVariableToken typeVariable) {
throw new IllegalStateException("Cannot define type variable for frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withAnnotations(List<? extends AnnotationDescription> annotationDescriptions) {
throw new IllegalStateException("Cannot add annotation to frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withNestHost(TypeDescription nestHost) {
throw new IllegalStateException("Cannot set nest host of frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withNestMembers(TypeList nestMembers) {
throw new IllegalStateException("Cannot add nest members to frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withEnclosingType(TypeDescription enclosingType) {
throw new IllegalStateException("Cannot set enclosing type of frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enclosingMethod) {
throw new IllegalStateException("Cannot set enclosing method of frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withDeclaringType(TypeDescription declaringType) {
throw new IllegalStateException("Cannot add declaring type to frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withDeclaredTypes(TypeList declaredTypes) {
throw new IllegalStateException("Cannot add declared types to frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withLocalClass(boolean localClass) {
throw new IllegalStateException("Cannot define local class state to frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withAnonymousClass(boolean anonymousClass) {
throw new IllegalStateException("Cannot define anonymous class state to frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitializer) {
return new Frozen(typeDescription, new LoadedTypeInitializer.Compound(this.loadedTypeInitializer, loadedTypeInitializer));
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender) {
throw new IllegalStateException("Cannot add initializer to frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withName(String name) {
throw new IllegalStateException("Cannot change name of frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matcher, Transformer<TypeVariableToken> transformer) {
throw new IllegalStateException("Cannot add type variables of frozen type: " + typeDescription);
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public LoadedTypeInitializer getLoadedTypeInitializer() {
return loadedTypeInitializer;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeInitializer getTypeInitializer() {
return TypeInitializer.None.INSTANCE;
}
{@inheritDoc}
/**
* {@inheritDoc}
*/
public TypeDescription validated() {
return typeDescription;
}
}
}