Java Code Examples for com.google.auto.common.MoreTypes#asExecutable()

The following examples show how to use com.google.auto.common.MoreTypes#asExecutable() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: PaperParcelAutoValueExtension.java    From paperparcel with Apache License 2.0 5 votes vote down vote up
private MethodSpec constructor(Context context) {
  Types types = context.processingEnvironment().getTypeUtils();
  DeclaredType declaredValueType = MoreTypes.asDeclared(context.autoValueClass().asType());

  ImmutableList.Builder<ParameterSpec> parameterBuilder = ImmutableList.builder();
  for (Map.Entry<String, ExecutableElement> entry : context.properties().entrySet()) {
    ExecutableType resolvedExecutableType =
        MoreTypes.asExecutable(types.asMemberOf(declaredValueType, entry.getValue()));
    TypeName typeName = TypeName.get(resolvedExecutableType.getReturnType());
    ParameterSpec.Builder spec = ParameterSpec.builder(typeName, entry.getKey());
    AnnotationMirror nullableAnnotation =
        Utils.getAnnotationWithSimpleName(entry.getValue(), NULLABLE_ANNOTATION_NAME);
    if (nullableAnnotation != null) {
      spec.addAnnotation(AnnotationSpec.get(nullableAnnotation));
    }
    parameterBuilder.add(spec.build());
  }

  ImmutableList<ParameterSpec> parameters = parameterBuilder.build();
  CodeBlock parameterList = CodeBlocks.join(FluentIterable.from(parameters)
      .transform(new Function<ParameterSpec, CodeBlock>() {
        @Override public CodeBlock apply(ParameterSpec parameterSpec) {
          return CodeBlock.of("$N", parameterSpec.name);
        }
      }), ", ");

  return MethodSpec.constructorBuilder()
      .addParameters(parameters)
      .addStatement("super($L)", parameterList)
      .build();
}
 
Example 2
Source File: ProductionBinding.java    From dagger2-sample with Apache License 2.0 5 votes vote down vote up
ProductionBinding forProducesMethod(
    ExecutableElement producesMethod, TypeMirror contributedBy) {
  checkNotNull(producesMethod);
  checkArgument(producesMethod.getKind().equals(METHOD));
  checkArgument(contributedBy.getKind().equals(TypeKind.DECLARED));
  Produces producesAnnotation = producesMethod.getAnnotation(Produces.class);
  checkArgument(producesAnnotation != null);
  DeclaredType declaredContainer = MoreTypes.asDeclared(contributedBy);
  ExecutableType resolvedMethod =
      MoreTypes.asExecutable(types.asMemberOf(declaredContainer, producesMethod));
  Key key = keyFactory.forProducesMethod(resolvedMethod, producesMethod);
  ImmutableSet<DependencyRequest> dependencies =
      dependencyRequestFactory.forRequiredResolvedVariables(
          declaredContainer,
          producesMethod.getParameters(),
          resolvedMethod.getParameterTypes());
  Kind kind = MoreTypes.isTypeOf(ListenableFuture.class, producesMethod.getReturnType())
      ? Kind.FUTURE_PRODUCTION
      : Kind.IMMEDIATE;
  return new AutoValue_ProductionBinding(
      key,
      producesMethod,
      dependencies,
      findBindingPackage(key),
      false,
      ConfigurationAnnotations.getNullableType(producesMethod),
      Optional.of(MoreTypes.asTypeElement(declaredContainer)),
      kind,
      producesAnnotation.type(),
      ImmutableList.copyOf(producesMethod.getThrownTypes()));
}
 
