private Optional<Copier> getConvertingSetterFunction(
      ExecutableElement copyOfMethod, DeclaredType targetType, TypeMirror parameterType) {
    // We have a parameter type, for example Set<? extends T>, and we want to know if it can be
    // passed to the given copyOf method, which might for example be one of these methods from
    // ImmutableSet:
    //    public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements)
    //    public static <E> ImmutableSet<E> copyOf(E[] elements)
    // Additionally, if it can indeed be passed to the method, we want to know whether the result
    // (here ImmutableSet<? extends T>) is compatible with the property to be set.
    // We can't use Types.asMemberOf to do the substitution for us, because the methods in question
    // are static. So even if our target type is ImmutableSet<String>, if we ask what the type of
    // copyOf is in ImmutableSet<String> it will still tell us <T> Optional<T> (T).
    // Instead, we do the variable substitutions ourselves.
    if (TypeVariables.canAssignStaticMethodResult(
        copyOfMethod, parameterType, targetType, typeUtils)) {
      String method = TypeEncoder.encodeRaw(targetType) + "." + copyOfMethod.getSimpleName();
      Function<String, String> callMethod = s -> method + "(" + s + ")";
      // This is a big old hack. We guess that the method can accept a null parameter if it has
      // "Nullable" in the name, which java.util.Optional.ofNullable and
      // com.google.common.base.Optional.fromNullable do.
      Copier copier =
          method.contains("Nullable")
              ? Copier.acceptingNull(callMethod)
              : Copier.notAcceptingNull(callMethod);
      return Optional.of(copier);
    }
    return Optional.empty();
  }
Returns an {@code Optional} containing a function to use {@code copyOfMethod} to copy the
{@code parameterType} to the {@code targetType}, or {@code Optional.empty()} if the method
can't be used. For example, we might have a property of type {@code ImmutableSet<T>} and our
setter has a parameter of type {@code Set<? extends T>}. Can we use {@code ImmutableSet<E>
ImmutableSet.copyOf(Collection<? extends E>)} to set the property? What about {@code
ImmutableSet<E> ImmutableSet.copyOf(E[])}?

<p>The example here is deliberately complicated, in that it has a type parameter of its own,
presumably because the {@code @AutoValue} class is {@code Foo<T>}. One subtle point is that the
builder will then be {@code Builder<T>} where this {@code T} is a <i>different</i> type
variable. However, we've used {@link TypeVariables} to ensure that the {@code T} in {@code
ImmutableSet<T>} is actually the one from {@code Builder<T>} instead of the original one from
{@code Foo<T>}.}

@param copyOfMethod the candidate method to do the copy, {@code
    ImmutableSet.copyOf(Collection<? extends E>)} or {@code ImmutableSet.copyOf(E[])} in the
    examples.
@param targetType the type of the property to be set, {@code ImmutableSet<T>} in the example.
@param parameterType the type of the setter parameter, {@code Set<? extends T>} in the example.
@return a function that maps a string parameter to a method call using that parameter. For
    example it might map {@code foo} to {@code ImmutableList.copyOf(foo)}.
value/src/main/java/com/google/auto/value/processor/BuilderMethodClassifier.java