@Override protected Map<Integer, TypeDefinition> resolveInitializationTypes(ArgumentHandler argumentHandler) { return adviceMethod.getReturnType().represents(void.class) ? Collections.<Integer, TypeDefinition>emptyMap() : Collections.<Integer, TypeDefinition>singletonMap(argumentHandler.exit(), adviceMethod.getReturnType()); }
@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; } },
/** * {@inheritDoc} */ public OffsetMapping make(ParameterDescription.InDefinedShape target, AnnotationDescription.Loadable<StubValue> annotation, AdviceType adviceType) { if (!target.getType().represents(Object.class)) { throw new IllegalStateException("Cannot use StubValue on non-Object parameter type " + target); } else { return this; } } }
/** * {@inheritDoc} */ public StackManipulation resolve(TypeDescription targetType, ByteCodeElement target, TypeList.Generic parameters, TypeDescription.Generic result) { FieldDescription fieldDescription = fieldResolver.resolve(targetType, target, parameters, result); if (!fieldDescription.isAccessibleTo(instrumentedType)) { throw new IllegalStateException(instrumentedType + " cannot access " + fieldDescription); } else if (result.represents(void.class)) { if (parameters.size() != (fieldDescription.isStatic() ? 1 : 2)) { throw new IllegalStateException("Cannot set " + fieldDescription + " with " + parameters); } else if (!fieldDescription.isStatic() && !parameters.get(0).asErasure().isAssignableTo(fieldDescription.getDeclaringType().asErasure())) { throw new IllegalStateException("Cannot set " + fieldDescription + " on " + parameters.get(0)); } else if (!parameters.get(fieldDescription.isStatic() ? 0 : 1).asErasure().isAssignableTo(fieldDescription.getType().asErasure())) { throw new IllegalStateException("Cannot set " + fieldDescription + " to " + parameters.get(fieldDescription.isStatic() ? 0 : 1)); } return FieldAccess.forField(fieldDescription).write(); } else { if (parameters.size() != (fieldDescription.isStatic() ? 0 : 1)) { throw new IllegalStateException("Cannot set " + fieldDescription + " with " + parameters); } else if (!fieldDescription.isStatic() && !parameters.get(0).asErasure().isAssignableTo(fieldDescription.getDeclaringType().asErasure())) { throw new IllegalStateException("Cannot get " + fieldDescription + " on " + parameters.get(0)); } else if (!fieldDescription.getType().asErasure().isAssignableTo(result.asErasure())) { throw new IllegalStateException("Cannot get " + fieldDescription + " as " + result); } return FieldAccess.forField(fieldDescription).read(); } }
/** * {@inheritDoc} */ public StackManipulation toStackManipulation(ParameterDescription target, Assigner assigner, Assigner.Typing typing) { TypeDescription.Generic componentType; if (target.getType().represents(Object.class)) { componentType = TypeDescription.Generic.OBJECT; } else if (target.getType().isArray()) { componentType = target.getType().getComponentType(); } else { throw new IllegalStateException("Cannot set method parameter array for non-array type: " + target); } List<StackManipulation> stackManipulations = new ArrayList<StackManipulation>(parameters.size()); for (ParameterDescription parameter : parameters) { StackManipulation stackManipulation = new StackManipulation.Compound( MethodVariableAccess.load(parameter), assigner.assign(parameter.getType(), componentType, typing) ); if (stackManipulation.isValid()) { stackManipulations.add(stackManipulation); } else { throw new IllegalStateException("Cannot assign " + parameter + " to " + componentType); } } return new StackManipulation.Compound(ArrayFactory.forType(componentType).withValues(stackManipulations)); }
/** * Locates a primitive unboxing delegate for a given primitive type. * * @param typeDescription A description of the primitive type. * @return A corresponding primitive unboxing delegate. */ protected static PrimitiveUnboxingDelegate forPrimitive(TypeDescription.Generic typeDescription) { if (typeDescription.represents(boolean.class)) { return BOOLEAN; } else if (typeDescription.represents(byte.class)) { return BYTE; } else if (typeDescription.represents(short.class)) { return SHORT; } else if (typeDescription.represents(char.class)) { return CHARACTER; } else if (typeDescription.represents(int.class)) { return INTEGER; } else if (typeDescription.represents(long.class)) { return LONG; } else if (typeDescription.represents(float.class)) { return FLOAT; } else if (typeDescription.represents(double.class)) { return DOUBLE; } else { throw new IllegalArgumentException("Expected non-void primitive type instead of " + typeDescription); } }
/** * {@inheritDoc} */ public Target resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, ArgumentHandler argumentHandler, Sort sort) { StackManipulation readAssignment = assigner.assign(instrumentedMethod.getReturnType(), target, typing); if (!readAssignment.isValid()) { throw new IllegalStateException("Cannot assign " + instrumentedMethod.getReturnType() + " to " + target); } else if (readOnly) { return instrumentedMethod.getReturnType().represents(void.class) ? new Target.ForDefaultValue.ReadOnly(target) : new Target.ForVariable.ReadOnly(instrumentedMethod.getReturnType(), argumentHandler.returned(), readAssignment); } else { StackManipulation writeAssignment = assigner.assign(target, instrumentedMethod.getReturnType(), typing); if (!writeAssignment.isValid()) { throw new IllegalStateException("Cannot assign " + target + " to " + instrumentedMethod.getReturnType()); } return instrumentedMethod.getReturnType().represents(void.class) ? new Target.ForDefaultValue.ReadWrite(target) : new Target.ForVariable.ReadWrite(instrumentedMethod.getReturnType(), argumentHandler.returned(), readAssignment, writeAssignment); } }
/** * {@inheritDoc} */ public void apply(MethodVisitor methodVisitor) { if (instrumentedMethod.getReturnType().represents(boolean.class) || instrumentedMethod.getReturnType().represents(byte.class) || instrumentedMethod.getReturnType().represents(short.class) || instrumentedMethod.getReturnType().represents(char.class) || instrumentedMethod.getReturnType().represents(int.class)) { methodVisitor.visitInsn(Opcodes.ICONST_0); } else if (instrumentedMethod.getReturnType().represents(long.class)) { methodVisitor.visitInsn(Opcodes.LCONST_0); } else if (instrumentedMethod.getReturnType().represents(float.class)) { methodVisitor.visitInsn(Opcodes.FCONST_0); } else if (instrumentedMethod.getReturnType().represents(double.class)) { methodVisitor.visitInsn(Opcodes.DCONST_0); } else if (!instrumentedMethod.getReturnType().represents(void.class)) { methodVisitor.visitInsn(Opcodes.ACONST_NULL); } methodVisitor.visitJumpInsn(Opcodes.GOTO, returnHandler); }
@Override protected void onUserReturn() { if (instrumentedMethod.getReturnType().represents(boolean.class) || instrumentedMethod.getReturnType().represents(byte.class) || instrumentedMethod.getReturnType().represents(short.class) || instrumentedMethod.getReturnType().represents(char.class) || instrumentedMethod.getReturnType().represents(int.class)) { stackMapFrameHandler.injectReturnFrame(methodVisitor); methodVisitor.visitVarInsn(Opcodes.ISTORE, argumentHandler.returned()); } else if (instrumentedMethod.getReturnType().represents(long.class)) { stackMapFrameHandler.injectReturnFrame(methodVisitor); methodVisitor.visitVarInsn(Opcodes.LSTORE, argumentHandler.returned()); } else if (instrumentedMethod.getReturnType().represents(float.class)) { stackMapFrameHandler.injectReturnFrame(methodVisitor); methodVisitor.visitVarInsn(Opcodes.FSTORE, argumentHandler.returned()); } else if (instrumentedMethod.getReturnType().represents(double.class)) { stackMapFrameHandler.injectReturnFrame(methodVisitor); methodVisitor.visitVarInsn(Opcodes.DSTORE, argumentHandler.returned()); } else if (!instrumentedMethod.getReturnType().represents(void.class)) { stackMapFrameHandler.injectReturnFrame(methodVisitor); methodVisitor.visitVarInsn(Opcodes.ASTORE, argumentHandler.returned()); } }
/** * {@inheritDoc} */ public StackManipulation assign(TypeDescription.Generic source, TypeDescription.Generic target, Typing typing) { if (source.represents(void.class) && target.represents(void.class)) { return StackManipulation.Trivial.INSTANCE; } else if (source.represents(void.class) /* && target != void.class */) { return typing.isDynamic() ? DefaultValue.of(target) : StackManipulation.Illegal.INSTANCE; } else if (/* source != void.class && */ target.represents(void.class)) { return Removal.of(source); } else /* source != void.class && target != void.class */ { return chained.assign(source, target, typing); } } }
/** * {@inheritDoc} */ public MethodDelegationBinder.ParameterBinding<?> bind(AnnotationDescription.Loadable<StubValue> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { if (!target.getType().represents(Object.class)) { throw new IllegalStateException(target + " uses StubValue annotation on non-Object type"); } return new MethodDelegationBinder.ParameterBinding.Anonymous(source.getReturnType().represents(void.class) ? NullConstant.INSTANCE : new StackManipulation.Compound(DefaultValue.of(source.getReturnType().asErasure()), assigner.assign(source.getReturnType(), TypeDescription.Generic.OBJECT, typing))); } }
/** * {@inheritDoc} */ public OffsetMapping make(ParameterDescription.InDefinedShape target, AnnotationDescription.Loadable<AllArguments> annotation, AdviceType adviceType) { if (!target.getType().represents(Object.class) && !target.getType().isArray()) { throw new IllegalStateException("Cannot use AllArguments annotation on a non-array type"); } else if (adviceType.isDelegation() && !annotation.loadSilent().readOnly()) { throw new IllegalStateException("Cannot define writable field access for " + target); } else { return new ForAllArguments(target.getType().represents(Object.class) ? TypeDescription.Generic.OBJECT : target.getType().getComponentType(), annotation.loadSilent()); } } }
/** * {@inheritDoc} */ public void injectReturnFrame(MethodVisitor methodVisitor) { if (!expandFrames && currentFrameDivergence == 0) { if (adviceMethod.getReturnType().represents(void.class)) { methodVisitor.visitFrame(Opcodes.F_SAME, EMPTY.length, EMPTY, EMPTY.length, EMPTY); } else { methodVisitor.visitFrame(Opcodes.F_SAME1, EMPTY.length, EMPTY, 1, new Object[]{toFrame(adviceMethod.getReturnType().asErasure())}); } } else { injectFullFrame(methodVisitor, startTypes, adviceMethod.getReturnType().represents(void.class) ? Collections.<TypeDescription>emptyList() : Collections.singletonList(adviceMethod.getReturnType().asErasure())); } }
/** * {@inheritDoc} */ public void injectReturnFrame(MethodVisitor methodVisitor) { if (!expandFrames && currentFrameDivergence == 0) { if (instrumentedMethod.getReturnType().represents(void.class)) { methodVisitor.visitFrame(Opcodes.F_SAME, EMPTY.length, EMPTY, EMPTY.length, EMPTY); } else { methodVisitor.visitFrame(Opcodes.F_SAME1, EMPTY.length, EMPTY, 1, new Object[]{toFrame(instrumentedMethod.getReturnType().asErasure())}); } } else { injectFullFrame(methodVisitor, CompoundList.of(initialTypes, preMethodTypes), instrumentedMethod.getReturnType().represents(void.class) ? Collections.<TypeDescription>emptyList() : Collections.singletonList(instrumentedMethod.getReturnType().asErasure())); } }
/** * {@inheritDoc} */ public SignatureVisitor onWildcard(Generic wildcard) { TypeList.Generic upperBounds = wildcard.getUpperBounds(), lowerBounds = wildcard.getLowerBounds(); if (lowerBounds.isEmpty() && upperBounds.getOnly().represents(Object.class)) { signatureVisitor.visitTypeArgument(); } else if (!lowerBounds.isEmpty() /* && upperBounds.isEmpty() */) { lowerBounds.getOnly().accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.SUPER))); } else /* if (!upperBounds.isEmpty() && lowerBounds.isEmpty()) */ { upperBounds.getOnly().accept(new ForSignatureVisitor(signatureVisitor.visitTypeArgument(SignatureVisitor.EXTENDS))); } return signatureVisitor; }
/** * {@inheritDoc} */ public boolean represents(java.lang.reflect.Type type) { return resolve().represents(type); }
/** * {@inheritDoc} */ public Boolean onNonGenericType(Generic typeDescription) { return (acceptsArray || !typeDescription.isArray()) && (acceptsPrimitive || !typeDescription.isPrimitive()) && (acceptsVoid || !typeDescription.represents(void.class)); }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { if (!instrumentedMethod.getReturnType().represents(void.class)) { throw new IllegalStateException("Instrumented method " + instrumentedMethod + " does not return void for field setting method call"); } return new Size(MethodReturn.VOID.apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize()); } }
@Override protected Generic onSimpleType(Generic typeDescription) { return typeDescription.represents(TargetType.class) ? new OfNonGenericType.Latent(this.typeDescription, typeDescription) : typeDescription; }
@Override protected Generic onSimpleType(Generic typeDescription) { return typeDescription.represents(TargetType.class) ? new OfNonGenericType.Latent(declaringType, typeDescription) : typeDescription; } }