static String encodeWithAnnotations(
      AnnotatedTypeMirror type,
      ImmutableList<AnnotationMirror> extraAnnotations,
      Set<TypeMirror> excludedAnnotationTypes) {
    StringBuilder sb = new StringBuilder();
    // A function that is equivalent to t.getAnnotationMirrors() except when the t in question is
    // our starting type. In that case we also add extraAnnotations to the result.
    Function<TypeMirror, List<? extends AnnotationMirror>> getTypeAnnotations =
        t ->
            (t == type.getType())
                ? ImmutableList.<AnnotationMirror>builder()
                    .addAll(type.annotations())
                    .addAll(extraAnnotations)
                    .build()
                : t.getAnnotationMirrors();
    return new AnnotatedEncodingTypeVisitor(excludedAnnotationTypes, getTypeAnnotations)
        .visit2(type.getType(), sb)
        .toString();
  }
Encodes the given type and its type annotations. The class comment for {@link TypeEncoder}
covers the details of annotation encoding.

@param extraAnnotations additional type annotations to include with the type
@param excludedAnnotationTypes annotations not to include in the encoding. For example, if
    {@code com.example.Nullable} is in this set then the encoding will not include this
    {@code @Nullable} annotation.
value/src/main/java/com/google/auto/value/processor/TypeEncoder.java