Skip to content

Commit

Permalink
Migrate ComponentCreatorDescriptor to XProcessing.
Browse files Browse the repository at this point in the history
RELNOTES=N/A
PiperOrigin-RevId: 404838253
  • Loading branch information
bcorso authored and Dagger Team committed Oct 21, 2021
1 parent 1c24b97 commit c926820
Show file tree
Hide file tree
Showing 18 changed files with 261 additions and 144 deletions.
25 changes: 16 additions & 9 deletions java/dagger/internal/codegen/binding/BindingFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package dagger.internal.codegen.binding;

import static androidx.room.compiler.processing.XElementKt.isMethod;
import static androidx.room.compiler.processing.XElementKt.isVariableElement;
import static androidx.room.compiler.processing.compat.XConverters.toJavac;
import static com.google.auto.common.MoreElements.isAnnotationPresent;
import static com.google.auto.common.MoreTypes.asDeclared;
Expand All @@ -31,6 +33,8 @@
import static dagger.internal.codegen.binding.MapKeys.getMapKey;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.xprocessing.XElements.asMethod;
import static dagger.internal.codegen.xprocessing.XElements.asVariable;
import static dagger.spi.model.BindingKind.ASSISTED_FACTORY;
import static dagger.spi.model.BindingKind.ASSISTED_INJECTION;
import static dagger.spi.model.BindingKind.BOUND_INSTANCE;
Expand All @@ -49,8 +53,11 @@
import static javax.lang.model.element.ElementKind.CONSTRUCTOR;
import static javax.lang.model.element.ElementKind.METHOD;