Example 3
Source File: ProvisionBinding.java    From dagger2-sample with Apache License 2.0 5 votes vote down vote up
ProvisionBinding forProvidesMethod(ExecutableElement providesMethod, TypeMirror contributedBy) {
  checkNotNull(providesMethod);
  checkArgument(providesMethod.getKind().equals(METHOD));
  checkArgument(contributedBy.getKind().equals(TypeKind.DECLARED));
  Provides providesAnnotation = providesMethod.getAnnotation(Provides.class);
  checkArgument(providesAnnotation != null);
  DeclaredType declaredContainer = MoreTypes.asDeclared(contributedBy);
  ExecutableType resolvedMethod =
      MoreTypes.asExecutable(types.asMemberOf(declaredContainer, providesMethod));
  Key key = keyFactory.forProvidesMethod(resolvedMethod, providesMethod);
  ImmutableSet<DependencyRequest> dependencies =
      dependencyRequestFactory.forRequiredResolvedVariables(
          declaredContainer,
          providesMethod.getParameters(),
          resolvedMethod.getParameterTypes());
  Optional<AnnotationMirror> scope = getScopeAnnotation(providesMethod);
  return new AutoValue_ProvisionBinding(
      key,
      providesMethod,
      dependencies,
      findBindingPackage(key),
      false /* no non-default parameter types */,
      ConfigurationAnnotations.getNullableType(providesMethod),
      Optional.of(MoreTypes.asTypeElement(declaredContainer)),
      Kind.PROVISION,
      providesAnnotation.type(),
      wrapOptionalInEquivalence(AnnotationMirrors.equivalence(), scope),
      Optional.<DependencyRequest>absent());
}
 
Example 4
Source File: MethodSignatureFormatter.java    From dagger2-sample with Apache License 2.0 5 votes vote down vote up
/**
 * Formats an ExecutableElement as if it were contained within the container, if the container is
 * present.
 */
public String format(ExecutableElement method, Optional<DeclaredType> container) {
  StringBuilder builder = new StringBuilder();
  TypeElement type = MoreElements.asType(method.getEnclosingElement());
  ExecutableType executableType = MoreTypes.asExecutable(method.asType());
  if (container.isPresent()) {
    executableType = MoreTypes.asExecutable(types.asMemberOf(container.get(), method));
    type = MoreElements.asType(container.get().asElement());
  }

  // TODO(cgruber): AnnotationMirror formatter.
  List<? extends AnnotationMirror> annotations = method.getAnnotationMirrors();
  if (!annotations.isEmpty()) {
    Iterator<? extends AnnotationMirror> annotationIterator = annotations.iterator();
    for (int i = 0; annotationIterator.hasNext(); i++) {
      if (i > 0) {
        builder.append(' ');
      }
      builder.append(ErrorMessages.format(annotationIterator.next()));
    }
    builder.append(' ');
  }
  builder.append(nameOfType(executableType.getReturnType()));
  builder.append(' ');
  builder.append(type.getQualifiedName());
  builder.append('.');
  builder.append(method.getSimpleName());
  builder.append('(');
  checkState(method.getParameters().size() == executableType.getParameterTypes().size());
  Iterator<? extends VariableElement> parameters = method.getParameters().iterator();
  Iterator<? extends TypeMirror> parameterTypes = executableType.getParameterTypes().iterator();
  for (int i = 0; parameters.hasNext(); i++) {
    if (i > 0) {
      builder.append(", ");
    }
    appendParameter(builder, parameters.next(), parameterTypes.next());
  }
  builder.append(')');
  return builder.toString();
}
 
Example 5
Source File: MembersInjectionBinding.java    From dagger2-sample with Apache License 2.0 5 votes vote down vote up
private InjectionSite injectionSiteForInjectMethod(ExecutableElement methodElement,
    DeclaredType containingType) {
  checkNotNull(methodElement);
  checkArgument(methodElement.getKind().equals(ElementKind.METHOD));
  checkArgument(isAnnotationPresent(methodElement, Inject.class));
  ExecutableType resolved =
      MoreTypes.asExecutable(types.asMemberOf(containingType, methodElement));
  return new AutoValue_MembersInjectionBinding_InjectionSite(InjectionSite.Kind.METHOD,
      methodElement,
      dependencyRequestFactory.forRequiredResolvedVariables(
          containingType,
          methodElement.getParameters(),
          resolved.getParameterTypes()));
}
 
