@Override protected boolean isRepresentable(MethodDescription instrumentedMethod) { return instrumentedMethod.isConstructor(); } },
@Override protected boolean isSort(MethodDescription target) { return target.isConstructor(); } },
@Override public boolean isPremature(MethodDescription methodDescription) { return methodDescription.isConstructor(); } },
/** * {@inheritDoc} */ public boolean isConstructor() { return methodDescription.isConstructor(); }
@Override protected boolean isPossibleThisFrameValue(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Object frame) { return instrumentedMethod.isConstructor() ? Opcodes.UNINITIALIZED_THIS.equals(frame) : toFrame(instrumentedType).equals(frame); } },
@Override protected boolean isPossibleThisFrameValue(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Object frame) { return instrumentedMethod.isConstructor() && Opcodes.UNINITIALIZED_THIS.equals(frame) || toFrame(instrumentedType).equals(frame); } },
/** * Invokes the given constructor in order to create an instance. * * @param methodDescription A description of the constructor to invoke. * @return A method call that invokes the given constructor without providing any arguments. */ public static MethodCall construct(MethodDescription methodDescription) { if (!methodDescription.isConstructor()) { throw new IllegalArgumentException("Not a constructor: " + methodDescription); } return new MethodCall(new MethodLocator.ForExplicitMethod(methodDescription), TargetHandler.ForConstructingInvocation.Factory.INSTANCE, Collections.<ArgumentLoader.Factory>emptyList(), MethodInvoker.ForContextualInvocation.Factory.INSTANCE, TerminationHandler.Simple.RETURNING, Assigner.DEFAULT, Assigner.Typing.STATIC); }
/** {@inheritDoc} */ public StackManipulation resolve(Assigner assigner, Assigner.Typing typing, MethodDescription source, MethodDescription target) { return Removal.of(target.isConstructor() ? target.getDeclaringType() : target.getReturnType()); } };
/** * {@inheritDoc} */ public StackManipulation toStackManipulation(MethodDescription invokedMethod, Assigner assigner, Assigner.Typing typing) { if (instrumentedMethod.isStatic() && !invokedMethod.isStatic() && !invokedMethod.isConstructor()) { throw new IllegalStateException("Cannot invoke " + invokedMethod + " from " + instrumentedMethod); } else if (invokedMethod.isConstructor() && (!instrumentedMethod.isConstructor() || !instrumentedType.equals(invokedMethod.getDeclaringType().asErasure()) && !instrumentedType.getSuperClass().asErasure().equals(invokedMethod.getDeclaringType().asErasure()))) { throw new IllegalStateException("Cannot invoke " + invokedMethod + " from " + instrumentedMethod + " in " + instrumentedType); } return new StackManipulation.Compound( invokedMethod.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), invokedMethod.isConstructor() ? Duplication.SINGLE : StackManipulation.Trivial.INSTANCE ); } }
/** * {@inheritDoc} */ public StackManipulation toStackManipulation(MethodDescription invokedMethod, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) { return Removal.of(invokedMethod.isConstructor() ? invokedMethod.getDeclaringType() : invokedMethod.getReturnType()); } },
@Override protected StackManipulation resolve(MethodDescription interceptedMethod, TypeDescription returnType, Assigner assigner, Assigner.Typing typing) { return Removal.of(interceptedMethod.isConstructor() ? interceptedMethod.getDeclaringType() : interceptedMethod.getReturnType()); } };
/** * Returns an auxiliary type for loading the supplied method description as a constant. * * @param methodDescription The method description to represent as a constant. * @return An appropriate auxiliary type. */ public static AuxiliaryType of(MethodDescription methodDescription) { if (methodDescription.isConstructor()) { return methodDescription.isPublic() ? FOR_PUBLIC_CONSTRUCTOR : FOR_DECLARED_CONSTRUCTOR; } else if (methodDescription.isMethod()) { return methodDescription.isPublic() ? FOR_PUBLIC_METHOD : FOR_DECLARED_METHOD; } else { throw new IllegalStateException("Cannot load constant for type initializer: " + methodDescription); } }
/** * {@inheritDoc} */ public int apply(MethodVisitor methodVisitor, int offset) { if (instrumentedMethod.isConstructor()) { throw new IllegalStateException("Cannot skip code execution from constructor: " + instrumentedMethod); } methodVisitor.visitVarInsn(load, offset); convertValue(methodVisitor); Label noSkip = new Label(); methodVisitor.visitJumpInsn(inverted ? nonDefaultJump : defaultJump, noSkip); relocation.apply(methodVisitor); methodVisitor.visitLabel(noSkip); return requiredSize; } }
/** * {@inheritDoc} */ public int apply(MethodVisitor methodVisitor, int offset) { if (instrumentedMethod.isConstructor()) { throw new IllegalStateException("Cannot skip code execution from constructor: " + instrumentedMethod); } methodVisitor.visitVarInsn(Opcodes.ALOAD, offset); methodVisitor.visitTypeInsn(Opcodes.INSTANCEOF, typeDescription.getInternalName()); Label noSkip = new Label(); methodVisitor.visitJumpInsn(Opcodes.IFEQ, noSkip); relocation.apply(methodVisitor); methodVisitor.visitLabel(noSkip); return NO_REQUIRED_SIZE; } }
+ initialTypes.size()]; int index = 0; if (instrumentedMethod.isConstructor()) { localVariable[index++] = Opcodes.UNINITIALIZED_THIS; } else if (!instrumentedMethod.isStatic()) {
@Override protected int copy(TypeDescription instrumentedType, MethodDescription instrumentedMethod, MethodDescription methodDescription, Object[] localVariable, Object[] translated) { int index = 0; if (!instrumentedMethod.isStatic()) { translated[index++] = instrumentedMethod.isConstructor() ? Opcodes.UNINITIALIZED_THIS : toFrame(instrumentedType); } for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) { translated[index++] = toFrame(typeDescription); } return index; }
/** * {@inheritDoc} */ public StackManipulation toStackManipulation(MethodDescription invokedMethod, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) { StackManipulation stackManipulation = assigner.assign(invokedMethod.isConstructor() ? invokedMethod.getDeclaringType().asGenericType() : invokedMethod.getReturnType(), instrumentedMethod.getReturnType(), typing); if (!stackManipulation.isValid()) { throw new IllegalStateException("Cannot return " + invokedMethod.getReturnType() + " from " + instrumentedMethod); } return new StackManipulation.Compound(stackManipulation, MethodReturn.of(instrumentedMethod.getReturnType())); } },
/** {@inheritDoc} */ public StackManipulation resolve(Assigner assigner, Assigner.Typing typing, MethodDescription source, MethodDescription target) { return new StackManipulation.Compound(assigner.assign(target.isConstructor() ? target.getDeclaringType().asGenericType() : target.getReturnType(), source.getReturnType(), typing), MethodReturn.of(source.getReturnType())); } },
/** * Creates a matcher where only overridable or declared methods are matched unless those are ignored. Methods that * are declared by the target type are only matched if they are not ignored. Declared methods that are not found on the * target type are always matched. * * @param ignoredMethods A method matcher that matches any ignored method. * @param originalType The original type of the instrumentation before adding any user methods. * @return A latent method matcher that identifies any method to instrument for a rebasement or redefinition. */ protected static LatentMatcher<MethodDescription> of(LatentMatcher<? super MethodDescription> ignoredMethods, TypeDescription originalType) { ElementMatcher.Junction<MethodDescription> predefinedMethodSignatures = none(); for (MethodDescription methodDescription : originalType.getDeclaredMethods()) { ElementMatcher.Junction<MethodDescription> signature = methodDescription.isConstructor() ? isConstructor() : ElementMatchers.<MethodDescription>named(methodDescription.getName()); signature = signature.and(returns(methodDescription.getReturnType().asErasure())); signature = signature.and(takesArguments(methodDescription.getParameters().asTypeList().asErasures())); predefinedMethodSignatures = predefinedMethodSignatures.or(signature); } return new InliningImplementationMatcher(ignoredMethods, predefinedMethodSignatures); }
/** * {@inheritDoc} */ public MethodDefinition.ImplementationDefinition<S> define(MethodDescription methodDescription) { MethodDefinition.ParameterDefinition.Initial<S> initialParameterDefinition = methodDescription.isConstructor() ? defineConstructor(methodDescription.getModifiers()) : defineMethod(methodDescription.getInternalName(), methodDescription.getReturnType(), methodDescription.getModifiers()); ParameterList<?> parameterList = methodDescription.getParameters(); MethodDefinition.ExceptionDefinition<S> exceptionDefinition; if (parameterList.hasExplicitMetaData()) { MethodDefinition.ParameterDefinition<S> parameterDefinition = initialParameterDefinition; for (ParameterDescription parameter : parameterList) { parameterDefinition = parameterDefinition.withParameter(parameter.getType(), parameter.getName(), parameter.getModifiers()); } exceptionDefinition = parameterDefinition; } else { exceptionDefinition = initialParameterDefinition.withParameters(parameterList.asTypeList()); } MethodDefinition.TypeVariableDefinition<S> typeVariableDefinition = exceptionDefinition.throwing(methodDescription.getExceptionTypes()); for (TypeDescription.Generic typeVariable : methodDescription.getTypeVariables()) { typeVariableDefinition = typeVariableDefinition.typeVariable(typeVariable.getSymbol(), typeVariable.getUpperBounds()); } return typeVariableDefinition; }