Skip to content

Commit

Permalink
Add auxiliary field mechanism.
Browse files Browse the repository at this point in the history
  • Loading branch information
raphw committed Nov 22, 2021
1 parent 5447bf3 commit e0e87be
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ public interface InstrumentedType extends TypeDescription {
*/
InstrumentedType withField(FieldDescription.Token token);

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

/**
* Creates a new instrumented type that includes a new method or constructor.
*
Expand Down Expand Up @@ -237,6 +246,11 @@ interface WithFlexibleName extends InstrumentedType {
*/
WithFlexibleName withField(FieldDescription.Token token);

/**
* {@inheritDoc}
*/
WithFlexibleName withAuxiliaryField(FieldDescription.Token token, Object value);

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -418,6 +432,7 @@ public InstrumentedType.WithFlexibleName represent(TypeDescription typeDescripti
typeDescription.getTypeVariables().asTokenList(is(typeDescription)),
typeDescription.getInterfaces().accept(Generic.Visitor.Substitutor.ForDetachment.of(typeDescription)),
typeDescription.getDeclaredFields().asTokenList(is(typeDescription)),
Collections.<String, Object>emptyMap(),
typeDescription.getDeclaredMethods().asTokenList(is(typeDescription)),
typeDescription.getRecordComponents().asTokenList(is(typeDescription)),
typeDescription.getDeclaredAnnotations(),
Expand Down Expand Up @@ -462,6 +477,7 @@ public InstrumentedType.WithFlexibleName subclass(String name, int modifiers, Ty
Collections.<TypeVariableToken>emptyList(),
Collections.<Generic>emptyList(),
Collections.<FieldDescription.Token>emptyList(),
Collections.<String, Object>emptyMap(),
Collections.<MethodDescription.Token>emptyList(),
Collections.<RecordComponentDescription.Token>emptyList(),
Collections.<AnnotationDescription>emptyList(),
Expand Down Expand Up @@ -527,6 +543,11 @@ class Default extends AbstractBase.OfSimpleType implements InstrumentedType.With
*/
private final List<? extends FieldDescription.Token> fieldTokens;

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

/**
* A list of method tokens describing the methods of the instrumented type.
*/
Expand Down Expand Up @@ -611,6 +632,7 @@ class Default extends AbstractBase.OfSimpleType implements InstrumentedType.With
* @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 auxiliaryFieldValues A mapping of auxiliary field names to their mapped values.
* @param methodTokens A list of method tokens describing the methods of the instrumented type.
* @param recordComponentTokens A list of record component tokens describing the record components of the instrumented type.
* @param annotationDescriptions A list of annotations of the annotated type.
Expand All @@ -633,6 +655,7 @@ protected Default(String name,
List<? extends TypeVariableToken> typeVariables,
List<? extends Generic> interfaceTypes,
List<? extends FieldDescription.Token> fieldTokens,
Map<String, Object> auxiliaryFieldValues,
List<? extends MethodDescription.Token> methodTokens,
List<? extends RecordComponentDescription.Token> recordComponentTokens,
List<? extends AnnotationDescription> annotationDescriptions,
Expand All @@ -654,6 +677,7 @@ protected Default(String name,
this.superClass = superClass;
this.interfaceTypes = interfaceTypes;
this.fieldTokens = fieldTokens;
this.auxiliaryFields = auxiliaryFieldValues;
this.methodTokens = methodTokens;
this.recordComponentTokens = recordComponentTokens;
this.annotationDescriptions = annotationDescriptions;
Expand Down Expand Up @@ -705,6 +729,7 @@ public WithFlexibleName withModifiers(int modifiers) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand All @@ -726,12 +751,13 @@ public WithFlexibleName withModifiers(int modifiers) {
* {@inheritDoc}
*/
public WithFlexibleName withField(FieldDescription.Token token) {
return new Default(this.name,
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
CompoundList.of(fieldTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand All @@ -749,6 +775,46 @@ public WithFlexibleName withField(FieldDescription.Token token) {
nestMembers);
}

/**
* {@inheritDoc}
*/
public WithFlexibleName withAuxiliaryField(FieldDescription.Token token, Object value) {
Map<String, Object> auxiliaryFields = new HashMap<String, Object>(this.auxiliaryFields);
Object previous = auxiliaryFields.put(token.getName(), value);
if (previous != null) {
if (previous == value) {
return this;
} else {
throw new IllegalStateException("Field " + token.getName()
+ " for " + this
+ " already mapped to " + previous
+ " and not " + value);
}
}
return new Default(name,
modifiers,
superClass,
typeVariables,
interfaceTypes,
CompoundList.of(fieldTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
typeInitializer,
new LoadedTypeInitializer.Compound(loadedTypeInitializer, new LoadedTypeInitializer.ForStaticField(token.getName(), value)),
declaringType,
enclosingMethod,
enclosingType,
declaredTypes,
permittedSubclasses,
anonymousClass,
localClass,
record,
nestHost,
nestMembers);
}

/**
* {@inheritDoc}
*/
Expand All @@ -759,6 +825,7 @@ public WithFlexibleName withMethod(MethodDescription.Token token) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
CompoundList.of(methodTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -786,6 +853,7 @@ public WithFlexibleName withRecordComponent(RecordComponentDescription.Token tok
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
CompoundList.of(recordComponentTokens, token.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
annotationDescriptions,
Expand Down Expand Up @@ -813,6 +881,7 @@ public WithFlexibleName withInterfaces(TypeList.Generic interfaceTypes) {
typeVariables,
CompoundList.of(this.interfaceTypes, interfaceTypes.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -840,6 +909,7 @@ public WithFlexibleName withAnnotations(List<? extends AnnotationDescription> an
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
CompoundList.of(this.annotationDescriptions, annotationDescriptions),
Expand Down Expand Up @@ -867,6 +937,7 @@ public WithFlexibleName withNestHost(TypeDescription nestHost) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -896,6 +967,7 @@ public WithFlexibleName withNestMembers(TypeList nestMembers) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -923,6 +995,7 @@ public WithFlexibleName withEnclosingType(TypeDescription enclosingType) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -950,6 +1023,7 @@ public WithFlexibleName withEnclosingMethod(MethodDescription.InDefinedShape enc
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -977,6 +1051,7 @@ public WithFlexibleName withDeclaringType(TypeDescription declaringType) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1004,6 +1079,7 @@ public WithFlexibleName withDeclaredTypes(TypeList declaredTypes) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1031,6 +1107,7 @@ public WithFlexibleName withPermittedSubclasses(TypeList permittedSubclasses) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1060,6 +1137,7 @@ public WithFlexibleName withTypeVariable(TypeVariableToken typeVariable) {
CompoundList.of(typeVariables, typeVariable.accept(Generic.Visitor.Substitutor.ForDetachment.of(this))),
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1087,6 +1165,7 @@ public WithFlexibleName withName(String name) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1121,6 +1200,7 @@ public WithFlexibleName withTypeVariables(ElementMatcher<? super Generic> matche
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1148,6 +1228,7 @@ public WithFlexibleName withLocalClass(boolean localClass) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1175,6 +1256,7 @@ public WithFlexibleName withAnonymousClass(boolean anonymousClass) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1202,6 +1284,7 @@ public WithFlexibleName withRecord(boolean record) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
record
? recordComponentTokens
Expand Down Expand Up @@ -1231,6 +1314,7 @@ public WithFlexibleName withInitializer(LoadedTypeInitializer loadedTypeInitiali
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1258,6 +1342,7 @@ public WithFlexibleName withInitializer(ByteCodeAppender byteCodeAppender) {
typeVariables,
interfaceTypes,
fieldTokens,
auxiliaryFields,
methodTokens,
recordComponentTokens,
annotationDescriptions,
Expand Down Expand Up @@ -1441,8 +1526,8 @@ public boolean isSealed() {
*/
public TypeList getPermittedSubtypes() {
return permittedSubclasses == null
? new TypeList.Empty()
: new TypeList.Explicit(permittedSubclasses);
? new TypeList.Empty()
: new TypeList.Explicit(permittedSubclasses);
}

/**
Expand Down Expand Up @@ -1950,6 +2035,13 @@ public WithFlexibleName withField(FieldDescription.Token token) {
throw new IllegalStateException("Cannot define field for frozen type: " + typeDescription);
}

/**
* {@inheritDoc}
*/
public WithFlexibleName withAuxiliaryField(FieldDescription.Token token, Object value) {
throw new IllegalStateException("Cannot define auxiliary field for frozen type: " + typeDescription);
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import java.lang.reflect.Field;
import java.lang.reflect.Type;

import static net.bytebuddy.matcher.ElementMatchers.fieldType;
import static net.bytebuddy.matcher.ElementMatchers.named;

/**
Expand Down Expand Up @@ -1265,16 +1264,9 @@ protected OfReferenceValue(FieldLocation fieldLocation,
* {@inheritDoc}
*/
public InstrumentedType prepare(InstrumentedType instrumentedType) {
if (!instrumentedType.getDeclaredFields().filter(named(name).and(fieldType(value.getClass()))).isEmpty()) {
throw new IllegalStateException("Field with name " + name
+ " and type " + value.getClass()
+ " already declared by " + instrumentedType);
}
return instrumentedType
.withField(new FieldDescription.Token(name,
Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC,
TypeDescription.ForLoadedType.of(value.getClass()).asGenericType()))
.withInitializer(new LoadedTypeInitializer.ForStaticField(name, value));
return instrumentedType.withAuxiliaryField(new FieldDescription.Token(name,
Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC,
TypeDescription.ForLoadedType.of(value.getClass()).asGenericType()), value);
}

/**
Expand Down
Loading

0 comments on commit e0e87be

Please sign in to comment.