Example 6
Source File: AdapterDescriptor.java    From paperparcel with Apache License 2.0 4 votes vote down vote up
@SuppressWarnings("ConstantConditions") // Already validated
private Optional<ConstructorInfo> getConstructorInfo(
    TypeElement adapterElement, DeclaredType resolvedAdapterType, boolean allowSerializable) {

  ExecutableElement mainConstructor = Utils.findLargestPublicConstructor(adapterElement);
  if (mainConstructor == null) return Optional.absent();

  ImmutableList.Builder<ConstructorInfo.Param> parameterBuilder = ImmutableList.builder();

  ExecutableType resolvedConstructorType =
      MoreTypes.asExecutable(types.asMemberOf(resolvedAdapterType, mainConstructor));
  List<? extends TypeMirror> resolveParameterList = resolvedConstructorType.getParameterTypes();
  List<? extends VariableElement> parameters = mainConstructor.getParameters();

  for (int i = 0; i < parameters.size(); i++) {
    VariableElement dependencyElement = parameters.get(i);
    TypeMirror resolvedDependencyType = resolveParameterList.get(i);

    if (Utils.isAdapterType(dependencyElement, elements, types)) {
      TypeMirror dependencyAdaptedType =
          Utils.getAdaptedType(elements, types, MoreTypes.asDeclared(resolvedDependencyType));
      AdapterDescriptor adapterDependency = create(dependencyAdaptedType, allowSerializable);
      if (adapterDependency == null) {
        return Optional.absent();
      }
      parameterBuilder.add(new ConstructorInfo.AdapterParam(adapterDependency));

    } else if (Utils.isCreatorType(dependencyElement, elements, types)) {
      TypeMirror creatorArg =
          Utils.getCreatorArg(elements, types, MoreTypes.asDeclared(resolvedDependencyType));
      VariableElement creator = Utils.findCreator(elements, types, creatorArg);
      ClassName creatorOwner = null;
      boolean requiresCast = false;
      if (creator != null) {
        TypeElement creatorOwnerElement = (TypeElement) creator.getEnclosingElement();
        // Must only pass the CREATOR directly if the Parcelable element is final. Otherwise
        // we need to use Parcel.readParcelable to read Parcelables because it supports
        // polymorphic types. The reason why we pass the CREATOR at all is because it is a
        // lot faster (no runtime reflection involved). This optimisation will occur in most
        // cases in kotlin (as classes are final by default, and will always occur when using
        // the AutoValueExtension).
        if (creatorOwnerElement.getModifiers().contains(Modifier.FINAL)) {
          creatorOwner = ClassName.get(creatorOwnerElement);
        }
        // Require a cast if the creator owner is generic.
        // See https://github.com/grandstaish/paperparcel/issues/193
        if (creatorOwnerElement.getTypeParameters().size() > 0) {
          requiresCast = true;
        }
      }
      parameterBuilder.add(new ConstructorInfo.CreatorParam(creatorOwner, requiresCast));

    } else {
      TypeMirror classArg =
          Utils.getClassArg(elements, types, MoreTypes.asDeclared(resolvedDependencyType));
      TypeName classTypeName = TypeName.get(classArg);
      parameterBuilder.add(new ConstructorInfo.ClassParam(classTypeName));
    }
  }

  return Optional.of(ConstructorInfo.create(parameterBuilder.build()));
}
 
