@Override
 public AnnotationAppender onParameterizedType(TypeDescription.Generic parameterizedType) {
   StringBuilder typePath = new StringBuilder(this.typePath);
   for (int index = 0; index < parameterizedType.asErasure().getSegmentCount(); index++) {
     typePath = typePath.append(INNER_CLASS_PATH);
   }
   AnnotationAppender annotationAppender = apply(parameterizedType, typePath.toString());
   TypeDescription.Generic ownerType = parameterizedType.getOwnerType();
   if (ownerType != null) {
     annotationAppender =
         ownerType.accept(
             new ForTypeAnnotations(
                 annotationAppender, annotationValueFilter, typeReference, this.typePath));
   }
   int index = 0;
   for (TypeDescription.Generic typeArgument : parameterizedType.getTypeArguments()) {
     annotationAppender =
         typeArgument.accept(
             new ForTypeAnnotations(
                 annotationAppender,
                 annotationValueFilter,
                 typeReference,
                 typePath.toString() + index++ + INDEXED_TYPE_DELIMITER));
   }
   return annotationAppender;
 }
 @Override
 @Before
 @SuppressWarnings("unchecked")
 public void setUp() throws Exception {
   super.setUp();
   when(firstSourceType.getStackSize()).thenReturn(StackSize.SINGLE);
   when(secondSourceType.getStackSize()).thenReturn(StackSize.SINGLE);
   when(componentType.asErasure()).thenReturn(rawComponentType);
   when(targetType.getComponentType()).thenReturn(componentType);
   when(targetType.asErasure()).thenReturn(rawTargetType);
   when(firstSourceType.asGenericType()).thenReturn(firstSourceType);
   when(firstSourceType.accept(any(TypeDescription.Generic.Visitor.class)))
       .thenReturn(firstSourceType);
   when(secondSourceType.asGenericType()).thenReturn(secondSourceType);
   when(secondSourceType.accept(any(TypeDescription.Generic.Visitor.class)))
       .thenReturn(secondSourceType);
 }
 @Override
 public void apply(
     MethodVisitor methodVisitor,
     MethodDescription methodDescription,
     AnnotationValueFilter annotationValueFilter) {
   AnnotationAppender annotationAppender =
       new AnnotationAppender.Default(new AnnotationAppender.Target.OnMethod(methodVisitor));
   annotationAppender =
       methodDescription
           .getReturnType()
           .accept(
               AnnotationAppender.ForTypeAnnotations.ofMethodReturnType(
                   annotationAppender, annotationValueFilter));
   annotationAppender =
       AnnotationAppender.ForTypeAnnotations.ofTypeVariable(
           annotationAppender,
           annotationValueFilter,
           AnnotationAppender.ForTypeAnnotations.VARIABLE_ON_INVOKEABLE,
           methodDescription.getTypeVariables());
   for (AnnotationDescription annotation : methodDescription.getDeclaredAnnotations()) {
     annotationAppender = annotationAppender.append(annotation, annotationValueFilter);
   }
   for (ParameterDescription parameterDescription : methodDescription.getParameters()) {
     AnnotationAppender parameterAppender =
         new AnnotationAppender.Default(
             new AnnotationAppender.Target.OnMethodParameter(
                 methodVisitor, parameterDescription.getIndex()));
     parameterAppender =
         parameterDescription
             .getType()
             .accept(
                 AnnotationAppender.ForTypeAnnotations.ofMethodParameterType(
                     parameterAppender, annotationValueFilter, parameterDescription.getIndex()));
     for (AnnotationDescription annotation : parameterDescription.getDeclaredAnnotations()) {
       parameterAppender = parameterAppender.append(annotation, annotationValueFilter);
     }
   }
   int exceptionTypeIndex = 0;
   for (TypeDescription.Generic exceptionType : methodDescription.getExceptionTypes()) {
     annotationAppender =
         exceptionType.accept(
             AnnotationAppender.ForTypeAnnotations.ofExceptionType(
                 annotationAppender, annotationValueFilter, exceptionTypeIndex++));
   }
 }
 /**
  * Appends all supplied type variables to the supplied method appender.
  *
  * @param annotationAppender The annotation appender to write any type annotation to.
  * @param annotationValueFilter The annotation value filter to apply.
  * @param variableOnType {@code true} if the type variables are declared by a type, {@code
  *     false} if they are declared by a method.
  * @param subListIndex The index of the first type variable to append. All previous type
  *     variables are ignored.
  * @param typeVariables The type variables to append.
  * @return The resulting annotation appender.
  */
 public static AnnotationAppender ofTypeVariable(
     AnnotationAppender annotationAppender,
     AnnotationValueFilter annotationValueFilter,
     boolean variableOnType,
     int subListIndex,
     List<? extends TypeDescription.Generic> typeVariables) {
   int typeVariableIndex = subListIndex, variableBaseReference, variableBoundBaseBase;
   if (variableOnType) {
     variableBaseReference = TypeReference.CLASS_TYPE_PARAMETER;
     variableBoundBaseBase = TypeReference.CLASS_TYPE_PARAMETER_BOUND;
   } else {
     variableBaseReference = TypeReference.METHOD_TYPE_PARAMETER;
     variableBoundBaseBase = TypeReference.METHOD_TYPE_PARAMETER_BOUND;
   }
   for (TypeDescription.Generic typeVariable :
       typeVariables.subList(subListIndex, typeVariables.size())) {
     int typeReference =
         TypeReference.newTypeParameterReference(variableBaseReference, typeVariableIndex)
             .getValue();
     for (AnnotationDescription annotationDescription : typeVariable.getDeclaredAnnotations()) {
       annotationAppender =
           annotationAppender.append(
               annotationDescription, annotationValueFilter, typeReference, EMPTY_TYPE_PATH);
     }
     int boundIndex =
         !typeVariable.getUpperBounds().get(0).getSort().isTypeVariable()
                 && typeVariable.getUpperBounds().get(0).asErasure().isInterface()
             ? 1
             : 0;
     for (TypeDescription.Generic typeBound : typeVariable.getUpperBounds()) {
       annotationAppender =
           typeBound.accept(
               new ForTypeAnnotations(
                   annotationAppender,
                   annotationValueFilter,
                   TypeReference.newTypeParameterBoundReference(
                       variableBoundBaseBase, typeVariableIndex, boundIndex++)));
     }
     typeVariableIndex++;
   }
   return annotationAppender;
 }