private static String parameterTypeString(
        ExecutableElement setter, AnnotatedTypeMirror parameterType) {
      if (setter.isVarArgs()) {
        TypeMirror componentType = MoreTypes.asArray(parameterType.getType()).getComponentType();
        // This is a bit ugly. It's OK to annotate just the component type, because if it is
        // say `@Nullable String` then we will end up with `@Nullable String...`. Unlike the
        // normal array case, we can't have the situation where the array itself is annotated;
        // you can write `String @Nullable []` to mean that, but you can't write
        // `String @Nullable ...`.
        return TypeEncoder.encodeWithAnnotations(componentType) + "...";
      } else {
        return TypeEncoder.encodeWithAnnotations(parameterType);
      }
    }
Information about a property setter, referenced from the autovalue.vm template. A property
called foo (defined by a method {@code T foo()} or {@code T getFoo()}) can have a setter method
{@code foo(T)} or {@code setFoo(T)} that returns the builder type. Additionally, it can have a
setter with a type that can be copied to {@code T} through a {@code copyOf} method; for example
a property {@code foo} of type {@code ImmutableSet<String>} can be set with a method {@code
setFoo(Collection<String> foos)}. And, if {@code T} is {@code Optional}, it can have a setter
with a type that can be copied to {@code T} through {@code Optional.of}.
value/src/main/java/com/google/auto/value/processor/BuilderSpec.java