Skip to content

Commit

Permalink
Added a method call instrumentation that allows to create explicit ca…
Browse files Browse the repository at this point in the history
…lls.
  • Loading branch information
Rafael Winterhalter committed Feb 9, 2015
1 parent 0a06194 commit 2736224
Show file tree
Hide file tree
Showing 13 changed files with 2,091 additions and 77 deletions.
Expand Up @@ -41,17 +41,17 @@ public abstract class FieldAccessor implements Instrumentation {
* {@code true} if the runtime type of the field's value should be considered when a field
* is accessed.
*/
protected final boolean considerRuntimeType;
protected final boolean dynamicallyTyped;

/**
* Creates a new field accessor.
*
* @param assigner The assigner to use.
* @param considerRuntimeType {@code true} if a field value's runtime type should be considered.
* @param dynamicallyTyped {@code true} if a field value's runtime type should be considered.
*/
protected FieldAccessor(Assigner assigner, boolean considerRuntimeType) {
protected FieldAccessor(Assigner assigner, boolean dynamicallyTyped) {
this.assigner = assigner;
this.considerRuntimeType = considerRuntimeType;
this.dynamicallyTyped = dynamicallyTyped;
}

/**
Expand Down Expand Up @@ -120,7 +120,7 @@ protected ByteCodeAppender.Size applyGetter(MethodVisitor methodVisitor,
MethodDescription methodDescription) {
StackManipulation stackManipulation = assigner.assign(fieldDescription.getFieldType(),
methodDescription.getReturnType(),
considerRuntimeType);
dynamicallyTyped);
if (!stackManipulation.isValid()) {
throw new IllegalStateException("Getter type of " + methodDescription + " is not compatible with " + fieldDescription);
}
Expand Down Expand Up @@ -150,7 +150,7 @@ protected ByteCodeAppender.Size applySetter(MethodVisitor methodVisitor,
MethodDescription methodDescription) {
StackManipulation stackManipulation = assigner.assign(methodDescription.getParameterTypes().get(0),
fieldDescription.getFieldType(),
considerRuntimeType);
dynamicallyTyped);
if (!stackManipulation.isValid()) {
throw new IllegalStateException("Setter type of " + methodDescription + " is not compatible with " + fieldDescription);
} else if (fieldDescription.isFinal()) {
Expand Down Expand Up @@ -209,13 +209,13 @@ private ByteCodeAppender.Size apply(MethodVisitor methodVisitor,
@Override
public boolean equals(Object other) {
return this == other || !(other == null || getClass() != other.getClass())
&& considerRuntimeType == ((FieldAccessor) other).considerRuntimeType
&& dynamicallyTyped == ((FieldAccessor) other).dynamicallyTyped
&& assigner.equals(((FieldAccessor) other).assigner);
}

@Override
public int hashCode() {
return 31 * assigner.hashCode() + (considerRuntimeType ? 1 : 0);
return 31 * assigner.hashCode() + (dynamicallyTyped ? 1 : 0);
}

/**
Expand Down Expand Up @@ -481,10 +481,10 @@ public static interface AssignerConfigurable extends Instrumentation {
* and runtime type use configuration.
*
* @param assigner The assigner to use.
* @param considerRuntimeType {@code true} if a field value's runtime type should be considered.
* @param dynamicallyTyped {@code true} if a field value's runtime type should be considered.
* @return This field accessor with the given assigner and runtime type use configuration.
*/
Instrumentation withAssigner(Assigner assigner, boolean considerRuntimeType);
Instrumentation withAssigner(Assigner assigner, boolean dynamicallyTyped);
}

/**
Expand Down Expand Up @@ -564,14 +564,14 @@ protected static class ForUnnamedField extends FieldAccessor implements OwnerTyp
* Creates a new field accessor instrumentation.
*
* @param assigner The assigner to use.
* @param considerRuntimeType {@code true} if a field value's runtime type should be considered.
* @param dynamicallyTyped {@code true} if a field value's runtime type should be considered.
* @param fieldNameExtractor The field name extractor to use.
*/
protected ForUnnamedField(Assigner assigner,
boolean considerRuntimeType,
boolean dynamicallyTyped,
FieldNameExtractor fieldNameExtractor) {
this(assigner,
considerRuntimeType,
dynamicallyTyped,
fieldNameExtractor,
FieldLocator.ForInstrumentedTypeHierarchy.Factory.INSTANCE);
}
Expand All @@ -580,23 +580,23 @@ protected ForUnnamedField(Assigner assigner,
* Creates a new field accessor instrumentation.
*
* @param assigner The assigner to use.
* @param considerRuntimeType {@code true} if a field value's runtime type should be considered.
* @param dynamicallyTyped {@code true} if a field value's runtime type should be considered.
* @param fieldNameExtractor The field name extractor to use.
* @param fieldLocatorFactory A factory that will produce a field locator that will be used to find locate
* a field to be accessed.
*/
protected ForUnnamedField(Assigner assigner,
boolean considerRuntimeType,
boolean dynamicallyTyped,
FieldNameExtractor fieldNameExtractor,
FieldLocator.Factory fieldLocatorFactory) {
super(assigner, considerRuntimeType);
super(assigner, dynamicallyTyped);
this.fieldNameExtractor = fieldNameExtractor;
this.fieldLocatorFactory = fieldLocatorFactory;
}

@Override
public AssignerConfigurable in(FieldLocator.Factory fieldLocatorFactory) {
return new ForUnnamedField(assigner, considerRuntimeType, fieldNameExtractor, nonNull(fieldLocatorFactory));
return new ForUnnamedField(assigner, dynamicallyTyped, fieldNameExtractor, nonNull(fieldLocatorFactory));
}

@Override
Expand All @@ -612,8 +612,8 @@ public AssignerConfigurable in(TypeDescription typeDescription) {
}

@Override
public Instrumentation withAssigner(Assigner assigner, boolean considerRuntimeType) {
return new ForUnnamedField(nonNull(assigner), considerRuntimeType, fieldNameExtractor, fieldLocatorFactory);
public Instrumentation withAssigner(Assigner assigner, boolean dynamicallyTyped) {
return new ForUnnamedField(nonNull(assigner), dynamicallyTyped, fieldNameExtractor, fieldLocatorFactory);
}

@Override
Expand Down Expand Up @@ -648,7 +648,7 @@ public int hashCode() {
public String toString() {
return "FieldAccessor.ForUnnamedField{" +
"assigner=" + assigner +
"considerRuntimeType=" + considerRuntimeType +
"dynamicallyTyped=" + dynamicallyTyped +
"fieldLocatorFactory=" + fieldLocatorFactory +
"fieldNameExtractor=" + fieldNameExtractor +
'}';
Expand Down Expand Up @@ -679,13 +679,13 @@ protected static class ForNamedField extends FieldAccessor implements FieldDefin
* Creates a field accessor instrumentation for a field of a given name.
*
* @param assigner The assigner to use.
* @param considerRuntimeType {@code true} if a field value's runtime type should be considered.
* @param dynamicallyTyped {@code true} if a field value's runtime type should be considered.
* @param fieldName The name of the field.
*/
protected ForNamedField(Assigner assigner,
boolean considerRuntimeType,
boolean dynamicallyTyped,
String fieldName) {
super(assigner, considerRuntimeType);
super(assigner, dynamicallyTyped);
this.fieldName = fieldName;
preparationHandler = PreparationHandler.NoOp.INSTANCE;
fieldLocatorFactory = FieldLocator.ForInstrumentedTypeHierarchy.Factory.INSTANCE;
Expand All @@ -699,14 +699,14 @@ protected ForNamedField(Assigner assigner,
* @param fieldLocatorFactory A factory that will produce a field locator that will be used to find locate
* a field to be accessed.
* @param assigner The assigner to use.
* @param considerRuntimeType {@code true} if a field value's runtime type should be considered.
* @param dynamicallyTyped {@code true} if a field value's runtime type should be considered.
*/
private ForNamedField(Assigner assigner,
boolean considerRuntimeType,
boolean dynamicallyTyped,
String fieldName,
PreparationHandler preparationHandler,
FieldLocator.Factory fieldLocatorFactory) {
super(assigner, considerRuntimeType);
super(assigner, dynamicallyTyped);
this.fieldName = fieldName;
this.preparationHandler = preparationHandler;
this.fieldLocatorFactory = fieldLocatorFactory;
Expand All @@ -720,7 +720,7 @@ public AssignerConfigurable defineAs(Class<?> type, ModifierContributor.ForField
@Override
public AssignerConfigurable defineAs(TypeDescription typeDescription, ModifierContributor.ForField... modifier) {
return new ForNamedField(assigner,
considerRuntimeType,
dynamicallyTyped,
fieldName,
new PreparationHandler.FieldDefiner(fieldName, nonVoid(typeDescription), nonNull(modifier)),
FieldLocator.ForInstrumentedType.INSTANCE);
Expand All @@ -729,7 +729,7 @@ public AssignerConfigurable defineAs(TypeDescription typeDescription, ModifierCo
@Override
public AssignerConfigurable in(FieldLocator.Factory fieldLocatorFactory) {
return new ForNamedField(assigner,
considerRuntimeType,
dynamicallyTyped,
fieldName,
preparationHandler,
nonNull(fieldLocatorFactory));
Expand All @@ -748,9 +748,9 @@ public AssignerConfigurable in(TypeDescription typeDescription) {
}

@Override
public Instrumentation withAssigner(Assigner assigner, boolean considerRuntimeType) {
public Instrumentation withAssigner(Assigner assigner, boolean dynamicallyTyped) {
return new ForNamedField(nonNull(assigner),
considerRuntimeType,
dynamicallyTyped,
fieldName,
preparationHandler,
fieldLocatorFactory);
Expand Down Expand Up @@ -795,7 +795,7 @@ public int hashCode() {
public String toString() {
return "FieldAccessor.ForNamedField{" +
"assigner=" + assigner +
"considerRuntimeType=" + considerRuntimeType +
"dynamicallyTyped=" + dynamicallyTyped +
"fieldName='" + fieldName + '\'' +
", preparationHandler=" + preparationHandler +
", fieldLocatorFactory=" + fieldLocatorFactory +
Expand Down
Expand Up @@ -35,18 +35,18 @@ public abstract class FixedValue implements Instrumentation {
/**
* Determines if the runtime type of a fixed value should be considered for the assignment to a return type.
*/
protected final boolean considerRuntimeType;
protected final boolean dynamicallyTyped;

/**
* Creates a new fixed value instrumentation.
*
* @param assigner The assigner to use for assigning the fixed value to the return type of the instrumented value.
* @param considerRuntimeType If {@code true}, the runtime type of the given value will be considered for assigning
* @param dynamicallyTyped If {@code true}, the runtime type of the given value will be considered for assigning
* the return type.
*/
protected FixedValue(Assigner assigner, boolean considerRuntimeType) {
protected FixedValue(Assigner assigner, boolean dynamicallyTyped) {
this.assigner = assigner;
this.considerRuntimeType = considerRuntimeType;
this.dynamicallyTyped = dynamicallyTyped;
}

/**
Expand Down Expand Up @@ -216,7 +216,8 @@ protected ByteCodeAppender.Size apply(MethodVisitor methodVisitor,
MethodDescription instrumentedMethod,
TypeDescription fixedValueType,
StackManipulation valueLoadingInstruction) {
StackManipulation assignment = assigner.assign(fixedValueType, instrumentedMethod.getReturnType(), considerRuntimeType);
StackManipulation assignment = assigner.assign(fixedValueType, instrumentedMethod.getReturnType(),
dynamicallyTyped);
if (!assignment.isValid()) {
throw new IllegalArgumentException("Cannot return value of type " + fixedValueType + " for " + instrumentedMethod);
}
Expand All @@ -231,13 +232,13 @@ protected ByteCodeAppender.Size apply(MethodVisitor methodVisitor,
@Override
public boolean equals(Object other) {
return this == other || !(other == null || getClass() != other.getClass())
&& considerRuntimeType == ((FixedValue) other).considerRuntimeType
&& dynamicallyTyped == ((FixedValue) other).dynamicallyTyped
&& assigner.equals(((FixedValue) other).assigner);
}

@Override
public int hashCode() {
return 31 * assigner.hashCode() + (considerRuntimeType ? 1 : 0);
return 31 * assigner.hashCode() + (dynamicallyTyped ? 1 : 0);
}

/**
Expand All @@ -251,11 +252,11 @@ public static interface AssignerConfigurable extends Instrumentation {
*
* @param assigner The assigner to use for assigning the fixed value to the return type of the
* instrumented value.
* @param considerRuntimeType If {@code true}, the runtime type of the given value will be considered for
* @param dynamicallyTyped If {@code true}, the runtime type of the given value will be considered for
* assigning the return type.
* @return A fixed value instrumentation that makes use of the given assigner.
*/
Instrumentation withAssigner(Assigner assigner, boolean considerRuntimeType);
Instrumentation withAssigner(Assigner assigner, boolean dynamicallyTyped);
}

/**
Expand All @@ -282,21 +283,21 @@ protected static class ForPoolValue extends FixedValue implements AssignerConfig
* @param loadedType A type description representing the loaded type.
* @param assigner The assigner to use for assigning the fixed value to the return type of the
* instrumented value.
* @param considerRuntimeType If {@code true}, the runtime type of the given value will be considered for
* @param dynamicallyTyped If {@code true}, the runtime type of the given value will be considered for
* assigning the return type.
*/
private ForPoolValue(StackManipulation valueLoadInstruction,
TypeDescription loadedType,
Assigner assigner,
boolean considerRuntimeType) {
super(assigner, considerRuntimeType);
boolean dynamicallyTyped) {
super(assigner, dynamicallyTyped);
this.valueLoadInstruction = valueLoadInstruction;
this.loadedType = loadedType;
}

@Override
public Instrumentation withAssigner(Assigner assigner, boolean considerRuntimeType) {
return new ForPoolValue(valueLoadInstruction, loadedType, nonNull(assigner), considerRuntimeType);
public Instrumentation withAssigner(Assigner assigner, boolean dynamicallyTyped) {
return new ForPoolValue(valueLoadInstruction, loadedType, nonNull(assigner), dynamicallyTyped);
}

@Override
Expand Down Expand Up @@ -341,7 +342,7 @@ public String toString() {
"valueLoadInstruction=" + valueLoadInstruction +
", loadedType=" + loadedType +
", assigner=" + assigner +
", considerRuntimeType=" + considerRuntimeType +
", dynamicallyTyped=" + dynamicallyTyped +
'}';
}
}
Expand Down Expand Up @@ -378,11 +379,11 @@ protected static class ForStaticField extends FixedValue implements AssignerConf
* @param fixedValue The fixed value to be returned.
* @param assigner The assigner to use for assigning the fixed value to the return type of the
* instrumented value.
* @param considerRuntimeType If {@code true}, the runtime type of the given value will be considered for
* @param dynamicallyTyped If {@code true}, the runtime type of the given value will be considered for
* assigning the return type.
*/
protected ForStaticField(Object fixedValue, Assigner assigner, boolean considerRuntimeType) {
this(String.format("%s$%d", PREFIX, Math.abs(fixedValue.hashCode())), fixedValue, assigner, considerRuntimeType);
protected ForStaticField(Object fixedValue, Assigner assigner, boolean dynamicallyTyped) {
this(String.format("%s$%d", PREFIX, Math.abs(fixedValue.hashCode())), fixedValue, assigner, dynamicallyTyped);
}

/**
Expand All @@ -392,19 +393,19 @@ protected ForStaticField(Object fixedValue, Assigner assigner, boolean considerR
* @param fixedValue The fixed value to be returned.
* @param assigner The assigner to use for assigning the fixed value to the return type of the
* instrumented value.
* @param considerRuntimeType If {@code true}, the runtime type of the given value will be considered for
* @param dynamicallyTyped If {@code true}, the runtime type of the given value will be considered for
* assigning the return type.
*/
protected ForStaticField(String fieldName, Object fixedValue, Assigner assigner, boolean considerRuntimeType) {
super(assigner, considerRuntimeType);
protected ForStaticField(String fieldName, Object fixedValue, Assigner assigner, boolean dynamicallyTyped) {
super(assigner, dynamicallyTyped);
this.fieldName = fieldName;
this.fixedValue = fixedValue;
fieldType = new TypeDescription.ForLoadedType(fixedValue.getClass());
}

@Override
public Instrumentation withAssigner(Assigner assigner, boolean considerRuntimeType) {
return new ForStaticField(fieldName, fixedValue, nonNull(assigner), considerRuntimeType);
public Instrumentation withAssigner(Assigner assigner, boolean dynamicallyTyped) {
return new ForStaticField(fieldName, fixedValue, nonNull(assigner), dynamicallyTyped);
}

@Override
Expand Down Expand Up @@ -439,7 +440,7 @@ public String toString() {
", fieldType=" + fieldType +
", fixedValue=" + fixedValue +
", assigner=" + assigner +
", considerRuntimeType=" + considerRuntimeType +
", dynamicallyTyped=" + dynamicallyTyped +
'}';
}

Expand Down

0 comments on commit 2736224

Please sign in to comment.