Example 7
Source File: ComponentGenerator.java    From dagger2-sample with Apache License 2.0 4 votes vote down vote up
private void writeInterfaceMethods(BindingGraph input, ClassWriter componentWriter,
    ImmutableMap<BindingKey, MemberSelect> memberSelectSnippets,
    ImmutableSet<BindingKey> enumBindingKeys) throws AssertionError {
  Set<MethodSignature> interfaceMethods = Sets.newHashSet();

  for (ComponentMethodDescriptor componentMethod :
      input.componentDescriptor().componentMethods()) {
    if (componentMethod.dependencyRequest().isPresent()) {
      DependencyRequest interfaceRequest = componentMethod.dependencyRequest().get();
      ExecutableElement requestElement =
          MoreElements.asExecutable(interfaceRequest.requestElement());
      ExecutableType requestType = MoreTypes.asExecutable(types.asMemberOf(
          MoreTypes.asDeclared(input.componentDescriptor().componentDefinitionType().asType()),
          requestElement));
      MethodSignature signature = MethodSignature.fromExecutableType(
          requestElement.getSimpleName().toString(),
          requestType);
      if (!interfaceMethods.contains(signature)) {
        interfaceMethods.add(signature);
        MethodWriter interfaceMethod = requestType.getReturnType().getKind().equals(VOID)
            ? componentWriter.addMethod(VoidName.VOID, requestElement.getSimpleName().toString())
                : componentWriter.addMethod(requestType.getReturnType(),
                    requestElement.getSimpleName().toString());
        interfaceMethod.annotate(Override.class);
        interfaceMethod.addModifiers(PUBLIC);
        BindingKey bindingKey = interfaceRequest.bindingKey();
        switch(interfaceRequest.kind()) {
          case MEMBERS_INJECTOR:
            MemberSelect membersInjectorSelect = memberSelectSnippets.get(bindingKey);
            List<? extends VariableElement> parameters = requestElement.getParameters();
            if (parameters.isEmpty()) {
              // we're returning the framework type
              interfaceMethod.body().addSnippet("return %s;",
                  membersInjectorSelect.getSnippetFor(componentWriter.name()));
            } else {
              VariableElement parameter = Iterables.getOnlyElement(parameters);
              Name parameterName = parameter.getSimpleName();
              interfaceMethod.addParameter(
                  TypeNames.forTypeMirror(
                      Iterables.getOnlyElement(requestType.getParameterTypes())),
                  parameterName.toString());
              interfaceMethod.body().addSnippet("%s.injectMembers(%s);",
                  // in this case we know we won't need the cast because we're never going to pass
                  // the reference to anything
                  membersInjectorSelect.getSnippetFor(componentWriter.name()),
                  parameterName);
              if (!requestType.getReturnType().getKind().equals(VOID)) {
                interfaceMethod.body().addSnippet("return %s;", parameterName);
              }
            }
            break;
          case INSTANCE:
            if (enumBindingKeys.contains(bindingKey)
                && !MoreTypes.asDeclared(bindingKey.key().type())
                        .getTypeArguments().isEmpty()) {
              // If using a parameterized enum type, then we need to store the factory
              // in a temporary variable, in order to help javac be able to infer
              // the generics of the Factory.create methods.
              TypeName factoryType = ParameterizedTypeName.create(Provider.class,
                  TypeNames.forTypeMirror(requestType.getReturnType()));
              interfaceMethod.body().addSnippet("%s factory = %s;", factoryType,
                  memberSelectSnippets.get(bindingKey).getSnippetFor(componentWriter.name()));
              interfaceMethod.body().addSnippet("return factory.get();");
              break;
            }
            // fall through in the else case.
          case LAZY:
          case PRODUCED:
          case PRODUCER:
          case PROVIDER:
          case FUTURE:
            interfaceMethod.body().addSnippet("return %s;",
                frameworkTypeUsageStatement(
                    memberSelectSnippets.get(bindingKey).getSnippetFor(componentWriter.name()),
                    interfaceRequest.kind()));
            break;
          default:
            throw new AssertionError();
        }
      }
    }
  }
}
 
Example 8
Source File: ProvisionBinding.java    From dagger2-sample with Apache License 2.0 4 votes vote down vote up
/**
 * Returns a ProvisionBinding for the given element. If {@code resolvedType} is present, this
 * will return a resolved binding, with the key & type resolved to the given type (using
 * {@link Types#asMemberOf(DeclaredType, Element)}).
 */
