diff --git a/java/dagger/internal/codegen/binding/BindingFactory.java b/java/dagger/internal/codegen/binding/BindingFactory.java index b35ff2202be..72737ada90b 100644 --- a/java/dagger/internal/codegen/binding/BindingFactory.java +++ b/java/dagger/internal/codegen/binding/BindingFactory.java @@ -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; @@ -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; @@ -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; @@ -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; @@ -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(); } diff --git a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java b/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java index 96420a1c470..258ed6bc4f5 100644 --- a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java +++ b/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java @@ -16,18 +16,19 @@ 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; @@ -35,18 +36,10 @@ 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 creator type: that is, a type annotated with @@ -64,10 +57,10 @@ 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. @@ -75,7 +68,7 @@ public final ComponentCreatorKind kind() { *

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 unvalidatedSetterMethods(); + abstract ImmutableSetMultimap unvalidatedSetterMethods(); /** * Multimap of component requirements to factory method parameters that set that requirement. @@ -83,7 +76,7 @@ public final ComponentCreatorKind kind() { *

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 + abstract ImmutableSetMultimap unvalidatedFactoryParameters(); /** @@ -93,7 +86,7 @@ public final ComponentCreatorKind kind() { *

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 + public final ImmutableSetMultimap 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 @@ -109,19 +102,19 @@ public final ComponentCreatorKind kind() { * set them. */ @Memoized - ImmutableMap requirementElements() { + ImmutableMap requirementElements() { return flatten(unvalidatedRequirementElements()); } /** Map of component requirements to setter methods for those requirements. */ @Memoized - public ImmutableMap setterMethods() { + public ImmutableMap setterMethods() { return flatten(unvalidatedSetterMethods()); } /** Map of component requirements to factory method parameters for those requirements. */ @Memoized - public ImmutableMap factoryParameters() { + public ImmutableMap factoryParameters() { return flatten(unvalidatedFactoryParameters()); } @@ -151,77 +144,74 @@ final ImmutableSet 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 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 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 factoryParameters = - ImmutableSetMultimap.builder(); + ImmutableSetMultimap.Builder + factoryParameters = ImmutableSetMultimap.builder(); - ExecutableType resolvedFactoryMethodType = - MoreTypes.asExecutable(types.asMemberOf(type, factoryMethod)); - List parameters = factoryMethod.getParameters(); - List parameterTypes = resolvedFactoryMethodType.getParameterTypes(); + XMethodType resolvedFactoryMethodType = factoryMethod.asMemberOf(creator.getType()); + List parameters = factoryMethod.getParameters(); + List 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); } } diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptor.java b/java/dagger/internal/codegen/binding/ComponentDescriptor.java index 9de692d1a78..69321d5d43f 100644 --- a/java/dagger/internal/codegen/binding/ComponentDescriptor.java +++ b/java/dagger/internal/codegen/binding/ComponentDescriptor.java @@ -256,7 +256,7 @@ final Optional 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. */ diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java b/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java index 576504c562d..c1a89ca83ec 100644 --- a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java +++ b/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java @@ -176,7 +176,7 @@ private ComponentDescriptor create( ? Optional.empty() : Optional.of( ComponentCreatorDescriptor.create( - getOnlyElement(enclosedCreators), elements, types, dependencyRequestFactory)); + getOnlyElement(enclosedCreators), types, dependencyRequestFactory)); ImmutableSet scopes = scopesOf(typeElement); if (componentAnnotation.isProduction()) { diff --git a/java/dagger/internal/codegen/binding/ComponentRequirement.java b/java/dagger/internal/codegen/binding/ComponentRequirement.java index 9e7c790fa3e..b71034cb90c 100644 --- a/java/dagger/internal/codegen/binding/ComponentRequirement.java +++ b/java/dagger/internal/codegen/binding/ComponentRequirement.java @@ -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; @@ -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; @@ -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, @@ -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, diff --git a/java/dagger/internal/codegen/binding/ConfigurationAnnotations.java b/java/dagger/internal/codegen/binding/ConfigurationAnnotations.java index 981030ed5fc..b6a9d4d5e77 100644 --- a/java/dagger/internal/codegen/binding/ConfigurationAnnotations.java +++ b/java/dagger/internal/codegen/binding/ConfigurationAnnotations.java @@ -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; @@ -98,6 +99,10 @@ public static Optional getNullableAnnotation(XElement element) { .findFirst(); } + public static Optional getNullableType(XElement element) { + return getNullableAnnotation(element).map(XAnnotation::getType); + } + /** Returns the first type that specifies this' nullability, or empty if none. */ public static Optional getNullableType(Element element) { List mirrors = element.getAnnotationMirrors(); diff --git a/java/dagger/internal/codegen/binding/DependencyRequestFactory.java b/java/dagger/internal/codegen/binding/DependencyRequestFactory.java index 87f334320e1..985e4b00f04 100644 --- a/java/dagger/internal/codegen/binding/DependencyRequestFactory.java +++ b/java/dagger/internal/codegen/binding/DependencyRequestFactory.java @@ -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; @@ -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); diff --git a/java/dagger/internal/codegen/binding/KeyFactory.java b/java/dagger/internal/codegen/binding/KeyFactory.java index 10f4a67adbb..2b19e740f8a 100644 --- a/java/dagger/internal/codegen/binding/KeyFactory.java +++ b/java/dagger/internal/codegen/binding/KeyFactory.java @@ -37,6 +37,7 @@ import static javax.lang.model.element.ElementKind.METHOD; import androidx.room.compiler.processing.XProcessingEnv; +import androidx.room.compiler.processing.XType; import com.google.auto.common.MoreTypes; import com.google.common.collect.ImmutableSet; import com.squareup.javapoet.ClassName; @@ -130,6 +131,10 @@ Key forSubcomponentCreatorMethod( return Key.builder(fromJava(resolvedMethod.getReturnType())).build(); } + public Key forSubcomponentCreator(XType creatorType) { + return forSubcomponentCreator(toJavac(creatorType)); + } + public Key forSubcomponentCreator(TypeMirror creatorType) { return Key.builder(fromJava(creatorType)).build(); } diff --git a/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java b/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java index f334ec1fcf2..5b9db70001a 100644 --- a/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java +++ b/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java @@ -21,6 +21,8 @@ import static dagger.internal.codegen.base.DiagnosticFormatting.stripCommonTypePrefixes; import androidx.room.compiler.processing.XMethodElement; +import androidx.room.compiler.processing.XType; +import androidx.room.compiler.processing.compat.XConverters; import com.google.auto.common.MoreElements; import com.google.auto.common.MoreTypes; import dagger.internal.codegen.base.Formatter; @@ -73,6 +75,14 @@ public String format(ExecutableElement method) { return format(method, Optional.empty()); } + /** + * Formats an ExecutableElement as if it were contained within the container, if the container is + * present. + */ + public String format(XMethodElement method, Optional container) { + return format(toJavac(method), container.map(XConverters::toJavac).map(MoreTypes::asDeclared)); + } + /** * Formats an ExecutableElement as if it were contained within the container, if the container is * present. diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java b/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java index 976d3cc0680..fdeeb3244f7 100644 --- a/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java +++ b/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java @@ -16,15 +16,16 @@ package dagger.internal.codegen.componentgenerator; -import static com.google.auto.common.MoreElements.isAnnotationPresent; import static com.google.common.base.CaseFormat.LOWER_CAMEL; import static com.google.common.base.CaseFormat.UPPER_CAMEL; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.Iterables.getOnlyElement; import static com.squareup.javapoet.MethodSpec.constructorBuilder; import static dagger.internal.codegen.binding.ComponentCreatorKind.BUILDER; import static dagger.internal.codegen.javapoet.TypeSpecs.addSupertype; import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom; import static dagger.internal.codegen.writing.ComponentNames.getRootComponentClassName; +import static dagger.internal.codegen.xprocessing.XTypeElements.getAllUnimplementedMethods; import static javax.lang.model.element.Modifier.ABSTRACT; import static javax.lang.model.element.Modifier.FINAL; import static javax.lang.model.element.Modifier.PRIVATE; @@ -32,6 +33,7 @@ import static javax.lang.model.element.Modifier.STATIC; import androidx.room.compiler.processing.XFiler; +import androidx.room.compiler.processing.XMethodElement; import com.google.auto.common.MoreTypes; import com.google.common.base.Ascii; import com.google.common.collect.ImmutableList; @@ -40,7 +42,6 @@ import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; -import dagger.BindsInstance; import dagger.internal.codegen.base.SourceFileGenerator; import dagger.internal.codegen.binding.ComponentCreatorDescriptor; import dagger.internal.codegen.binding.ComponentCreatorKind; @@ -115,7 +116,7 @@ public ImmutableList topLevelTypes(ComponentDescriptor compone boolean noArgFactoryMethod; if (componentDescriptor.creatorDescriptor().isPresent()) { ComponentCreatorDescriptor creatorDescriptor = componentDescriptor.creatorDescriptor().get(); - builderMethodReturnType = ClassName.get(creatorDescriptor.typeElement()); + builderMethodReturnType = creatorDescriptor.typeElement().getClassName(); creatorKind = creatorDescriptor.kind(); noArgFactoryMethod = creatorDescriptor.factoryParameters().isEmpty(); } else { @@ -204,22 +205,15 @@ && isElementAccessibleFrom( private boolean hasBindsInstanceMethods(ComponentDescriptor componentDescriptor) { return componentDescriptor.creatorDescriptor().isPresent() - && elements - .getUnimplementedMethods(componentDescriptor.creatorDescriptor().get().typeElement()) + && getAllUnimplementedMethods(componentDescriptor.creatorDescriptor().get().typeElement()) .stream() .anyMatch(method -> isBindsInstance(method)); } - private static boolean isBindsInstance(ExecutableElement method) { - if (isAnnotationPresent(method, BindsInstance.class)) { - return true; - } - - if (method.getParameters().size() == 1) { - return isAnnotationPresent(method.getParameters().get(0), BindsInstance.class); - } - - return false; + private static boolean isBindsInstance(XMethodElement method) { + return method.hasAnnotation(TypeNames.BINDS_INSTANCE) + || (method.getParameters().size() == 1 + && getOnlyElement(method.getParameters()).hasAnnotation(TypeNames.BINDS_INSTANCE)); } private static MethodSpec builderSetterMethod( diff --git a/java/dagger/internal/codegen/javapoet/BUILD b/java/dagger/internal/codegen/javapoet/BUILD index 98f45af7140..625f8bd35dd 100644 --- a/java/dagger/internal/codegen/javapoet/BUILD +++ b/java/dagger/internal/codegen/javapoet/BUILD @@ -26,6 +26,7 @@ java_library( tags = ["maven:merged"], deps = [ "//java/dagger/internal/codegen/langmodel", + "//java/dagger/internal/codegen/xprocessing", "//java/dagger/internal/guava:base", "//java/dagger/internal/guava:collect", "@google_bazel_common//third_party/java/auto:common", diff --git a/java/dagger/internal/codegen/javapoet/TypeSpecs.java b/java/dagger/internal/codegen/javapoet/TypeSpecs.java index 8ec8747dc10..a7d0c1d147f 100644 --- a/java/dagger/internal/codegen/javapoet/TypeSpecs.java +++ b/java/dagger/internal/codegen/javapoet/TypeSpecs.java @@ -16,6 +16,9 @@ package dagger.internal.codegen.javapoet; +import static androidx.room.compiler.processing.compat.XConverters.toJavac; + +import androidx.room.compiler.processing.XTypeElement; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeSpec; @@ -24,6 +27,18 @@ /** Convenience methods for use with JavaPoet's {@link TypeSpec}. */ public final class TypeSpecs { + /** + * If {@code supertype} is a class, adds it as a superclass for {@code typeBuilder}; if it is an + * interface, adds it as a superinterface. + * + * @return {@code typeBuilder} + */ + @CanIgnoreReturnValue + public static TypeSpec.Builder addSupertype( + TypeSpec.Builder typeBuilder, XTypeElement supertype) { + return addSupertype(typeBuilder, toJavac(supertype)); + } + /** * If {@code supertype} is a class, adds it as a superclass for {@code typeBuilder}; if it is an * interface, adds it as a superinterface. diff --git a/java/dagger/internal/codegen/validation/ComponentDescriptorValidator.java b/java/dagger/internal/codegen/validation/ComponentDescriptorValidator.java index 08d770387ea..d4a3a0d675e 100644 --- a/java/dagger/internal/codegen/validation/ComponentDescriptorValidator.java +++ b/java/dagger/internal/codegen/validation/ComponentDescriptorValidator.java @@ -16,8 +16,10 @@ package dagger.internal.codegen.validation; +import static androidx.room.compiler.processing.XElementKt.isMethod; +import static androidx.room.compiler.processing.XElementKt.isMethodParameter; import static androidx.room.compiler.processing.compat.XConverters.toXProcessing; -import static com.google.auto.common.MoreTypes.asDeclared; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.in; import static com.google.common.collect.Collections2.transform; @@ -29,13 +31,19 @@ import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent; import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet; import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSetMultimap; +import static dagger.internal.codegen.xprocessing.XElements.asMethod; +import static dagger.internal.codegen.xprocessing.XElements.asMethodParameter; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static javax.tools.Diagnostic.Kind.ERROR; +import androidx.room.compiler.processing.XAnnotation; +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.XProcessingEnv; -import com.google.auto.common.MoreElements; -import com.google.auto.common.MoreTypes; +import androidx.room.compiler.processing.XType; import com.google.common.base.Equivalence.Wrapper; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; @@ -56,7 +64,6 @@ import dagger.internal.codegen.javapoet.TypeNames; import dagger.internal.codegen.kotlin.KotlinMetadataUtil; import dagger.internal.codegen.langmodel.DaggerElements; -import dagger.internal.codegen.langmodel.DaggerTypes; import dagger.spi.model.Scope; import java.util.ArrayDeque; import java.util.Collection; @@ -68,13 +75,8 @@ import java.util.Set; import java.util.StringJoiner; import javax.inject.Inject; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; 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; import javax.tools.Diagnostic; @@ -93,7 +95,6 @@ public final class ComponentDescriptorValidator { private final XProcessingEnv processingEnv; private final DaggerElements elements; - private final DaggerTypes types; private final CompilerOptions compilerOptions; private final MethodSignatureFormatter methodSignatureFormatter; private final ComponentHierarchyValidator componentHierarchyValidator; @@ -103,14 +104,12 @@ public final class ComponentDescriptorValidator { ComponentDescriptorValidator( XProcessingEnv processingEnv, DaggerElements elements, - DaggerTypes types, CompilerOptions compilerOptions, MethodSignatureFormatter methodSignatureFormatter, ComponentHierarchyValidator componentHierarchyValidator, KotlinMetadataUtil metadataUtil) { this.processingEnv = processingEnv; this.elements = elements; - this.types = types; this.compilerOptions = compilerOptions; this.methodSignatureFormatter = methodSignatureFormatter; this.componentHierarchyValidator = componentHierarchyValidator; @@ -304,9 +303,9 @@ private void validateCreators(ComponentDescriptor component) { Sets.difference( creatorModuleAndDependencyRequirements, componentModuleAndDependencyRequirements); - DeclaredType container = asDeclared(creator.typeElement().asType()); + XType container = creator.typeElement().getType(); if (!inapplicableRequirementsOnCreator.isEmpty()) { - Collection excessElements = + Collection excessElements = Multimaps.filterKeys( creator.unvalidatedRequirementElements(), in(inapplicableRequirementsOnCreator)) .values(); @@ -337,11 +336,12 @@ private void validateCreators(ComponentDescriptor component) { } // Validate that declared creator requirements (modules, dependencies) have unique types. - ImmutableSetMultimap, Element> declaredRequirementsByType = + ImmutableSetMultimap, XElement> declaredRequirementsByType = Multimaps.filterKeys( creator.unvalidatedRequirementElements(), creatorModuleAndDependencyRequirements::contains) - .entries().stream() + .entries() + .stream() .collect( toImmutableSetMultimap(entry -> entry.getKey().wrappedType(), Entry::getValue)); declaredRequirementsByType @@ -369,40 +369,39 @@ private void validateCreators(ComponentDescriptor component) { // for subcomponents. } - private String formatElement(Element element, DeclaredType container) { + private String formatElement(XElement element, XType container) { // TODO(cgdecker): Extract some or all of this to another class? // But note that it does different formatting for parameters than // DaggerElements.elementToString(Element). - switch (element.getKind()) { - case METHOD: - return methodSignatureFormatter.format( - MoreElements.asExecutable(element), Optional.of(container)); - case PARAMETER: - return formatParameter(MoreElements.asVariable(element), container); - default: - // This method shouldn't be called with any other type of element. - throw new AssertionError(); + if (isMethod(element)) { + return methodSignatureFormatter.format(asMethod(element), Optional.of(container)); + } else if (isMethodParameter(element)) { + return formatParameter(asMethodParameter(element), container); } + // This method shouldn't be called with any other type of element. + throw new AssertionError(); } - private String formatParameter(VariableElement parameter, DeclaredType container) { + private String formatParameter(XExecutableParameterElement parameter, XType container) { // TODO(cgdecker): Possibly leave the type (and annotations?) off of the parameters here and // just use their names, since the type will be redundant in the context of the error message. StringJoiner joiner = new StringJoiner(" "); - parameter.getAnnotationMirrors().stream().map(Object::toString).forEach(joiner::add); - TypeMirror parameterType = resolveParameterType(parameter, container); + parameter.getAllAnnotations().stream() + .map(XAnnotation::getQualifiedName) + .forEach(joiner::add); + XType parameterType = resolveParameterType(parameter, container); return joiner - .add(stripCommonTypePrefixes(parameterType.toString())) - .add(parameter.getSimpleName()) + .add(stripCommonTypePrefixes(parameterType.getTypeName().toString())) + .add(parameter.getName()) .toString(); } - private TypeMirror resolveParameterType(VariableElement parameter, DeclaredType container) { - ExecutableElement method = - MoreElements.asExecutable(parameter.getEnclosingElement()); + private XType resolveParameterType(XExecutableParameterElement parameter, XType container) { + checkArgument(isMethod(parameter.getEnclosingMethodElement())); + XMethodElement method = asMethod(parameter.getEnclosingMethodElement()); int parameterIndex = method.getParameters().indexOf(parameter); - ExecutableType methodType = MoreTypes.asExecutable(types.asMemberOf(container, method)); + XMethodType methodType = method.asMemberOf(container); return methodType.getParameterTypes().get(parameterIndex); } diff --git a/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java b/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java index 6e4aa424a26..05fbdff817b 100644 --- a/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java +++ b/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java @@ -16,7 +16,7 @@ package dagger.internal.codegen.writing; -import static com.google.auto.common.MoreTypes.asDeclared; +import static androidx.room.compiler.processing.XTypeKt.isVoid; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Iterables.getOnlyElement; @@ -31,6 +31,9 @@ import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; +import androidx.room.compiler.processing.XMethodElement; +import androidx.room.compiler.processing.XType; +import androidx.room.compiler.processing.XVariableElement; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; @@ -51,22 +54,18 @@ import dagger.internal.codegen.javapoet.TypeNames; import dagger.internal.codegen.kotlin.KotlinMetadataUtil; import dagger.internal.codegen.langmodel.DaggerElements; -import dagger.internal.codegen.langmodel.DaggerTypes; +import dagger.internal.codegen.xprocessing.MethodSpecs; import java.util.Optional; import java.util.Set; import java.util.stream.Stream; import javax.inject.Inject; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; /** Factory for creating {@link ComponentCreatorImplementation} instances. */ final class ComponentCreatorImplementationFactory { private final ComponentImplementation componentImplementation; private final DaggerElements elements; - private final DaggerTypes types; private final KotlinMetadataUtil metadataUtil; private final ModuleProxies moduleProxies; @@ -74,12 +73,10 @@ final class ComponentCreatorImplementationFactory { ComponentCreatorImplementationFactory( ComponentImplementation componentImplementation, DaggerElements elements, - DaggerTypes types, KotlinMetadataUtil metadataUtil, ModuleProxies moduleProxies) { this.componentImplementation = componentImplementation; this.elements = elements; - this.types = types; this.metadataUtil = metadataUtil; this.moduleProxies = moduleProxies; } @@ -408,18 +405,16 @@ protected ImmutableSet setterMethods() { @Override protected ImmutableMap factoryMethodParameters() { return ImmutableMap.copyOf( - Maps.transformValues( - creatorDescriptor.factoryParameters(), - element -> element.getSimpleName().toString())); + Maps.transformValues(creatorDescriptor.factoryParameters(), XVariableElement::getName)); } - private DeclaredType creatorType() { - return asDeclared(creatorDescriptor.typeElement().asType()); + private XType creatorType() { + return creatorDescriptor.typeElement().getType(); } @Override protected MethodSpec.Builder factoryMethodBuilder() { - return MethodSpec.overriding(creatorDescriptor.factoryMethod(), creatorType(), types); + return MethodSpecs.overriding(creatorDescriptor.factoryMethod(), creatorType()); } private RequirementStatus requirementStatus(ComponentRequirement requirement) { @@ -450,9 +445,9 @@ private boolean isOwnedModule(ComponentRequirement requirement) { @Override protected MethodSpec.Builder setterMethodBuilder(ComponentRequirement requirement) { - ExecutableElement supertypeMethod = creatorDescriptor.setterMethods().get(requirement); - MethodSpec.Builder method = MethodSpec.overriding(supertypeMethod, creatorType(), types); - if (!supertypeMethod.getReturnType().getKind().equals(TypeKind.VOID)) { + XMethodElement supertypeMethod = creatorDescriptor.setterMethods().get(requirement); + MethodSpec.Builder method = MethodSpecs.overriding(supertypeMethod, creatorType()); + if (!isVoid(supertypeMethod.getReturnType())) { // Take advantage of covariant returns so that we don't have to worry about type variables method.returns(componentImplementation.getCreatorName()); } diff --git a/java/dagger/internal/codegen/writing/ComponentImplementation.java b/java/dagger/internal/codegen/writing/ComponentImplementation.java index 5bc6d33ba72..b6b8a6557d6 100644 --- a/java/dagger/internal/codegen/writing/ComponentImplementation.java +++ b/java/dagger/internal/codegen/writing/ComponentImplementation.java @@ -696,8 +696,8 @@ private void createRootComponentFactoryMethod() { if (creatorDescriptor.isPresent()) { ComponentCreatorDescriptor descriptor = creatorDescriptor.get(); creatorKind = descriptor.kind(); - creatorType = ClassName.get(descriptor.typeElement()); - factoryMethodName = descriptor.factoryMethod().getSimpleName().toString(); + creatorType = descriptor.typeElement().getClassName(); + factoryMethodName = descriptor.factoryMethod().getName(); noArgFactoryMethod = descriptor.factoryParameters().isEmpty(); } else { creatorKind = BUILDER; diff --git a/java/dagger/internal/codegen/writing/ComponentNames.java b/java/dagger/internal/codegen/writing/ComponentNames.java index 61c6c085dfc..d7922ff6204 100644 --- a/java/dagger/internal/codegen/writing/ComponentNames.java +++ b/java/dagger/internal/codegen/writing/ComponentNames.java @@ -147,7 +147,7 @@ private static ImmutableMultimap pathsByCreatorKey( if (componentDescriptor.creatorDescriptor().isPresent()) { Key creatorKey = keyFactory.forSubcomponentCreator( - componentDescriptor.creatorDescriptor().get().typeElement().asType()); + componentDescriptor.creatorDescriptor().get().typeElement().getType()); builder.put(creatorKey, componentPath); } }); diff --git a/java/dagger/internal/codegen/xprocessing/MethodSpecs.java b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java new file mode 100644 index 00000000000..f663e555588 --- /dev/null +++ b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2021 The Dagger Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dagger.internal.codegen.xprocessing; + +import static javax.lang.model.element.Modifier.PROTECTED; +import static javax.lang.model.element.Modifier.PUBLIC; + +import androidx.room.compiler.processing.XMethodElement; +import androidx.room.compiler.processing.XMethodType; +import androidx.room.compiler.processing.XType; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.TypeName; + +// TODO(bcorso): Consider moving these methods into XProcessing library. +/** A utility class for {@link MethodSpec} helper methods. */ +public final class MethodSpecs { + + /** Returns a {@link MethodSpec} that overrides the given method. */ + public static MethodSpec.Builder overriding(XMethodElement method, XType owner) { + XMethodType methodType = method.asMemberOf(owner); + MethodSpec.Builder builder = + MethodSpec.methodBuilder(method.getName()) + .addAnnotation(Override.class) + .addTypeVariables(methodType.getTypeVariableNames()) + .varargs(method.isVarArgs()) + .returns(methodType.getReturnType().getTypeName()); + if (method.isPublic()) { + builder.addModifiers(PUBLIC); + } else if (method.isProtected()) { + builder.addModifiers(PROTECTED); + } + for (int i = 0; i < methodType.getParameterTypes().size(); i++) { + String parameterName = method.getParameters().get(i).getName(); + TypeName parameterType = methodType.getParameterTypes().get(i).getTypeName(); + builder.addParameter(ParameterSpec.builder(parameterType, parameterName).build()); + } + method.getThrownTypes().stream().map(XType::getTypeName).forEach(builder::addException); + return builder; + } + + private MethodSpecs() {} +} diff --git a/java/dagger/internal/codegen/xprocessing/XElements.java b/java/dagger/internal/codegen/xprocessing/XElements.java index 1627245c58e..0d99ca419ca 100644 --- a/java/dagger/internal/codegen/xprocessing/XElements.java +++ b/java/dagger/internal/codegen/xprocessing/XElements.java @@ -16,11 +16,18 @@ package dagger.internal.codegen.xprocessing; +import static androidx.room.compiler.processing.XElementKt.isMethod; +import static androidx.room.compiler.processing.XElementKt.isMethodParameter; +import static androidx.room.compiler.processing.XElementKt.isVariableElement; +import static com.google.common.base.Preconditions.checkState; import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet; import androidx.room.compiler.processing.XAnnotated; import androidx.room.compiler.processing.XAnnotation; import androidx.room.compiler.processing.XElement; +import androidx.room.compiler.processing.XExecutableParameterElement; +import androidx.room.compiler.processing.XMethodElement; +import androidx.room.compiler.processing.XVariableElement; import com.google.common.collect.ImmutableSet; import com.squareup.javapoet.ClassName; import java.util.Collection; @@ -30,6 +37,21 @@ /** A utility class for {@link XElement} helper methods. */ public final class XElements { + public static XExecutableParameterElement asMethodParameter(XElement element) { + checkState(isMethodParameter(element)); + return (XExecutableParameterElement) element; + } + + public static XVariableElement asVariable(XElement element) { + checkState(isVariableElement(element)); + return (XVariableElement) element; + } + + public static XMethodElement asMethod(XElement element) { + checkState(isMethod(element)); + return (XMethodElement) element; + } + public static ImmutableSet getAnnotatedAnnotations( XAnnotated annotated, ClassName annotationName) { return annotated.getAllAnnotations().stream()