import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XMethodElement;
import androidx.room.compiler.processing.XTypeElement;
import androidx.room.compiler.processing.XVariableElement;
import androidx.room.compiler.processing.compat.XConverters;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableCollection;
Expand All @@ -77,7 +84,6 @@
import java.util.Optional;
import java.util.function.BiFunction;
import javax.inject.Inject;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
Expand Down Expand Up @@ -418,17 +424,18 @@ public ContributionBinding componentDependencyMethodBinding(
* Returns a {@link dagger.spi.model.BindingKind#BOUND_INSTANCE} binding for a
* {@code @BindsInstance}-annotated builder setter method or factory method parameter.
*/
ProvisionBinding boundInstanceBinding(ComponentRequirement requirement, Element element) {
checkArgument(element instanceof VariableElement || element instanceof ExecutableElement);
VariableElement parameterElement =
element instanceof VariableElement
? MoreElements.asVariable(element)
: getOnlyElement(MoreElements.asExecutable(element).getParameters());
ProvisionBinding boundInstanceBinding(ComponentRequirement requirement, XElement element) {
checkArgument(isVariableElement(element) || isMethod(element));
XVariableElement parameterElement =
isVariableElement(element)
? asVariable(element)
: getOnlyElement(asMethod(element).getParameters());
return ProvisionBinding.builder()
.contributionType(ContributionType.UNIQUE)
.bindingElement(element)
.bindingElement(toJavac(element))
.key(requirement.key().get())
.nullableType(getNullableType(parameterElement))
.nullableType(
getNullableType(parameterElement).map(XConverters::toJavac).map(MoreTypes::asDeclared))
.kind(BOUND_INSTANCE)
.build();
}
Expand Down
116 changes: 53 additions & 63 deletions java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,30 @@

package dagger.internal.codegen.binding;

import static androidx.room.compiler.processing.compat.XConverters.toJavac;
import static com.google.auto.common.MoreElements.isAnnotationPresent;
import static com.google.auto.common.MoreTypes.asDeclared;
import static com.google.auto.common.MoreTypes.asTypeElement;
import static com.google.common.base.Verify.verify;
import static com.google.common.collect.Iterables.getOnlyElement;
import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
import static dagger.internal.codegen.binding.ComponentCreatorAnnotation.getCreatorAnnotations;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.xprocessing.XTypeElements.getAllUnimplementedMethods;

import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XExecutableParameterElement;
import androidx.room.compiler.processing.XMethodElement;
import androidx.room.compiler.processing.XMethodType;
import androidx.room.compiler.processing.XType;
import androidx.room.compiler.processing.XTypeElement;
import com.google.auto.common.MoreTypes;
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import dagger.BindsInstance;
import dagger.internal.codegen.langmodel.DaggerElements;
import dagger.internal.codegen.javapoet.TypeNames;
import dagger.internal.codegen.langmodel.DaggerTypes;
import dagger.spi.model.DependencyRequest;
import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeMirror;

/**
* A descriptor for a component <i>creator</i> type: that is, a type annotated with
Expand All @@ -64,26 +57,26 @@ public final ComponentCreatorKind kind() {
}

/** The annotated creator type. */
public abstract TypeElement typeElement();
public abstract XTypeElement typeElement();

/** The method that creates and returns a component instance. */
public abstract ExecutableElement factoryMethod();
public abstract XMethodElement factoryMethod();

/**
* Multimap of component requirements to setter methods that set that requirement.
*
* <p>In a valid creator, there will be exactly one element per component requirement, so this
* method should only be called when validating the descriptor.
*/
abstract ImmutableSetMultimap<ComponentRequirement, ExecutableElement> unvalidatedSetterMethods();
abstract ImmutableSetMultimap<ComponentRequirement, XMethodElement> unvalidatedSetterMethods();

/**
* Multimap of component requirements to factory method parameters that set that requirement.
*
* <p>In a valid creator, there will be exactly one element per component requirement, so this
* method should only be called when validating the descriptor.
*/
abstract ImmutableSetMultimap<ComponentRequirement, VariableElement>
abstract ImmutableSetMultimap<ComponentRequirement, XExecutableParameterElement>
unvalidatedFactoryParameters();

/**
Expand All @@ -93,7 +86,7 @@ public final ComponentCreatorKind kind() {
* <p>In a valid creator, there will be exactly one element per component requirement, so this
* method should only be called when validating the descriptor.
*/
public final ImmutableSetMultimap<ComponentRequirement, Element>
public final ImmutableSetMultimap<ComponentRequirement, XElement>
unvalidatedRequirementElements() {
// ComponentCreatorValidator ensures that there are either setter methods or factory method
// parameters, but not both, so we can cheat a little here since we know that only one of
Expand All @@ -109,19 +102,19 @@ public final ComponentCreatorKind kind() {
* set them.
*/
@Memoized
ImmutableMap<ComponentRequirement, Element> requirementElements() {
ImmutableMap<ComponentRequirement, XElement> requirementElements() {
return flatten(unvalidatedRequirementElements());
}

/** Map of component requirements to setter methods for those requirements. */
@Memoized
public ImmutableMap<ComponentRequirement, ExecutableElement> setterMethods() {
public ImmutableMap<ComponentRequirement, XMethodElement> setterMethods() {
return flatten(unvalidatedSetterMethods());
}

/** Map of component requirements to factory method parameters for those requirements. */
@Memoized
public ImmutableMap<ComponentRequirement, VariableElement> factoryParameters() {
public ImmutableMap<ComponentRequirement, XExecutableParameterElement> factoryParameters() {
return flatten(unvalidatedFactoryParameters());
}

Expand Down Expand Up @@ -151,77 +144,74 @@ final ImmutableSet<ComponentRequirement> boundInstanceRequirements() {
}

/** Returns the element in this creator that sets the given {@code requirement}. */
final Element elementForRequirement(ComponentRequirement requirement) {
final XElement elementForRequirement(ComponentRequirement requirement) {
return requirementElements().get(requirement);
}

/** Creates a new {@link ComponentCreatorDescriptor} for the given creator {@code type}. */
public static ComponentCreatorDescriptor create(
XTypeElement xTypeElement,
DaggerElements elements,
DaggerTypes types,
DependencyRequestFactory dependencyRequestFactory) {
TypeElement typeElement = toJavac(xTypeElement);
TypeMirror componentType = typeElement.getEnclosingElement().asType();

ImmutableSetMultimap.Builder<ComponentRequirement, ExecutableElement> setterMethods =
ImmutableSetMultimap.builder();

DeclaredType type = asDeclared(typeElement.asType());
ExecutableElement factoryMethod = null;
for (ExecutableElement method : elements.getUnimplementedMethods(typeElement)) {
ExecutableType resolvedMethodType = MoreTypes.asExecutable(types.asMemberOf(type, method));
XTypeElement creator, DaggerTypes types, DependencyRequestFactory dependencyRequestFactory) {
XType componentType = creator.getEnclosingTypeElement().getType();

ImmutableSetMultimap.Builder<ComponentRequirement, XMethodElement> setterMethods =
ImmutableSetMultimap.builder();
XMethodElement factoryMethod = null;
for (XMethodElement method : getAllUnimplementedMethods(creator)) {
XMethodType resolvedMethodType = method.asMemberOf(creator.getType());
if (types.isSubtype(componentType, resolvedMethodType.getReturnType())) {
verify(factoryMethod == null); // validation should have ensured there's only 1.
factoryMethod = method;
} else {
VariableElement parameter = getOnlyElement(method.getParameters());
TypeMirror parameterType = getOnlyElement(resolvedMethodType.getParameterTypes());
XExecutableParameterElement parameter = getOnlyElement(method.getParameters());
XType parameterType = getOnlyElement(resolvedMethodType.getParameterTypes());
setterMethods.put(
requirement(method, parameter, parameterType, dependencyRequestFactory, method),
requirement(
method, parameter, parameterType, dependencyRequestFactory, method.getName()),
method);
}
}
verify(factoryMethod != null); // validation should have ensured this.

ImmutableSetMultimap.Builder<ComponentRequirement, VariableElement> factoryParameters =
ImmutableSetMultimap.builder();
ImmutableSetMultimap.Builder<ComponentRequirement, XExecutableParameterElement>
factoryParameters = ImmutableSetMultimap.builder();

ExecutableType resolvedFactoryMethodType =
MoreTypes.asExecutable(types.asMemberOf(type, factoryMethod));
List<? extends VariableElement> parameters = factoryMethod.getParameters();
List<? extends TypeMirror> parameterTypes = resolvedFactoryMethodType.getParameterTypes();
XMethodType resolvedFactoryMethodType = factoryMethod.asMemberOf(creator.getType());
List<XExecutableParameterElement> parameters = factoryMethod.getParameters();
List<XType> parameterTypes = resolvedFactoryMethodType.getParameterTypes();
for (int i = 0; i < parameters.size(); i++) {
VariableElement parameter = parameters.get(i);
TypeMirror parameterType = parameterTypes.get(i);
XExecutableParameterElement parameter = parameters.get(i);
XType parameterType = parameterTypes.get(i);
factoryParameters.put(
requirement(factoryMethod, parameter, parameterType, dependencyRequestFactory, parameter),
requirement(
factoryMethod,
parameter,
parameterType,
dependencyRequestFactory,
parameter.getName()),
parameter);
}

// Validation should have ensured exactly one creator annotation is present on the type.
ComponentCreatorAnnotation annotation = getOnlyElement(getCreatorAnnotations(typeElement));
ComponentCreatorAnnotation annotation = getOnlyElement(getCreatorAnnotations(creator));
return new AutoValue_ComponentCreatorDescriptor(
annotation, typeElement, factoryMethod, setterMethods.build(), factoryParameters.build());
annotation, creator, factoryMethod, setterMethods.build(), factoryParameters.build());
}

private static ComponentRequirement requirement(
ExecutableElement method,
VariableElement parameter,
TypeMirror type,
XMethodElement method,
XExecutableParameterElement parameter,
XType parameterType,
DependencyRequestFactory dependencyRequestFactory,
Element elementForVariableName) {
if (isAnnotationPresent(method, BindsInstance.class)
|| isAnnotationPresent(parameter, BindsInstance.class)) {
String variableName) {
if (method.hasAnnotation(TypeNames.BINDS_INSTANCE)
|| parameter.hasAnnotation(TypeNames.BINDS_INSTANCE)) {
DependencyRequest request =
dependencyRequestFactory.forRequiredResolvedVariable(parameter, type);
String variableName = elementForVariableName.getSimpleName().toString();
dependencyRequestFactory.forRequiredResolvedVariable(parameter, parameterType);
return ComponentRequirement.forBoundInstance(
request.key(), request.isNullable(), variableName);
}

return moduleAnnotation(asTypeElement(type)).isPresent()
? ComponentRequirement.forModule(type)
: ComponentRequirement.forDependency(type);
return moduleAnnotation(parameterType.getTypeElement()).isPresent()
? ComponentRequirement.forModule(parameterType)
: ComponentRequirement.forDependency(parameterType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ final Optional<ComponentMethodDescriptor> getFactoryMethodForChildComponent(
.filter(child -> child.creatorDescriptor().isPresent())
.collect(
toImmutableMap(
child -> child.creatorDescriptor().get().typeElement(),
child -> toJavac(child.creatorDescriptor().get().typeElement()),
child -> child)));

/** Returns the child component with the given builder type. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ private ComponentDescriptor create(
? Optional.empty()
: Optional.of(
ComponentCreatorDescriptor.create(
getOnlyElement(enclosedCreators), elements, types, dependencyRequestFactory));
getOnlyElement(enclosedCreators), types, dependencyRequestFactory));

ImmutableSet<Scope> scopes = scopesOf(typeElement);
if (componentAnnotation.isProduction()) {
Expand Down
10 changes: 10 additions & 0 deletions java/dagger/internal/codegen/binding/ComponentRequirement.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package dagger.internal.codegen.binding;

import static androidx.room.compiler.processing.compat.XConverters.toJavac;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static dagger.internal.codegen.binding.SourceFiles.simpleVariableName;
Expand All @@ -25,6 +26,7 @@
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.STATIC;

import androidx.room.compiler.processing.XType;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.auto.value.AutoValue;
Expand Down Expand Up @@ -193,6 +195,10 @@ public ParameterSpec toParameterSpec() {
return ParameterSpec.builder(TypeName.get(type()), variableName()).build();
}

public static ComponentRequirement forDependency(XType type) {
return forDependency(toJavac(type));
}

public static ComponentRequirement forDependency(TypeMirror type) {
return new AutoValue_ComponentRequirement(
Kind.DEPENDENCY,
Expand All @@ -202,6 +208,10 @@ public static ComponentRequirement forDependency(TypeMirror type) {
simpleVariableName(MoreTypes.asTypeElement(type)));
}

public static ComponentRequirement forModule(XType type) {
return forModule(toJavac(type));
}

public static ComponentRequirement forModule(TypeMirror type) {
return new AutoValue_ComponentRequirement(
Kind.MODULE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import androidx.room.compiler.processing.XAnnotation;
import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XType;
import androidx.room.compiler.processing.XTypeElement;
import com.google.auto.common.MoreElements;
import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -98,6 +99,10 @@ public static Optional<XAnnotation> getNullableAnnotation(XElement element) {
.findFirst();
}

public static Optional<XType> getNullableType(XElement element) {
return getNullableAnnotation(element).map(XAnnotation::getType);
}

/** Returns the first type that specifies this' nullability, or empty if none. */
public static Optional<DeclaredType> getNullableType(Element element) {
List<? extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import static dagger.spi.model.RequestKind.PROVIDER;

import androidx.room.compiler.processing.XMethodElement;
import androidx.room.compiler.processing.XType;
import androidx.room.compiler.processing.XVariableElement;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import dagger.Lazy;
Expand Down Expand Up @@ -132,6 +134,11 @@ private RequestKind multibindingContributionRequestKind(
throw new AssertionError(multibindingContribution.toString());
}

DependencyRequest forRequiredResolvedVariable(
XVariableElement variableElement, XType resolvedType) {
return forRequiredResolvedVariable(toJavac(variableElement), toJavac(resolvedType));
}

DependencyRequest forRequiredResolvedVariable(
VariableElement variableElement, TypeMirror resolvedType) {
checkNotNull(variableElement);
Expand Down
Loading

0 comments on commit c926820

Please sign in to comment.