ProvisionBinding forInjectConstructor(ExecutableElement constructorElement,
    Optional<TypeMirror> resolvedType) {
  checkNotNull(constructorElement);
  checkArgument(constructorElement.getKind().equals(CONSTRUCTOR));
  checkArgument(isAnnotationPresent(constructorElement, Inject.class));
  checkArgument(!getQualifier(constructorElement).isPresent());

  ExecutableType cxtorType = MoreTypes.asExecutable(constructorElement.asType());
  DeclaredType enclosingCxtorType =
      MoreTypes.asDeclared(constructorElement.getEnclosingElement().asType());
  // If the class this is constructing has some type arguments, resolve everything.
  if (!enclosingCxtorType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
    DeclaredType resolved = MoreTypes.asDeclared(resolvedType.get());
    // Validate that we're resolving from the correct type.
    checkState(types.isSameType(types.erasure(resolved), types.erasure(enclosingCxtorType)),
        "erased expected type: %s, erased actual type: %s",
        types.erasure(resolved), types.erasure(enclosingCxtorType));
    cxtorType = MoreTypes.asExecutable(types.asMemberOf(resolved, constructorElement));
    enclosingCxtorType = resolved;
  }

  Key key = keyFactory.forInjectConstructorWithResolvedType(enclosingCxtorType);
  checkArgument(!key.qualifier().isPresent());
  ImmutableSet<DependencyRequest> dependencies =
      dependencyRequestFactory.forRequiredResolvedVariables(enclosingCxtorType,
          constructorElement.getParameters(),
          cxtorType.getParameterTypes());
  Optional<DependencyRequest> membersInjectionRequest =
      membersInjectionRequest(enclosingCxtorType);
  Optional<AnnotationMirror> scope =
      getScopeAnnotation(constructorElement.getEnclosingElement());

  TypeElement bindingTypeElement =
      MoreElements.asType(constructorElement.getEnclosingElement());

  return new AutoValue_ProvisionBinding(
      key,
      constructorElement,
      dependencies,
      findBindingPackage(key),
      hasNonDefaultTypeParameters(bindingTypeElement, key.type(), types),
      Optional.<DeclaredType>absent(),
      Optional.<TypeElement>absent(),
      Kind.INJECTION,
      Provides.Type.UNIQUE,
      wrapOptionalInEquivalence(AnnotationMirrors.equivalence(), scope),
      membersInjectionRequest);
}
 
Example 9
Source File: ComponentDescriptor.java    From dagger2-sample with Apache License 2.0 4 votes vote down vote up
private ComponentMethodDescriptor getDescriptorForComponentMethod(TypeElement componentElement,
    Kind componentKind,
    ExecutableElement componentMethod) {
  ExecutableType resolvedComponentMethod = MoreTypes.asExecutable(types.asMemberOf(
      MoreTypes.asDeclared(componentElement.asType()), componentMethod));
  TypeMirror returnType = resolvedComponentMethod.getReturnType();
  if (returnType.getKind().equals(DECLARED)) {
    if (MoreTypes.isTypeOf(Provider.class, returnType)
        || MoreTypes.isTypeOf(Lazy.class, returnType)) {
      return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor(
          ComponentMethodKind.PROVISON,
          Optional.of(dependencyRequestFactory.forComponentProvisionMethod(componentMethod,
              resolvedComponentMethod)),
          componentMethod);
    } else if (MoreTypes.isTypeOf(MembersInjector.class, returnType)) {
      return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor(
          ComponentMethodKind.MEMBERS_INJECTION,
          Optional.of(dependencyRequestFactory.forComponentMembersInjectionMethod(
              componentMethod,
              resolvedComponentMethod)),
          componentMethod);
    } else if (getAnnotationMirror(MoreTypes.asElement(returnType), Subcomponent.class)
        .isPresent()) {
      return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor(
          ComponentMethodKind.SUBCOMPONENT,
          Optional.<DependencyRequest>absent(),
          componentMethod);
    }
  }

  // a typical provision method
  if (componentMethod.getParameters().isEmpty()
      && !componentMethod.getReturnType().getKind().equals(VOID)) {
    switch (componentKind) {
      case COMPONENT:
        return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor(
            ComponentMethodKind.PROVISON,
            Optional.of(dependencyRequestFactory.forComponentProvisionMethod(componentMethod,
                resolvedComponentMethod)),
            componentMethod);
      case PRODUCTION_COMPONENT:
        return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor(
            ComponentMethodKind.PRODUCTION,
            Optional.of(dependencyRequestFactory.forComponentProductionMethod(componentMethod,
                resolvedComponentMethod)),
            componentMethod);
      default:
        throw new AssertionError();
    }
  }

  List<? extends TypeMirror> parameterTypes = resolvedComponentMethod.getParameterTypes();
  if (parameterTypes.size() == 1
      && (returnType.getKind().equals(VOID)
          || MoreTypes.equivalence().equivalent(returnType, parameterTypes.get(0)))) {
    return new AutoValue_ComponentDescriptor_ComponentMethodDescriptor(
        ComponentMethodKind.MEMBERS_INJECTION,
        Optional.of(dependencyRequestFactory.forComponentMembersInjectionMethod(
            componentMethod,
            resolvedComponentMethod)),
        componentMethod);
  }

  throw new IllegalArgumentException("not a valid component method: " + componentMethod);
}
 
