@Override
 public int hashCode() {
   int result = annotationAppender.hashCode();
   result = 31 * result + annotationValueFilter.hashCode();
   result = 31 * result + typeReference;
   result = 31 * result + typePath.hashCode();
   return result;
 }
 @Override
 public boolean equals(Object other) {
   if (this == other) return true;
   if (other == null || getClass() != other.getClass()) return false;
   ForTypeAnnotations that = (ForTypeAnnotations) other;
   return typeReference == that.typeReference
       && annotationAppender.equals(that.annotationAppender)
       && annotationValueFilter.equals(that.annotationValueFilter)
       && typePath.equals(that.typePath);
 }
 /**
  * Handles the writing of a single annotation to an annotation visitor.
  *
  * @param annotationVisitor The annotation visitor the write process is to be applied on.
  * @param annotation The annotation to be written.
  * @param annotationValueFilter The value filter to apply for discovering which values of an
  *     annotation should be written.
  */
 private static void handle(
     AnnotationVisitor annotationVisitor,
     AnnotationDescription annotation,
     AnnotationValueFilter annotationValueFilter) {
   for (MethodDescription.InDefinedShape methodDescription :
       annotation.getAnnotationType().getDeclaredMethods()) {
     if (annotationValueFilter.isRelevant(annotation, methodDescription)) {
       apply(
           annotationVisitor,
           methodDescription.getReturnType().asErasure(),
           methodDescription.getName(),
           annotation.getValue(methodDescription));
     }
   }
   annotationVisitor.visitEnd();
 }