docs: Optional<PropertyBuilder> makePropertyBuilder(ExecutableElement method, String property) {
      TypeMirror barBuilderTypeMirror = builderMethodClassifier.builderMethodReturnType(method);
      if (barBuilderTypeMirror.getKind() != TypeKind.DECLARED) {
        errorReporter.reportError(
            "Method looks like a property builder, but its return type is not a class or interface",
            method);
        return Optional.empty();
      }
      DeclaredType barBuilderDeclaredType = MoreTypes.asDeclared(barBuilderTypeMirror);
      TypeElement barBuilderTypeElement = MoreTypes.asTypeElement(barBuilderTypeMirror);
      Map<String, ExecutableElement> barBuilderNoArgMethods = noArgMethodsOf(barBuilderTypeElement);
  
      ExecutableElement barGetter = getterToPropertyName.inverse().get(property);
      TypeMirror barTypeMirror = barGetter.getReturnType();
      if (barTypeMirror.getKind() != TypeKind.DECLARED) {
        errorReporter.reportError(
            "Method looks like a property builder, but the type of property "
                + property
                + " is not a class or interface",
            method);
        return Optional.empty();
      }
      if (isNullable(barGetter)) {
        errorReporter.reportError(
            "Property " + property + " has a property builder so it cannot be @Nullable",
            barGetter);
      }
      TypeElement barTypeElement = MoreTypes.asTypeElement(barTypeMirror);
      Map<String, ExecutableElement> barNoArgMethods = noArgMethodsOf(barTypeElement);
  
      // Condition (1), must have build() method returning Bar.
      ExecutableElement build = barBuilderNoArgMethods.get("build");
      if (build == null || build.getModifiers().contains(Modifier.STATIC)) {
        errorReporter.reportError(
            "Method looks like a property builder, but it returns "
                + barBuilderTypeElement
                + " which does not have a non-static build() method",
            method);
        return Optional.empty();
      }
  
      // We've determined that `BarBuilder` has a method `build()`. But it must return `Bar`.
      // And if the type of `bar()` is Bar<String> then `BarBuilder.build()` must return Bar<String>.
      TypeMirror buildType = eclipseHack.methodReturnType(build, barBuilderDeclaredType);
      if (!MoreTypes.equivalence().equivalent(barTypeMirror, buildType)) {
        errorReporter.reportError(
            "Property builder for "
                + property
                + " has type "
                + barBuilderTypeElement
                + " whose build() method returns "
                + buildType
                + " instead of "
                + barTypeMirror,
            method);
        return Optional.empty();
      }
  
      Optional<ExecutableElement> maybeBuilderMaker =
          builderMaker(barNoArgMethods, barBuilderTypeElement);
      if (!maybeBuilderMaker.isPresent()) {
        errorReporter.reportError(
            "Method looks like a property builder, but its type "
                + barBuilderTypeElement
                + " does not have a public constructor and "
                + barTypeElement
                + " does not have a static builder() or newBuilder() method that returns "
                + barBuilderTypeElement,
            method);
        return Optional.empty();
      }
      ExecutableElement builderMaker = maybeBuilderMaker.get();
  
      String barBuilderType = TypeEncoder.encodeWithAnnotations(barBuilderTypeMirror);
      String rawBarType = TypeEncoder.encodeRaw(barTypeMirror);
      String initializer =
          (builderMaker.getKind() == ElementKind.CONSTRUCTOR)
              ? "new " + barBuilderType + "()"
              : rawBarType + "." + builderMaker.getSimpleName() + "()";
      String builtToBuilder = null;
      String copyAll = null;
      ExecutableElement toBuilder = barNoArgMethods.get("toBuilder");
      if (toBuilder != null
          && !toBuilder.getModifiers().contains(Modifier.STATIC)
          && typeUtils.isAssignable(
              typeUtils.erasure(toBuilder.getReturnType()),
              typeUtils.erasure(barBuilderTypeMirror))) {
        builtToBuilder = toBuilder.getSimpleName().toString();
      } else {
        boolean isGuavaBuilder =
            barBuilderTypeMirror.toString().startsWith(COM_GOOGLE_COMMON_COLLECT_IMMUTABLE)
                && barBuilderTypeMirror.toString().contains(".Builder<");
        Optional<ExecutableElement> maybeCopyAll = addAllPutAll(barBuilderTypeElement);
        if (maybeCopyAll.isPresent() && isGuavaBuilder) {
          copyAll = maybeCopyAll.get().getSimpleName().toString();
        }
      }
      ExecutableElement barOf = barNoArgMethods.get("of");
      boolean hasOf = (barOf != null && barOf.getModifiers().contains(Modifier.STATIC));
      // An expression (initDefault) to make a default one of these, plus optionally a statement
      // (beforeInitDefault) that prepares the expression. For a collection, beforeInitDefault is
      // empty and initDefault is (e.g.) `ImmutableList.of()`. For a nested value type,
      // beforeInitDefault is (e.g.)
      //   `NestedAutoValueType.Builder foo$builder = NestedAutoValueType.builder();`
      // and initDefault is `foo$builder.build();`. The reason for the separate statement is to
      // exploit type inference rather than having to write `NestedAutoValueType.<Bar>build();`.
      String beforeInitDefault;
      String initDefault;
      if (hasOf) {
        beforeInitDefault = "";
        initDefault = rawBarType + ".of()";
      } else {
        String localBuilder = property + "$builder";
        beforeInitDefault = barBuilderType + " " + localBuilder + " = " + initializer + ";";
        initDefault = localBuilder + ".build()";
      }
  
      PropertyBuilder propertyBuilder =
          new PropertyBuilder(
              method,
              barBuilderType,
              barBuilderTypeMirror,
              initializer,
              beforeInitDefault,
              initDefault,
              builtToBuilder,
              copyAll);
      return Optional.of(propertyBuilder);
    }