Example 10
Source File: ComponentMethodDescriptor.java    From bullet with Apache License 2.0 4 votes vote down vote up
static Optional<ComponentMethodDescriptor> forComponentMethod(Types types, DeclaredType componentElement, ExecutableElement componentMethod) {
  // Using same algorithm as Dagger's ComponentDescriptor#getDescriptorForComponentMethod
  ExecutableType resolvedComponentMethod = MoreTypes.asExecutable(types.asMemberOf(componentElement, componentMethod));
  TypeMirror returnType = resolvedComponentMethod.getReturnType();
  if (returnType.getKind() == TypeKind.DECLARED) {
    if (MoreTypes.isTypeOf(Provider.class, returnType)
        || MoreTypes.isTypeOf(Lazy.class, returnType)) {
      return methodDescriptor(
          ComponentMethodKind.PROVIDER_OR_LAZY,
          MoreTypes.asDeclared(MoreTypes.asDeclared(returnType).getTypeArguments().get(0)),
          componentMethod);
    } else if (MoreTypes.isTypeOf(MembersInjector.class, returnType)) {
      return methodDescriptor(
          ComponentMethodKind.MEMBERS_INJECTOR,
          MoreTypes.asDeclared(MoreTypes.asDeclared(returnType).getTypeArguments().get(0)),
          componentMethod);
    } else if (MoreElements.getAnnotationMirror(types.asElement(returnType), Subcomponent.class).isPresent()) {
      // Ignore subcomponent methods
      return Optional.absent();
    }
  }

  if (resolvedComponentMethod.getParameterTypes().isEmpty()
      && resolvedComponentMethod.getReturnType().getKind() == TypeKind.DECLARED) {
    return methodDescriptor(
        ComponentMethodKind.SIMPLE_PROVISION,
        MoreTypes.asDeclared(returnType),
        componentMethod);
  }

  List<? extends TypeMirror> parameterTypes = resolvedComponentMethod.getParameterTypes();
  if (parameterTypes.size() == 1
      && parameterTypes.get(0).getKind() == TypeKind.DECLARED
      && (returnType.getKind().equals(TypeKind.VOID)
          || types.isSameType(returnType, parameterTypes.get(0)))) {
    return methodDescriptor(
        ComponentMethodKind.SIMPLE_MEMBERS_INJECTION,
        MoreTypes.asDeclared(parameterTypes.get(0)),
        componentMethod);
  }

  // Let Dagger do the validation
  return Optional.absent();
}
 
Example 11
Source File: BuilderMethodClassifier.java    From auto with Apache License 2.0 4 votes vote down vote up
/**
 * Classifies a method given that it has one argument. Currently, a method with one argument can
 * only be a setter, meaning that it must look like {@code foo(T)} or {@code setFoo(T)}, where the
 * {@code AutoValue} class has a property called {@code foo} of type {@code T}.
 */
