// Generated by delombok at Sun Feb 26 12:31:38 KST 2017 package scouter.bytebuddy.implementation; import scouter.bytebuddy.description.field.FieldDescription; import scouter.bytebuddy.description.method.MethodDescription; import scouter.bytebuddy.description.method.ParameterDescription; import scouter.bytebuddy.description.type.TypeDescription; import scouter.bytebuddy.dynamic.scaffold.FieldLocator; import scouter.bytebuddy.dynamic.scaffold.InstrumentedType; import scouter.bytebuddy.implementation.bytecode.ByteCodeAppender; import scouter.bytebuddy.implementation.bytecode.StackManipulation; import scouter.bytebuddy.implementation.bytecode.assign.Assigner; import scouter.bytebuddy.implementation.bytecode.member.FieldAccess; import scouter.bytebuddy.implementation.bytecode.member.MethodReturn; import scouter.bytebuddy.implementation.bytecode.member.MethodVariableAccess; import scouter.bytebuddy.jar.asm.MethodVisitor; import java.lang.reflect.Field; /** * <p> * Defines a method to access a given field by following the Java bean conventions for getters and setters: * </p> * <ul> * <li>Getter: A method named {@code getFoo()} will be instrumented to read and return the value of a field {@code foo} * or another field if one was specified explicitly. If a property is of type {@link java.lang.Boolean} or * {@code boolean}, the name {@code isFoo()} is also permitted.</li> * <li>Setter: A method named {@code setFoo(value)} will be instrumented to write the given argument {@code value} * to a field {@code foo} or to another field if one was specified explicitly.</li> * </ul> * <p> * Field accessors always implement a getter if a non-{@code void} value is returned from a method and attempt to define a setter * otherwise. If a field accessor is not explicitly defined as a setter via {@link PropertyConfigurable}, an instrumented * method must define exactly one parameter. Using the latter API, an explicit parameter index can be defined and a return * value can be specified explicitly when {@code void} is not returned. * </p> */ public abstract class FieldAccessor implements Implementation { /** * The field's location. */ protected final FieldLocation fieldLocation; /** * The assigner to use. */ protected final Assigner assigner; /** * Indicates if dynamic type castings should be attempted for incompatible assignments. */ protected final Assigner.Typing typing; /** * Creates a new field accessor. * * @param fieldLocation The field's location. * @param assigner The assigner to use. * @param typing Indicates if dynamic type castings should be attempted for incompatible assignments. */ protected FieldAccessor(FieldLocation fieldLocation, Assigner assigner, Assigner.Typing typing) { this.fieldLocation = fieldLocation; this.assigner = assigner; this.typing = typing; } /** * Defines a field accessor where any access is targeted to a field named {@code name}. * * @param name The name of the field to be accessed. * @return A field accessor for a field of a given name. */ public static OwnerTypeLocatable ofField(String name) { return of(new FieldNameExtractor.ForFixedValue(name)); } /** * Defines a field accessor where any access is targeted to a field that matches the methods * name with the Java specification for bean properties, i.e. a method {@code getFoo} or {@code setFoo(value)} * will either read or write a field named {@code foo}. * * @return A field accessor that follows the Java naming conventions for bean properties. */ public static OwnerTypeLocatable ofBeanProperty() { return of(FieldNameExtractor.ForBeanProperty.INSTANCE); } /** * Defines a custom strategy for determining the field that is accessed by this field accessor. * * @param fieldNameExtractor The field name extractor to use. * @return A field accessor using the given field name extractor. */ public static OwnerTypeLocatable of(FieldNameExtractor fieldNameExtractor) { return new ForImplicitProperty(new FieldLocation.Relative(fieldNameExtractor)); } /** * Defines a field accessor where the specified field is accessed. The field must be within the hierarchy of the instrumented type. * * @param field The field being accessed. * @return A field accessor for the given field. */ public static AssignerConfigurable of(Field field) { return of(new FieldDescription.ForLoadedField(field)); } /** * Defines a field accessor where the specified field is accessed. The field must be within the hierarchy of the instrumented type. * * @param fieldDescription The field being accessed. * @return A field accessor for the given field. */ public static AssignerConfigurable of(FieldDescription fieldDescription) { return new ForImplicitProperty(new FieldLocation.Absolute(fieldDescription)); } /** * Creates a getter getter. * * @param fieldDescription The field to read the value from. * @param instrumentedMethod The getter method. * @return A stack manipulation that gets the field's value. */ protected StackManipulation getter(FieldDescription fieldDescription, MethodDescription instrumentedMethod) { return access(fieldDescription, instrumentedMethod, new StackManipulation.Compound(FieldAccess.forField(fieldDescription).read(), assigner.assign(fieldDescription.getType(), instrumentedMethod.getReturnType(), typing))); } /** * Creates a setter instruction. * * @param fieldDescription The field to set a value for. * @param parameterDescription The parameter for what value is to be set. * @return A stack manipulation that sets the field's value. */ protected StackManipulation setter(FieldDescription fieldDescription, ParameterDescription parameterDescription) { if (fieldDescription.isFinal() && parameterDescription.getDeclaringMethod().isMethod()) { throw new IllegalArgumentException("Cannot set final field " + fieldDescription + " from " + parameterDescription.getDeclaringMethod()); } return access(fieldDescription, parameterDescription.getDeclaringMethod(), new StackManipulation.Compound(MethodVariableAccess.load(parameterDescription), assigner.assign(parameterDescription.getType(), fieldDescription.getType(), typing), FieldAccess.forField(fieldDescription).write())); } /** * Checks a field access and loads the {@code this} instance if necessary. * * @param fieldDescription The field to get a value * @param instrumentedMethod The instrumented method. * @param fieldAccess A stack manipulation describing the field access. * @return An appropriate stack manipulation. */ private StackManipulation access(FieldDescription fieldDescription, MethodDescription instrumentedMethod, StackManipulation fieldAccess) { if (!fieldAccess.isValid()) { throw new IllegalStateException("Incompatible type of " + fieldDescription + " and " + instrumentedMethod); } else if (instrumentedMethod.isStatic() && !fieldDescription.isStatic()) { throw new IllegalArgumentException("Cannot call instance field " + fieldDescription + " from static method " + instrumentedMethod); } return new StackManipulation.Compound(fieldDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), fieldAccess); } @Override public InstrumentedType prepare(InstrumentedType instrumentedType) { return instrumentedType; } /** * A field location represents an identified field description which depends on the instrumented type and method. */ protected interface FieldLocation { /** * Specifies a field locator factory to use. * * @param fieldLocatorFactory The field locator factory to use. * @return An appropriate field location. */ FieldLocation with(FieldLocator.Factory fieldLocatorFactory); /** * A prepared field location. * * @param instrumentedType The instrumented type. * @return A prepared field location. */ Prepared prepare(TypeDescription instrumentedType); /** * A prepared field location. */ interface Prepared { /** * Resolves the field description to use. * * @param instrumentedMethod The instrumented method. * @return The resolved field description. */ FieldDescription resolve(MethodDescription instrumentedMethod); } /** * An absolute field description representing a previously resolved field. */ class Absolute implements FieldLocation, Prepared { /** * The field description. */ private final FieldDescription fieldDescription; /** * Creates an absolute field location. * * @param fieldDescription The field description. */ protected Absolute(FieldDescription fieldDescription) { this.fieldDescription = fieldDescription; } @Override public FieldLocation with(FieldLocator.Factory fieldLocatorFactory) { throw new IllegalStateException("Cannot specify a field locator factory for an absolute field location"); } @Override public Prepared prepare(TypeDescription instrumentedType) { if (!instrumentedType.isAssignableTo(fieldDescription.getDeclaringType().asErasure())) { throw new IllegalStateException(fieldDescription + " is not declared by " + instrumentedType); } else if (!fieldDescription.isVisibleTo(instrumentedType)) { throw new IllegalStateException("Cannot access " + fieldDescription + " from " + instrumentedType); } return this; } @Override public FieldDescription resolve(MethodDescription instrumentedMethod) { return fieldDescription; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof FieldAccessor.FieldLocation.Absolute)) return false; final FieldAccessor.FieldLocation.Absolute other = (FieldAccessor.FieldLocation.Absolute) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$fieldDescription = this.fieldDescription; final java.lang.Object other$fieldDescription = other.fieldDescription; if (this$fieldDescription == null ? other$fieldDescription != null : !this$fieldDescription.equals(other$fieldDescription)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof FieldAccessor.FieldLocation.Absolute; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $fieldDescription = this.fieldDescription; result = result * PRIME + ($fieldDescription == null ? 43 : $fieldDescription.hashCode()); return result; } } /** * A relative field location where a field is located dynamically. */ class Relative implements FieldLocation { /** * The field name extractor to use. */ private final FieldNameExtractor fieldNameExtractor; /** * The field locator factory to use. */ private final FieldLocator.Factory fieldLocatorFactory; /** * Creates a new relative field location. * * @param fieldNameExtractor The field name extractor to use. */ protected Relative(FieldNameExtractor fieldNameExtractor) { this(fieldNameExtractor, FieldLocator.ForClassHierarchy.Factory.INSTANCE); } /** * Creates a new relative field location. * * @param fieldNameExtractor The field name extractor to use. * @param fieldLocatorFactory The field locator factory to use. */ private Relative(FieldNameExtractor fieldNameExtractor, FieldLocator.Factory fieldLocatorFactory) { this.fieldNameExtractor = fieldNameExtractor; this.fieldLocatorFactory = fieldLocatorFactory; } @Override public FieldLocation with(FieldLocator.Factory fieldLocatorFactory) { return new Relative(fieldNameExtractor, fieldLocatorFactory); } @Override public FieldLocation.Prepared prepare(TypeDescription instrumentedType) { return new Prepared(fieldNameExtractor, fieldLocatorFactory.make(instrumentedType)); } /** * A prepared version of a field location. */ protected static class Prepared implements FieldLocation.Prepared { /** * The field name extractor to use. */ private final FieldNameExtractor fieldNameExtractor; /** * The field locator factory to use. */ private final FieldLocator fieldLocator; /** * Creates a new relative field location. * * @param fieldNameExtractor The field name extractor to use. * @param fieldLocator The field locator to use. */ protected Prepared(FieldNameExtractor fieldNameExtractor, FieldLocator fieldLocator) { this.fieldNameExtractor = fieldNameExtractor; this.fieldLocator = fieldLocator; } @Override public FieldDescription resolve(MethodDescription instrumentedMethod) { FieldLocator.Resolution resolution = fieldLocator.locate(fieldNameExtractor.resolve(instrumentedMethod)); if (!resolution.isResolved()) { throw new IllegalStateException("Cannot resolve field for " + instrumentedMethod + " using " + fieldLocator); } return resolution.getField(); } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof FieldAccessor.FieldLocation.Relative.Prepared)) return false; final FieldAccessor.FieldLocation.Relative.Prepared other = (FieldAccessor.FieldLocation.Relative.Prepared) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$fieldNameExtractor = this.fieldNameExtractor; final java.lang.Object other$fieldNameExtractor = other.fieldNameExtractor; if (this$fieldNameExtractor == null ? other$fieldNameExtractor != null : !this$fieldNameExtractor.equals(other$fieldNameExtractor)) return false; final java.lang.Object this$fieldLocator = this.fieldLocator; final java.lang.Object other$fieldLocator = other.fieldLocator; if (this$fieldLocator == null ? other$fieldLocator != null : !this$fieldLocator.equals(other$fieldLocator)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof FieldAccessor.FieldLocation.Relative.Prepared; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $fieldNameExtractor = this.fieldNameExtractor; result = result * PRIME + ($fieldNameExtractor == null ? 43 : $fieldNameExtractor.hashCode()); final java.lang.Object $fieldLocator = this.fieldLocator; result = result * PRIME + ($fieldLocator == null ? 43 : $fieldLocator.hashCode()); return result; } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof FieldAccessor.FieldLocation.Relative)) return false; final FieldAccessor.FieldLocation.Relative other = (FieldAccessor.FieldLocation.Relative) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$fieldNameExtractor = this.fieldNameExtractor; final java.lang.Object other$fieldNameExtractor = other.fieldNameExtractor; if (this$fieldNameExtractor == null ? other$fieldNameExtractor != null : !this$fieldNameExtractor.equals(other$fieldNameExtractor)) return false; final java.lang.Object this$fieldLocatorFactory = this.fieldLocatorFactory; final java.lang.Object other$fieldLocatorFactory = other.fieldLocatorFactory; if (this$fieldLocatorFactory == null ? other$fieldLocatorFactory != null : !this$fieldLocatorFactory.equals(other$fieldLocatorFactory)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof FieldAccessor.FieldLocation.Relative; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $fieldNameExtractor = this.fieldNameExtractor; result = result * PRIME + ($fieldNameExtractor == null ? 43 : $fieldNameExtractor.hashCode()); final java.lang.Object $fieldLocatorFactory = this.fieldLocatorFactory; result = result * PRIME + ($fieldLocatorFactory == null ? 43 : $fieldLocatorFactory.hashCode()); return result; } } } /** * A field name extractor is responsible for determining a field name to a method that is implemented * to access this method. */ public interface FieldNameExtractor { /** * Extracts a field name to be accessed by a getter or setter method. * * @param methodDescription The method for which a field name is to be determined. * @return The name of the field to be accessed by this method. */ String resolve(MethodDescription methodDescription); /** * A {@link FieldAccessor.FieldNameExtractor} that determines a field name * according to the rules of Java bean naming conventions. */ enum ForBeanProperty implements FieldNameExtractor { /** * The singleton instance. */ INSTANCE; @Override public String resolve(MethodDescription methodDescription) { String name = methodDescription.getInternalName(); int crop; if (name.startsWith("get") || name.startsWith("set")) { crop = 3; } else if (name.startsWith("is")) { crop = 2; } else { throw new IllegalArgumentException(methodDescription + " does not follow Java bean naming conventions"); } name = name.substring(crop); if (name.length() == 0) { throw new IllegalArgumentException(methodDescription + " does not specify a bean name"); } return Character.toLowerCase(name.charAt(0)) + name.substring(1); } } /** * A field name extractor that returns a fixed value. */ class ForFixedValue implements FieldNameExtractor { /** * The name to return. */ private final String name; /** * Creates a new field name extractor for a fixed value. * * @param name The name to return. */ protected ForFixedValue(String name) { this.name = name; } @Override public String resolve(MethodDescription methodDescription) { return name; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof FieldAccessor.FieldNameExtractor.ForFixedValue)) return false; final FieldAccessor.FieldNameExtractor.ForFixedValue other = (FieldAccessor.FieldNameExtractor.ForFixedValue) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$name = this.name; final java.lang.Object other$name = other.name; if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof FieldAccessor.FieldNameExtractor.ForFixedValue; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $name = this.name; result = result * PRIME + ($name == null ? 43 : $name.hashCode()); return result; } } } /** * A field accessor that allows to define the access to be a field write of a given argument. */ public interface PropertyConfigurable extends Implementation { /** * Creates a field accessor for the described field that serves as a setter for the supplied parameter index. The instrumented * method must return {@code void} or a chained instrumentation must be supplied. * * @param index The index of the parameter for which to set the field's value. * @return An instrumentation that sets the parameter's value to the described field. */ Implementation.Composable setsArgumentAt(int index); } /** * A field accessor that can be configured to use a given assigner and runtime type use configuration. */ public interface AssignerConfigurable extends PropertyConfigurable { /** * Returns a field accessor that is identical to this field accessor but uses the given assigner * and runtime type use configuration. * * @param assigner The assigner to use. * @param typing Indicates if dynamic type castings should be attempted for incompatible assignments. * @return This field accessor with the given assigner and runtime type use configuration. */ PropertyConfigurable withAssigner(Assigner assigner, Assigner.Typing typing); } /** * A field accessor that can be configured to locate a field in a specific manner. */ public interface OwnerTypeLocatable extends AssignerConfigurable { /** * Determines that a field should only be considered when it was defined in a given type. * * @param type The type to be considered. * @return This field accessor which will only considered fields that are defined in the given type. */ AssignerConfigurable in(Class<?> type); /** * Determines that a field should only be considered when it was defined in a given type. * * @param typeDescription A description of the type to be considered. * @return This field accessor which will only considered fields that are defined in the given type. */ AssignerConfigurable in(TypeDescription typeDescription); /** * Determines that a field should only be considered when it was identified by a field locator that is * produced by the given factory. * * @param fieldLocatorFactory A factory that will produce a field locator that will be used to find locate * a field to be accessed. * @return This field accessor which will only considered fields that are defined in the given type. */ AssignerConfigurable in(FieldLocator.Factory fieldLocatorFactory); } /** * A field accessor for an implicit property where a getter or setter property is infered from the signature. */ protected static class ForImplicitProperty extends FieldAccessor implements OwnerTypeLocatable { /** * Creates a field accessor for an implicit property. * * @param fieldLocation The field's location. */ protected ForImplicitProperty(FieldLocation fieldLocation) { this(fieldLocation, Assigner.DEFAULT, Assigner.Typing.STATIC); } /** * Creates a field accessor for an implicit property. * * @param fieldLocation The field's location. * @param assigner The assigner to use. * @param typing The typing to use. */ private ForImplicitProperty(FieldLocation fieldLocation, Assigner assigner, Assigner.Typing typing) { super(fieldLocation, assigner, typing); } @Override public ByteCodeAppender appender(Target implementationTarget) { return new Appender(fieldLocation.prepare(implementationTarget.getInstrumentedType())); } @Override public Composable setsArgumentAt(int index) { if (index < 0) { throw new IllegalArgumentException("A parameter index cannot be negative: " + index); } return new ForParameterSetter(fieldLocation, assigner, typing, index); } @Override public PropertyConfigurable withAssigner(Assigner assigner, Assigner.Typing typing) { return new ForImplicitProperty(fieldLocation, assigner, typing); } @Override public AssignerConfigurable in(Class<?> type) { return in(new TypeDescription.ForLoadedType(type)); } @Override public AssignerConfigurable in(TypeDescription typeDescription) { return in(new FieldLocator.ForExactType.Factory(typeDescription)); } @Override public AssignerConfigurable in(FieldLocator.Factory fieldLocatorFactory) { return new ForImplicitProperty(fieldLocation.with(fieldLocatorFactory), assigner, typing); } /** * An byte code appender for an field accessor implementation. */ protected class Appender implements ByteCodeAppender { /** * The field's location. */ private final FieldLocation.Prepared fieldLocation; /** * Creates a new byte code appender for a field accessor implementation. * * @param fieldLocation The field's location. */ protected Appender(FieldLocation.Prepared fieldLocation) { this.fieldLocation = fieldLocation; } @Override public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) { if (!instrumentedMethod.isMethod()) { throw new IllegalArgumentException(instrumentedMethod + " does not describe a field getter or setter"); } FieldDescription fieldDescription = fieldLocation.resolve(instrumentedMethod); StackManipulation implementation; if (!instrumentedMethod.getReturnType().represents(void.class)) { implementation = new StackManipulation.Compound(getter(fieldDescription, instrumentedMethod), MethodReturn.of(instrumentedMethod.getReturnType())); } else if (instrumentedMethod.getReturnType().represents(void.class) && instrumentedMethod.getParameters().size() == 1) { implementation = new StackManipulation.Compound(setter(fieldDescription, instrumentedMethod.getParameters().get(0)), MethodReturn.VOID); } else { throw new IllegalArgumentException("Method " + implementationContext + " is no bean property"); } return new Size(implementation.apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize()); } private ForImplicitProperty getOuter() { return ForImplicitProperty.this; } // HE: Remove when Lombok support for getOuter is added. @Override public boolean equals(Object object) { if (this == object) return true; if (object == null || getClass() != object.getClass()) return false; Appender appender = (Appender) object; return fieldLocation.equals(appender.fieldLocation) && ForImplicitProperty.this.equals(appender.getOuter()); } // HE: Remove when Lombok support for getOuter is added. /** * Returns the outer instance. * * @return The outer instance. */ @Override public int hashCode() { return fieldLocation.hashCode() + 31 * ForImplicitProperty.this.hashCode(); } } } /** * A field accessor that sets a parameters value of a given index. */ protected static class ForParameterSetter extends FieldAccessor implements Implementation.Composable { /** * The targeted parameter index. */ private final int index; /** * The termination handler to apply. */ private final TerminationHandler terminationHandler; /** * Creates a new field accessor. * * @param fieldLocation The field's location. * @param assigner The assigner to use. * @param typing Indicates if dynamic type castings should be attempted for incompatible assignments. * @param index The targeted parameter index. */ protected ForParameterSetter(FieldLocation fieldLocation, Assigner assigner, Assigner.Typing typing, int index) { this(fieldLocation, assigner, typing, index, TerminationHandler.RETURNING); } /** * Creates a new field accessor. * * @param fieldLocation The field's location. * @param assigner The assigner to use. * @param typing Indicates if dynamic type castings should be attempted for incompatible assignments. * @param index The targeted parameter index. * @param terminationHandler The termination handler to apply. */ private ForParameterSetter(FieldLocation fieldLocation, Assigner assigner, Assigner.Typing typing, int index, TerminationHandler terminationHandler) { super(fieldLocation, assigner, typing); this.index = index; this.terminationHandler = terminationHandler; } @Override public ByteCodeAppender appender(Target implementationTarget) { return new Appender(fieldLocation.prepare(implementationTarget.getInstrumentedType())); } @Override public Implementation andThen(Implementation implementation) { return new Compound(new ForParameterSetter(fieldLocation, assigner, typing, index, TerminationHandler.NON_OPERATIONAL), implementation); } /** * A termination handler is responsible for handling a field accessor's return. */ protected enum TerminationHandler { /** * Returns {@code void} or throws an exception if this is not the return type of the instrumented method. */ RETURNING { @Override protected StackManipulation resolve(MethodDescription instrumentedMethod) { if (!instrumentedMethod.getReturnType().represents(void.class)) { throw new IllegalStateException("Cannot implement setter with return value for " + instrumentedMethod); } return MethodReturn.VOID; } }, /** * Does not return from the method at all. */ NON_OPERATIONAL { @Override protected StackManipulation resolve(MethodDescription instrumentedMethod) { return StackManipulation.Trivial.INSTANCE; } }; /** * Resolves the return instruction. * * @param instrumentedMethod The instrumented method. * @return An appropriate stack manipulation. */ protected abstract StackManipulation resolve(MethodDescription instrumentedMethod); } /** * An appender for a field accessor that sets a parameter of a given index. */ protected class Appender implements ByteCodeAppender { /** * The field's location. */ private final FieldLocation.Prepared fieldLocation; /** * Creates a new byte code appender for a field accessor implementation. * * @param fieldLocation The field's location. */ protected Appender(FieldLocation.Prepared fieldLocation) { this.fieldLocation = fieldLocation; } @Override public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) { if (instrumentedMethod.getParameters().size() <= index) { throw new IllegalStateException(instrumentedMethod + " does not define a parameter with index " + index); } else { return new Size(new StackManipulation.Compound(setter(fieldLocation.resolve(instrumentedMethod), instrumentedMethod.getParameters().get(index)), terminationHandler.resolve(instrumentedMethod)).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize()); } } /** * Returns the outer instance. * * @return The outer instance. */ private ForParameterSetter getOuter() { return ForParameterSetter.this; } // HE: Remove when Lombok support for getOuter is added. @Override public boolean equals(Object object) { if (this == object) return true; if (object == null || getClass() != object.getClass()) return false; ForParameterSetter.Appender appender = (ForParameterSetter.Appender) object; return fieldLocation.equals(appender.fieldLocation) && ForParameterSetter.this.equals(appender.getOuter()); } // HE: Remove when Lombok support for getOuter is added. @Override public int hashCode() { return fieldLocation.hashCode() + 31 * ForParameterSetter.this.hashCode(); } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof FieldAccessor.ForParameterSetter)) return false; final FieldAccessor.ForParameterSetter other = (FieldAccessor.ForParameterSetter) o; if (!other.canEqual((java.lang.Object) this)) return false; if (!super.equals(o)) return false; if (this.index != other.index) return false; final java.lang.Object this$terminationHandler = this.terminationHandler; final java.lang.Object other$terminationHandler = other.terminationHandler; if (this$terminationHandler == null ? other$terminationHandler != null : !this$terminationHandler.equals(other$terminationHandler)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof FieldAccessor.ForParameterSetter; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; result = result * PRIME + super.hashCode(); result = result * PRIME + this.index; final java.lang.Object $terminationHandler = this.terminationHandler; result = result * PRIME + ($terminationHandler == null ? 43 : $terminationHandler.hashCode()); return result; } } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public boolean equals(final java.lang.Object o) { if (o == this) return true; if (!(o instanceof FieldAccessor)) return false; final FieldAccessor other = (FieldAccessor) o; if (!other.canEqual((java.lang.Object) this)) return false; final java.lang.Object this$fieldLocation = this.fieldLocation; final java.lang.Object other$fieldLocation = other.fieldLocation; if (this$fieldLocation == null ? other$fieldLocation != null : !this$fieldLocation.equals(other$fieldLocation)) return false; final java.lang.Object this$assigner = this.assigner; final java.lang.Object other$assigner = other.assigner; if (this$assigner == null ? other$assigner != null : !this$assigner.equals(other$assigner)) return false; final java.lang.Object this$typing = this.typing; final java.lang.Object other$typing = other.typing; if (this$typing == null ? other$typing != null : !this$typing.equals(other$typing)) return false; return true; } @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") protected boolean canEqual(final java.lang.Object other) { return other instanceof FieldAccessor; } @java.lang.Override @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") public int hashCode() { final int PRIME = 59; int result = 1; final java.lang.Object $fieldLocation = this.fieldLocation; result = result * PRIME + ($fieldLocation == null ? 43 : $fieldLocation.hashCode()); final java.lang.Object $assigner = this.assigner; result = result * PRIME + ($assigner == null ? 43 : $assigner.hashCode()); final java.lang.Object $typing = this.typing; result = result * PRIME + ($typing == null ? 43 : $typing.hashCode()); return result; } }