/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { if (instrumentedMethod.isStatic()) { throw new IllegalStateException("Hash code method must not be static: " + instrumentedMethod); } else if (!instrumentedMethod.getReturnType().represents(int.class)) { throw new IllegalStateException("Hash code method does not return primitive integer: " + instrumentedMethod); } List<StackManipulation> stackManipulations = new ArrayList<StackManipulation>(2 + fieldDescriptions.size() * 8); stackManipulations.add(initialValue); int padding = 0; for (FieldDescription.InDefinedShape fieldDescription : fieldDescriptions) { stackManipulations.add(IntegerConstant.forValue(multiplier)); stackManipulations.add(Multiplication.INTEGER); stackManipulations.add(MethodVariableAccess.loadThis()); stackManipulations.add(FieldAccess.forField(fieldDescription).read()); NullValueGuard nullValueGuard = fieldDescription.getType().isPrimitive() || fieldDescription.getType().isArray() || nonNullable.matches(fieldDescription) ? NullValueGuard.NoOp.INSTANCE : new NullValueGuard.UsingJump(instrumentedMethod); stackManipulations.add(nullValueGuard.before()); stackManipulations.add(ValueTransformer.of(fieldDescription.getType())); stackManipulations.add(Addition.INTEGER); stackManipulations.add(nullValueGuard.after()); padding = Math.max(padding, nullValueGuard.getRequiredVariablePadding()); } stackManipulations.add(MethodReturn.INTEGER); return new Size(new StackManipulation.Compound(stackManipulations).apply(methodVisitor, implementationContext).getMaximalSize(), instrumentedMethod.getStackSize() + padding); } }
/** * {@inheritDoc} */ public AnnotationAppender onNonGenericType(TypeDescription.Generic typeDescription) { StringBuilder typePath = new StringBuilder(this.typePath); for (int index = 0; index < typeDescription.asErasure().getInnerClassCount(); index++) { typePath = typePath.append(INNER_CLASS_PATH); } AnnotationAppender annotationAppender = apply(typeDescription, typePath.toString()); if (typeDescription.isArray()) { annotationAppender = typeDescription.getComponentType().accept(new ForTypeAnnotations(annotationAppender, annotationValueFilter, typeReference, this.typePath + COMPONENT_TYPE_PATH)); // Impossible to be inner class } return annotationAppender; }
stackManipulations.add(TypeCasting.to(instrumentedType)); stackManipulations.add(FieldAccess.forField(fieldDescription).read()); NullValueGuard nullValueGuard = fieldDescription.getType().isPrimitive() || fieldDescription.getType().isArray() || nonNullable.matches(fieldDescription) ? NullValueGuard.NoOp.INSTANCE : new NullValueGuard.UsingJump(instrumentedMethod);
/** * Append a referency type * * @param type Type to append * @param nullable Nullness of type * @param output Output to append to * @param <A> Type of output * @return Supplied output to append to */ public <A extends Appendable> A appendReferenceTypeSignature(Generic type, Nullness nullable, A output) { try { if (type.isArray()) { appendArrayTypeSignature(type, nullable, output); } else if (type.getSort() == Sort.VARIABLE) { appendTypeVariableSignature(type, nullable, output); } else { appendClassTypeSignature(type, nullable, output); } return output; } catch (Exception e) { throw new RuntimeException(String.format("Could not write reference type signature %s", type)); } }
@Override public final boolean matches(final TypeDescription target) { return target.getDeclaredFields() .filter(not(isSynthetic())) .filter(f -> f.getType().isArray()) .isEmpty(); } }
if (target.getType().represents(Object.class)) { componentType = TypeDescription.Generic.OBJECT; } else if (target.getType().isArray()) { componentType = target.getType().getComponentType(); } else {
/** * {@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)); }
/** * {@inheritDoc} */ public MethodDelegationBinder.ParameterBinding<?> bind(AnnotationDescription.Loadable<Super> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { if (target.getType().isPrimitive() || target.getType().isArray()) { throw new IllegalStateException(target + " uses the @Super annotation on an invalid type"); } TypeDescription proxyType = TypeLocator.ForType .of(annotation.getValue(PROXY_TYPE).resolve(TypeDescription.class)) .resolve(implementationTarget.getInstrumentedType(), target.getType()); if (proxyType.isFinal()) { throw new IllegalStateException("Cannot extend final type as @Super proxy: " + proxyType); } else if (source.isStatic() || !implementationTarget.getInstrumentedType().isAssignableTo(proxyType)) { return MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } else { return new MethodDelegationBinder.ParameterBinding.Anonymous(annotation .getValue(STRATEGY).resolve(EnumerationDescription.class).load(Instantiation.class) .proxyFor(proxyType, implementationTarget, annotation)); } }
/** * {@inheritDoc} */ public FieldDescription resolve(TypeDescription targetType, ByteCodeElement target, TypeList.Generic parameters, TypeDescription.Generic result) { if (parameters.isEmpty()) { throw new IllegalStateException("Cannot substitute parameterless instruction with " + target); } else if (parameters.get(0).isPrimitive() || parameters.get(0).isArray()) { throw new IllegalStateException("Cannot access field on primitive or array type for " + target); } TypeDefinition current = parameters.get(0); do { FieldList<?> fields = current.getDeclaredFields().filter(not(isStatic()).<FieldDescription>and(isVisibleTo(instrumentedType)).and(matcher)); if (fields.size() == 1) { return fields.getOnly(); } else if (fields.size() > 1) { throw new IllegalStateException("Ambiguous field location of " + fields); } current = current.getSuperClass(); } while (current != null); throw new IllegalStateException("Cannot locate field matching " + matcher + " on " + targetType); } }
/** * {@inheritDoc} */ public MethodDelegationBinder.ParameterBinding<?> bind(AnnotationDescription.Loadable<This> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner, Assigner.Typing typing) { if (target.getType().isPrimitive()) { throw new IllegalStateException(target + " uses a primitive type with a @This annotation"); } else if (target.getType().isArray()) { throw new IllegalStateException(target + " uses an array type with a @This annotation"); } else if (source.isStatic() && !annotation.loadSilent().optional()) { return MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } return new MethodDelegationBinder.ParameterBinding.Anonymous(source.isStatic() ? NullConstant.INSTANCE : new StackManipulation.Compound(MethodVariableAccess.loadThis(), assigner.assign(implementationTarget.getInstrumentedType().asGenericType(), target.getType(), typing))); } }
/** * {@inheritDoc} */ public MethodDescription resolve(TypeDescription targetType, ByteCodeElement target, TypeList.Generic parameters, TypeDescription.Generic result) { if (parameters.isEmpty()) { throw new IllegalStateException("Cannot substitute parameterless instruction with " + target); } else if (parameters.get(0).isPrimitive() || parameters.get(0).isArray()) { throw new IllegalStateException("Cannot invoke method on primitive or array type for " + target); } TypeDefinition typeDefinition = parameters.get(0); List<MethodDescription> candidates = CompoundList.<MethodDescription>of(methodGraphCompiler.compile(typeDefinition, instrumentedType) .listNodes() .asMethodList() .filter(matcher), typeDefinition.getDeclaredMethods().filter(isPrivate().<MethodDescription>and(isVisibleTo(instrumentedType)).and(matcher))); if (candidates.size() == 1) { return candidates.get(0); } else { throw new IllegalStateException("Not exactly one method that matches " + matcher + ": " + candidates); } } }
/** * {@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 List<ArgumentLoader> resolve(MethodDescription instrumentedMethod, MethodDescription invokedMethod) { if (instrumentedMethod.getParameters().size() <= index) { throw new IllegalStateException(instrumentedMethod + " does not declare a parameter with index " + index); } else if (!instrumentedMethod.getParameters().get(index).getType().isArray()) { throw new IllegalStateException("Cannot access an item from non-array parameter " + instrumentedMethod.getParameters().get(index)); } List<ArgumentLoader> argumentLoaders = new ArrayList<ArgumentLoader>(instrumentedMethod.getParameters().size()); for (int index = 0; index < invokedMethod.getParameters().size(); index++) { argumentLoaders.add(new ForMethodParameterArrayElement(instrumentedMethod.getParameters().get(this.index), index++)); } return argumentLoaders; } }
/** * {@inheritDoc} */ public SignatureVisitor onNonGenericType(Generic typeDescription) { if (typeDescription.isArray()) { typeDescription.getComponentType().accept(new ForSignatureVisitor(signatureVisitor.visitArrayType())); } else if (typeDescription.isPrimitive()) { signatureVisitor.visitBaseType(typeDescription.asErasure().getDescriptor().charAt(ONLY_CHARACTER)); } else { signatureVisitor.visitClassType(typeDescription.asErasure().getInternalName()); signatureVisitor.visitEnd(); } return signatureVisitor; }
/** * {@inheritDoc} */ public Boolean onNonGenericType(Generic typeDescription) { return (acceptsArray || !typeDescription.isArray()) && (acceptsPrimitive || !typeDescription.isPrimitive()) && (acceptsVoid || !typeDescription.represents(void.class)); }
/** * {@inheritDoc} */ public List<ArgumentLoader> resolve(MethodDescription instrumentedMethod, MethodDescription invokedMethod) { if (instrumentedMethod.getParameters().size() <= index) { throw new IllegalStateException(instrumentedMethod + " does not declare a parameter with index " + index); } else if (!instrumentedMethod.getParameters().get(index).getType().isArray()) { throw new IllegalStateException("Cannot access an item from non-array parameter " + instrumentedMethod.getParameters().get(index)); } return Collections.<ArgumentLoader>singletonList(new ForMethodParameterArrayElement(instrumentedMethod.getParameters().get(index), arrayIndex)); } }
/** * {@inheritDoc} */ public Generic onNonGenericType(Generic typeDescription) { return typeDescription.isArray() ? new OfGenericArray.Latent(typeDescription.getComponentType().accept(this), typeDescription) : onSimpleType(typeDescription); }
/** * {@inheritDoc} */ public Boolean onNonGenericType(Generic typeDescription) { return typeDescription.isArray() && genericArray.getComponentType().accept(Assigner.INSTANCE).isAssignableFrom(typeDescription.getComponentType()); } }
/** * {@inheritDoc} */ public Boolean onNonGenericType(Generic typeDescription) { return isValid(typeDescription) && (!typeDescription.isArray() || typeDescription.getComponentType().accept(this)); }
/** * {@inheritDoc} */ public Generic onNonGenericType(Generic typeDescription) { return typeDescription.isArray() ? new OfGenericArray.Latent(onNonGenericType(typeDescription.getComponentType()), Empty.INSTANCE) : new OfNonGenericType.Latent(typeDescription.asErasure(), Empty.INSTANCE); }