private void classifyMethodOneArg(ExecutableElement method) {
  String methodName = method.getSimpleName().toString();
  Map<String, ExecutableElement> propertyNameToGetter = getterToPropertyName.inverse();
  String propertyName = null;
  ExecutableElement valueGetter = propertyNameToGetter.get(methodName);
  Multimap<String, PropertySetter> propertyNameToSetters = null;
  if (valueGetter != null) {
    propertyNameToSetters = propertyNameToUnprefixedSetters;
    propertyName = methodName;
  } else if (valueGetter == null && methodName.startsWith("set") && methodName.length() > 3) {
    propertyNameToSetters = propertyNameToPrefixedSetters;
    propertyName = PropertyNames.decapitalizeLikeJavaBeans(methodName.substring(3));
    valueGetter = propertyNameToGetter.get(propertyName);
    if (valueGetter == null) {
      // If our property is defined by a getter called getOAuth() then it is called "OAuth"
      // because of Introspector.decapitalize. Therefore we want Introspector.decapitalize to
      // be used for the setter too, so that you can write setOAuth(x). Meanwhile if the property
      // is defined by a getter called oAuth() then it is called "oAuth", but you would still
      // expect to be able to set it using setOAuth(x). Hence the second try using a decapitalize
      // method without the quirky two-leading-capitals rule.
      propertyName = PropertyNames.decapitalizeNormally(methodName.substring(3));
      valueGetter = propertyNameToGetter.get(propertyName);
    }
  }
  if (valueGetter == null || propertyNameToSetters == null) {
    // The second disjunct isn't needed but convinces control-flow checkers that
    // propertyNameToSetters can't be null when we call put on it below.
    errorReporter.reportError(
        method, "Method does not correspond to a property of %s", autoValueClass);
    checkForFailedJavaBean(method);
    return;
  }
  Optional<Function<String, String>> function = getSetterFunction(valueGetter, method);
  if (function.isPresent()) {
    DeclaredType builderTypeMirror = MoreTypes.asDeclared(builderType.asType());
    ExecutableType methodMirror =
        MoreTypes.asExecutable(typeUtils.asMemberOf(builderTypeMirror, method));
    if (TYPE_EQUIVALENCE.equivalent(methodMirror.getReturnType(), builderType.asType())) {
      TypeMirror parameterType = Iterables.getOnlyElement(methodMirror.getParameterTypes());
      propertyNameToSetters.put(
          propertyName, new PropertySetter(method, parameterType, function.get()));
    } else {
      errorReporter.reportError(
          method, "Setter methods must return %s%s", builderType, typeParamsString());
    }
  }
}
 
Example 12
Source File: BuilderMethodClassifier.java    From auto with Apache License 2.0 4 votes vote down vote up
/**
 * Returns an {@code Optional} describing how to convert a value from the setter's parameter type
 * to the getter's return type, or {@code Optional.empty()} if the conversion isn't possible. An
 * error will have been reported in the latter case. We can convert if they are already the same
 * type, when the returned function will be the identity; or if the setter type can be copied
 * using a method like {@code ImmutableList.copyOf} or {@code Optional.of}, when the returned
 * function will be something like {@code s -> "Optional.of(" + s + ")"}.
 */
private Optional<Function<String, String>> getSetterFunction(
    ExecutableElement valueGetter, ExecutableElement setter) {
  VariableElement parameterElement = Iterables.getOnlyElement(setter.getParameters());
  boolean nullableParameter =
      nullableAnnotationFor(parameterElement, parameterElement.asType()).isPresent();
  TypeMirror targetType = getterToPropertyType.get(valueGetter);
  ExecutableType finalSetter =
      MoreTypes.asExecutable(
          typeUtils.asMemberOf(MoreTypes.asDeclared(builderType.asType()), setter));
  TypeMirror parameterType = finalSetter.getParameterTypes().get(0);
  // Two types are assignable to each other if they are the same type, or if one is primitive and
  // the other is the corresponding boxed type. There might be other cases where this is true, but
  // we're likely to want to accept those too.
  if (typeUtils.isAssignable(parameterType, targetType)
      && typeUtils.isAssignable(targetType, parameterType)) {
    if (nullableParameter) {
      boolean nullableProperty =
          nullableAnnotationFor(valueGetter, valueGetter.getReturnType()).isPresent();
      if (!nullableProperty) {
        errorReporter.reportError(
            setter,
            "Parameter of setter method is @Nullable but property method %s.%s() is not",
            autoValueClass, valueGetter.getSimpleName());
        return Optional.empty();
      }
    }
    return Optional.of(s -> s);
  }

  // Parameter type is not equal to property type, but might be convertible with copyOf.
  ImmutableList<ExecutableElement> copyOfMethods = copyOfMethods(targetType, nullableParameter);
  if (!copyOfMethods.isEmpty()) {
    return getConvertingSetterFunction(copyOfMethods, valueGetter, setter, parameterType);
  }
  errorReporter.reportError(
      setter,
      "Parameter type %s of setter method should be %s to match getter %s.%s",
      parameterType, targetType, autoValueClass, valueGetter.getSimpleName());
  return Optional.empty();
}