diff --git a/java/dagger/internal/codegen/binding/CancellationPolicy.java b/java/dagger/internal/codegen/binding/CancellationPolicy.java
new file mode 100644
index 00000000000..7be42ffbbe1
--- /dev/null
+++ b/java/dagger/internal/codegen/binding/CancellationPolicy.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 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.binding;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
+
+import androidx.room.compiler.processing.XAnnotation;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.xprocessing.XAnnotations;
+
+/**
+ * The cancellation policy for a {@link dagger.producers.ProductionComponent}.
+ *
+ *
@see dagger.producers.CancellationPolicy
+ */
+public enum CancellationPolicy {
+ PROPAGATE,
+ IGNORE;
+
+ static CancellationPolicy from(XAnnotation annotation) {
+ checkArgument(XAnnotations.getClassName(annotation).equals(TypeNames.CANCELLATION_POLICY));
+ return valueOf(getSimpleName(annotation.getAsEnum("fromSubcomponents")));
+ }
+}
diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptor.java b/java/dagger/internal/codegen/binding/ComponentDescriptor.java
index a105608b71d..2e5d6b545d9 100644
--- a/java/dagger/internal/codegen/binding/ComponentDescriptor.java
+++ b/java/dagger/internal/codegen/binding/ComponentDescriptor.java
@@ -21,14 +21,27 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotation;
+import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotation;
+import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotations;
+import static dagger.internal.codegen.base.ComponentCreatorAnnotation.creatorAnnotationsFor;
+import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
+import static dagger.internal.codegen.base.Scopes.productionScope;
+import static dagger.internal.codegen.binding.ConfigurationAnnotations.enclosedAnnotatedTypes;
+import static dagger.internal.codegen.binding.ConfigurationAnnotations.isSubcomponentCreator;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.javapoet.TypeNames.isFutureType;
import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
+import static dagger.internal.codegen.xprocessing.XTypeElements.getAllUnimplementedMethods;
+import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
-import androidx.room.compiler.processing.XAnnotation;
import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XMethodElement;
+import androidx.room.compiler.processing.XMethodType;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XType;
import androidx.room.compiler.processing.XTypeElement;
import com.google.auto.value.AutoValue;
import com.google.auto.value.extension.memoized.Memoized;
@@ -45,15 +58,18 @@
import dagger.Module;
import dagger.Subcomponent;
import dagger.internal.codegen.base.ComponentAnnotation;
+import dagger.internal.codegen.base.DaggerSuperficialValidation;
+import dagger.internal.codegen.base.ModuleAnnotation;
import dagger.internal.codegen.javapoet.TypeNames;
import dagger.internal.codegen.model.DependencyRequest;
import dagger.internal.codegen.model.Scope;
-import dagger.internal.codegen.xprocessing.XAnnotations;
+import dagger.internal.codegen.xprocessing.XTypeElements;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
+import javax.inject.Inject;
/**
* A component declaration.
@@ -68,52 +84,54 @@
@CheckReturnValue
@AutoValue
public abstract class ComponentDescriptor {
+ /** The annotation that specifies that {@link #typeElement()} is a component. */
+ public abstract ComponentAnnotation annotation();
+
/**
- * The cancellation policy for a {@link dagger.producers.ProductionComponent}.
- *
- *
@see dagger.producers.CancellationPolicy
+ * The element that defines the component. This is the element to which the {@link #annotation()}
+ * was applied.
*/
- public enum CancellationPolicy {
- PROPAGATE,
- IGNORE;
+ public abstract XTypeElement typeElement();
- private static CancellationPolicy from(XAnnotation annotation) {
- checkArgument(XAnnotations.getClassName(annotation).equals(TypeNames.CANCELLATION_POLICY));
- return valueOf(getSimpleName(annotation.getAsEnum("fromSubcomponents")));
- }
- }
+ /**
+ * The set of component dependencies listed in {@link Component#dependencies} or {@link
+ * dagger.producers.ProductionComponent#dependencies()}.
+ */
+ public abstract ImmutableSet dependencies();
- /** Creates a {@link ComponentDescriptor}. */
- static ComponentDescriptor create(
- ComponentAnnotation componentAnnotation,
- XTypeElement component,
- ImmutableSet componentDependencies,
- ImmutableSet transitiveModules,
- ImmutableMap dependenciesByDependencyMethod,
- ImmutableSet scopes,
- ImmutableSet subcomponentsFromModules,
- ImmutableBiMap subcomponentsByFactoryMethod,
- ImmutableBiMap subcomponentsByBuilderMethod,
- ImmutableSet componentMethods,
- Optional creator) {
- ComponentDescriptor descriptor =
- new AutoValue_ComponentDescriptor(
- componentAnnotation,
- component,
- componentDependencies,
- transitiveModules,
- dependenciesByDependencyMethod,
- scopes,
- subcomponentsFromModules,
- subcomponentsByFactoryMethod,
- subcomponentsByBuilderMethod,
- componentMethods,
- creator);
- return descriptor;
- }
+ /**
+ * The {@link ModuleDescriptor modules} declared in {@link Component#modules()} and reachable by
+ * traversing {@link Module#includes()}.
+ */
+ public abstract ImmutableSet modules();
- /** The annotation that specifies that {@link #typeElement()} is a component. */
- public abstract ComponentAnnotation annotation();
+ /** The scopes of the component. */
+ public abstract ImmutableSet scopes();
+
+ /**
+ * All {@linkplain Subcomponent direct child} components that are declared by a {@linkplain
+ * Module#subcomponents() module's subcomponents}.
+ */
+ abstract ImmutableSet childComponentsDeclaredByModules();
+
+ /**
+ * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
+ * factory method.
+ */
+ public abstract ImmutableBiMap
+ childComponentsDeclaredByFactoryMethods();
+
+ /**
+ * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
+ * builder method.
+ */
+ abstract ImmutableMap
+ childComponentsDeclaredByBuilderEntryPoints();
+
+ public abstract ImmutableSet componentMethods();
+
+ /** Returns a descriptor for the creator type for this component type, if the user defined one. */
+ public abstract Optional creatorDescriptor();
/** Returns {@code true} if this is a subcomponent. */
public final boolean isSubcomponent() {
@@ -136,18 +154,6 @@ public final boolean isRealComponent() {
return annotation().isRealComponent();
}
- /**
- * The element that defines the component. This is the element to which the {@link #annotation()}
- * was applied.
- */
- public abstract XTypeElement typeElement();
-
- /**
- * The set of component dependencies listed in {@link Component#dependencies} or {@link
- * dagger.producers.ProductionComponent#dependencies()}.
- */
- public abstract ImmutableSet dependencies();
-
/** The non-abstract {@link #modules()} and the {@link #dependencies()}. */
public final ImmutableSet dependenciesAndConcreteModules() {
return Stream.concat(
@@ -158,12 +164,6 @@ public final ImmutableSet dependenciesAndConcreteModules()
.collect(toImmutableSet());
}
- /**
- * The {@link ModuleDescriptor modules} declared in {@link Component#modules()} and reachable by
- * traversing {@link Module#includes()}.
- */
- public abstract ImmutableSet modules();
-
/** The types of the {@link #modules()}. */
public final ImmutableSet moduleTypes() {
return modules().stream().map(ModuleDescriptor::moduleElement).collect(toImmutableSet());
@@ -198,13 +198,21 @@ ImmutableSet requirements() {
}
/**
- * This component's {@linkplain #dependencies() dependencies} keyed by each provision or
- * production method defined by that dependency. Note that the dependencies' types are not simply
- * the enclosing type of the method; a method may be declared by a supertype of the actual
- * dependency.
+ * Returns this component's dependencies keyed by its provision/production method.
+ *
+ * Note that the dependencies' types are not simply the enclosing type of the method; a method
+ * may be declared by a supertype of the actual dependency.
*/
- public abstract ImmutableMap
- dependenciesByDependencyMethod();
+ @Memoized
+ public ImmutableMap dependenciesByDependencyMethod() {
+ ImmutableMap.Builder builder = ImmutableMap.builder();
+ for (ComponentRequirement componentDependency : dependencies()) {
+ XTypeElements.getAllMethods(componentDependency.typeElement()).stream()
+ .filter(ComponentDescriptor::isComponentContributionMethod)
+ .forEach(method -> builder.put(method, componentDependency));
+ }
+ return builder.buildOrThrow();
+ }
/** The {@linkplain #dependencies() component dependency} that defines a method. */
public final ComponentRequirement getDependencyThatDefinesMethod(XElement method) {
@@ -216,9 +224,6 @@ public final ComponentRequirement getDependencyThatDefinesMethod(XElement method
return dependenciesByDependencyMethod().get(method);
}
- /** The scopes of the component. */
- public abstract ImmutableSet scopes();
-
/**
* All {@link Subcomponent}s which are direct children of this component. This includes
* subcomponents installed from {@link Module#subcomponents()} as well as subcomponent {@linkplain
@@ -233,19 +238,6 @@ public final ImmutableSet childComponents() {
.build();
}
- /**
- * All {@linkplain Subcomponent direct child} components that are declared by a {@linkplain
- * Module#subcomponents() module's subcomponents}.
- */
- abstract ImmutableSet childComponentsDeclaredByModules();
-
- /**
- * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
- * factory method.
- */
- public abstract ImmutableBiMap
- childComponentsDeclaredByFactoryMethods();
-
/** Returns a map of {@link #childComponents()} indexed by {@link #typeElement()}. */
@Memoized
public ImmutableMap childComponentsByElement() {
@@ -259,13 +251,6 @@ final Optional getFactoryMethodForChildComponent(
childComponentsDeclaredByFactoryMethods().inverse().get(childComponent));
}
- /**
- * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
- * builder method.
- */
- abstract ImmutableBiMap
- childComponentsDeclaredByBuilderEntryPoints();
-
private final Supplier>
childComponentsByBuilderType =
Suppliers.memoize(
@@ -285,8 +270,6 @@ final ComponentDescriptor getChildComponentWithBuilderType(XTypeElement builderT
builderType.getQualifiedName());
}
- public abstract ImmutableSet componentMethods();
-
/** Returns the first component method associated with this binding request, if one exists. */
public Optional firstMatchingComponentMethod(BindingRequest request) {
return Optional.ofNullable(firstMatchingComponentMethods().get(request));
@@ -308,11 +291,6 @@ public final ImmutableSet entryPointMethods() {
.collect(toImmutableSet());
}
- // TODO(gak): Consider making this non-optional and revising the
- // interaction between the spec & generation
- /** Returns a descriptor for the creator type for this component type, if the user defined one. */
- public abstract Optional creatorDescriptor();
-
/**
* Returns {@code true} for components that have a creator, either because the user {@linkplain
* #creatorDescriptor() specified one} or because it's a top-level component with an implicit
@@ -408,4 +386,191 @@ static boolean isComponentContributionMethod(XMethodElement method) {
static boolean isComponentProductionMethod(XMethodElement method) {
return isComponentContributionMethod(method) && isFutureType(method.getReturnType());
}
+
+ /** A factory for creating a {@link ComponentDescriptor}. */
+ public static final class Factory {
+ private final XProcessingEnv processingEnv;
+ private final DependencyRequestFactory dependencyRequestFactory;
+ private final ModuleDescriptor.Factory moduleDescriptorFactory;
+ private final InjectionAnnotations injectionAnnotations;
+ private final DaggerSuperficialValidation superficialValidation;
+
+ @Inject
+ Factory(
+ XProcessingEnv processingEnv,
+ DependencyRequestFactory dependencyRequestFactory,
+ ModuleDescriptor.Factory moduleDescriptorFactory,
+ InjectionAnnotations injectionAnnotations,
+ DaggerSuperficialValidation superficialValidation) {
+ this.processingEnv = processingEnv;
+ this.dependencyRequestFactory = dependencyRequestFactory;
+ this.moduleDescriptorFactory = moduleDescriptorFactory;
+ this.injectionAnnotations = injectionAnnotations;
+ this.superficialValidation = superficialValidation;
+ }
+
+ /** Returns a descriptor for a root component type. */
+ public ComponentDescriptor rootComponentDescriptor(XTypeElement typeElement) {
+ Optional annotation =
+ rootComponentAnnotation(typeElement, superficialValidation);
+ checkArgument(annotation.isPresent(), "%s must have a component annotation", typeElement);
+ return create(typeElement, annotation.get());
+ }
+
+ /** Returns a descriptor for a subcomponent type. */
+ public ComponentDescriptor subcomponentDescriptor(XTypeElement typeElement) {
+ Optional annotation =
+ subcomponentAnnotation(typeElement, superficialValidation);
+ checkArgument(annotation.isPresent(), "%s must have a subcomponent annotation", typeElement);
+ return create(typeElement, annotation.get());
+ }
+
+ /**
+ * Returns a descriptor for a fictional component based on a module type in order to validate
+ * its bindings.
+ */
+ public ComponentDescriptor moduleComponentDescriptor(XTypeElement typeElement) {
+ Optional annotation = moduleAnnotation(typeElement, superficialValidation);
+ checkArgument(annotation.isPresent(), "%s must have a module annotation", typeElement);
+ return create(typeElement, ComponentAnnotation.fromModuleAnnotation(annotation.get()));
+ }
+
+ private ComponentDescriptor create(
+ XTypeElement typeElement, ComponentAnnotation componentAnnotation) {
+ ImmutableSet componentDependencies =
+ componentAnnotation.dependencyTypes().stream()
+ .map(ComponentRequirement::forDependency)
+ .collect(toImmutableSet());
+
+ // Start with the component's modules. For fictional components built from a module, start
+ // with that module.
+ ImmutableSet modules =
+ componentAnnotation.isRealComponent()
+ ? componentAnnotation.modules()
+ : ImmutableSet.of(typeElement);
+
+ ImmutableSet transitiveModules =
+ moduleDescriptorFactory.transitiveModules(modules);
+
+ ImmutableSet.Builder componentMethodsBuilder =
+ ImmutableSet.builder();
+ ImmutableBiMap.Builder
+ subcomponentsByFactoryMethod = ImmutableBiMap.builder();
+ ImmutableMap.Builder
+ subcomponentsByBuilderMethod = ImmutableBiMap.builder();
+ if (componentAnnotation.isRealComponent()) {
+ for (XMethodElement componentMethod : getAllUnimplementedMethods(typeElement)) {
+ ComponentMethodDescriptor componentMethodDescriptor =
+ getDescriptorForComponentMethod(componentAnnotation, typeElement, componentMethod);
+ componentMethodsBuilder.add(componentMethodDescriptor);
+ componentMethodDescriptor
+ .subcomponent()
+ .ifPresent(
+ subcomponent -> {
+ // If the dependency request is present, that means the method returns the
+ // subcomponent factory.
+ if (componentMethodDescriptor.dependencyRequest().isPresent()) {
+ subcomponentsByBuilderMethod.put(componentMethodDescriptor, subcomponent);
+ } else {
+ subcomponentsByFactoryMethod.put(componentMethodDescriptor, subcomponent);
+ }
+ });
+ }
+ }
+
+ // Validation should have ensured that this set will have at most one element.
+ ImmutableSet enclosedCreators =
+ enclosedAnnotatedTypes(typeElement, creatorAnnotationsFor(componentAnnotation));
+ Optional creatorDescriptor =
+ enclosedCreators.isEmpty()
+ ? Optional.empty()
+ : Optional.of(
+ ComponentCreatorDescriptor.create(
+ getOnlyElement(enclosedCreators), dependencyRequestFactory));
+
+ ImmutableSet scopes = injectionAnnotations.getScopes(typeElement);
+ if (componentAnnotation.isProduction()) {
+ scopes =
+ ImmutableSet.builder()
+ .addAll(scopes).add(productionScope(processingEnv))
+ .build();
+ }
+
+ ImmutableSet subcomponentsFromModules =
+ transitiveModules.stream()
+ .flatMap(transitiveModule -> transitiveModule.subcomponentDeclarations().stream())
+ .map(SubcomponentDeclaration::subcomponentType)
+ .map(this::subcomponentDescriptor)
+ .collect(toImmutableSet());
+
+ return new AutoValue_ComponentDescriptor(
+ componentAnnotation,
+ typeElement,
+ componentDependencies,
+ transitiveModules,
+ scopes,
+ subcomponentsFromModules,
+ subcomponentsByFactoryMethod.buildOrThrow(),
+ subcomponentsByBuilderMethod.buildOrThrow(),
+ componentMethodsBuilder.build(),
+ creatorDescriptor);
+ }
+
+ private ComponentMethodDescriptor getDescriptorForComponentMethod(
+ ComponentAnnotation componentAnnotation,
+ XTypeElement componentElement,
+ XMethodElement componentMethod) {
+ ComponentMethodDescriptor.Builder descriptor =
+ ComponentMethodDescriptor.builder(componentMethod);
+
+ XMethodType resolvedComponentMethod = componentMethod.asMemberOf(componentElement.getType());
+ XType returnType = resolvedComponentMethod.getReturnType();
+ if (isDeclared(returnType)
+ && !injectionAnnotations.getQualifier(componentMethod).isPresent()) {
+ XTypeElement returnTypeElement = returnType.getTypeElement();
+ if (returnTypeElement.hasAnyAnnotation(subcomponentAnnotations())) {
+ // It's a subcomponent factory method. There is no dependency request, and there could be
+ // any number of parameters. Just return the descriptor.
+ return descriptor.subcomponent(subcomponentDescriptor(returnTypeElement)).build();
+ }
+ if (isSubcomponentCreator(returnTypeElement)) {
+ descriptor.subcomponent(
+ subcomponentDescriptor(returnTypeElement.getEnclosingTypeElement()));
+ }
+ }
+
+ switch (componentMethod.getParameters().size()) {
+ case 0:
+ checkArgument(
+ !isVoid(returnType), "component method cannot be void: %s", componentMethod);
+ descriptor.dependencyRequest(
+ componentAnnotation.isProduction()
+ ? dependencyRequestFactory.forComponentProductionMethod(
+ componentMethod, resolvedComponentMethod)
+ : dependencyRequestFactory.forComponentProvisionMethod(
+ componentMethod, resolvedComponentMethod));
+ break;
+
+ case 1:
+ checkArgument(
+ isVoid(returnType)
+ // TODO(bcorso): Replace this with isSameType()?
+ || returnType
+ .getTypeName()
+ .equals(resolvedComponentMethod.getParameterTypes().get(0).getTypeName()),
+ "members injection method must return void or parameter type: %s",
+ componentMethod);
+ descriptor.dependencyRequest(
+ dependencyRequestFactory.forComponentMembersInjectionMethod(
+ componentMethod, resolvedComponentMethod));
+ break;
+
+ default:
+ throw new IllegalArgumentException(
+ "component method has too many parameters: " + componentMethod);
+ }
+
+ return descriptor.build();
+ }
+ }
}
diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java b/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java
deleted file mode 100644
index 1d094507896..00000000000
--- a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2014 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.binding;
-
-import static androidx.room.compiler.processing.XTypeKt.isVoid;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotation;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotation;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotations;
-import static dagger.internal.codegen.base.ComponentCreatorAnnotation.creatorAnnotationsFor;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static dagger.internal.codegen.base.Scopes.productionScope;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.enclosedAnnotatedTypes;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.isSubcomponentCreator;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.xprocessing.XTypeElements.getAllUnimplementedMethods;
-import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
-
-import androidx.room.compiler.processing.XMethodElement;
-import androidx.room.compiler.processing.XMethodType;
-import androidx.room.compiler.processing.XProcessingEnv;
-import androidx.room.compiler.processing.XType;
-import androidx.room.compiler.processing.XTypeElement;
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.base.ComponentAnnotation;
-import dagger.internal.codegen.base.DaggerSuperficialValidation;
-import dagger.internal.codegen.base.ModuleAnnotation;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.model.Scope;
-import dagger.internal.codegen.xprocessing.XTypeElements;
-import java.util.Optional;
-import javax.inject.Inject;
-
-/** A factory for {@link ComponentDescriptor}s. */
-public final class ComponentDescriptorFactory {
- private final XProcessingEnv processingEnv;
- private final DependencyRequestFactory dependencyRequestFactory;
- private final ModuleDescriptor.Factory moduleDescriptorFactory;
- private final InjectionAnnotations injectionAnnotations;
- private final DaggerSuperficialValidation superficialValidation;
-
- @Inject
- ComponentDescriptorFactory(
- XProcessingEnv processingEnv,
- DependencyRequestFactory dependencyRequestFactory,
- ModuleDescriptor.Factory moduleDescriptorFactory,
- InjectionAnnotations injectionAnnotations,
- DaggerSuperficialValidation superficialValidation) {
- this.processingEnv = processingEnv;
- this.dependencyRequestFactory = dependencyRequestFactory;
- this.moduleDescriptorFactory = moduleDescriptorFactory;
- this.injectionAnnotations = injectionAnnotations;
- this.superficialValidation = superficialValidation;
- }
-
- /** Returns a descriptor for a root component type. */
- public ComponentDescriptor rootComponentDescriptor(XTypeElement typeElement) {
- Optional annotation =
- rootComponentAnnotation(typeElement, superficialValidation);
- checkArgument(annotation.isPresent(), "%s must have a component annotation", typeElement);
- return create(typeElement, annotation.get());
- }
-
- /** Returns a descriptor for a subcomponent type. */
- public ComponentDescriptor subcomponentDescriptor(XTypeElement typeElement) {
- Optional annotation =
- subcomponentAnnotation(typeElement, superficialValidation);
- checkArgument(annotation.isPresent(), "%s must have a subcomponent annotation", typeElement);
- return create(typeElement, annotation.get());
- }
-
- /**
- * Returns a descriptor for a fictional component based on a module type in order to validate its
- * bindings.
- */
- public ComponentDescriptor moduleComponentDescriptor(XTypeElement typeElement) {
- Optional annotation = moduleAnnotation(typeElement, superficialValidation);
- checkArgument(annotation.isPresent(), "%s must have a module annotation", typeElement);
- return create(typeElement, ComponentAnnotation.fromModuleAnnotation(annotation.get()));
- }
-
- private ComponentDescriptor create(
- XTypeElement typeElement, ComponentAnnotation componentAnnotation) {
- ImmutableSet componentDependencies =
- componentAnnotation.dependencyTypes().stream()
- .map(ComponentRequirement::forDependency)
- .collect(toImmutableSet());
-
- ImmutableMap.Builder dependenciesByDependencyMethod =
- ImmutableMap.builder();
- for (ComponentRequirement componentDependency : componentDependencies) {
- XTypeElements.getAllMethods(componentDependency.typeElement()).stream()
- .filter(ComponentDescriptor::isComponentContributionMethod)
- .forEach(method -> dependenciesByDependencyMethod.put(method, componentDependency));
- }
-
- // Start with the component's modules. For fictional components built from a module, start with
- // that module.
- ImmutableSet modules =
- componentAnnotation.isRealComponent()
- ? componentAnnotation.modules()
- : ImmutableSet.of(typeElement);
-
- ImmutableSet transitiveModules =
- moduleDescriptorFactory.transitiveModules(modules);
-
- ImmutableSet subcomponentsFromModules =
- transitiveModules.stream()
- .flatMap(transitiveModule -> transitiveModule.subcomponentDeclarations().stream())
- .map(SubcomponentDeclaration::subcomponentType)
- .map(this::subcomponentDescriptor)
- .collect(toImmutableSet());
-
- ImmutableSet.Builder componentMethodsBuilder =
- ImmutableSet.builder();
- ImmutableBiMap.Builder
- subcomponentsByFactoryMethod = ImmutableBiMap.builder();
- ImmutableBiMap.Builder
- subcomponentsByBuilderMethod = ImmutableBiMap.builder();
- if (componentAnnotation.isRealComponent()) {
- for (XMethodElement componentMethod : getAllUnimplementedMethods(typeElement)) {
- ComponentMethodDescriptor componentMethodDescriptor =
- getDescriptorForComponentMethod(componentAnnotation, typeElement, componentMethod);
- componentMethodsBuilder.add(componentMethodDescriptor);
- componentMethodDescriptor
- .subcomponent()
- .ifPresent(
- subcomponent -> {
- // If the dependency request is present, that means the method returns the
- // subcomponent factory.
- if (componentMethodDescriptor.dependencyRequest().isPresent()) {
- subcomponentsByBuilderMethod.put(componentMethodDescriptor, subcomponent);
- } else {
- subcomponentsByFactoryMethod.put(componentMethodDescriptor, subcomponent);
- }
- });
- }
- }
-
- // Validation should have ensured that this set will have at most one element.
- ImmutableSet enclosedCreators =
- enclosedAnnotatedTypes(typeElement, creatorAnnotationsFor(componentAnnotation));
- Optional creatorDescriptor =
- enclosedCreators.isEmpty()
- ? Optional.empty()
- : Optional.of(
- ComponentCreatorDescriptor.create(
- getOnlyElement(enclosedCreators), dependencyRequestFactory));
-
- ImmutableSet scopes = injectionAnnotations.getScopes(typeElement);
- if (componentAnnotation.isProduction()) {
- scopes =
- ImmutableSet.builder().addAll(scopes).add(productionScope(processingEnv)).build();
- }
-
- return ComponentDescriptor.create(
- componentAnnotation,
- typeElement,
- componentDependencies,
- transitiveModules,
- dependenciesByDependencyMethod.build(),
- scopes,
- subcomponentsFromModules,
- subcomponentsByFactoryMethod.build(),
- subcomponentsByBuilderMethod.build(),
- componentMethodsBuilder.build(),
- creatorDescriptor);
- }
-
- private ComponentMethodDescriptor getDescriptorForComponentMethod(
- ComponentAnnotation componentAnnotation,
- XTypeElement componentElement,
- XMethodElement componentMethod) {
- ComponentMethodDescriptor.Builder descriptor =
- ComponentMethodDescriptor.builder(componentMethod);
-
- XMethodType resolvedComponentMethod = componentMethod.asMemberOf(componentElement.getType());
- XType returnType = resolvedComponentMethod.getReturnType();
- if (isDeclared(returnType) && !injectionAnnotations.getQualifier(componentMethod).isPresent()) {
- XTypeElement returnTypeElement = returnType.getTypeElement();
- if (returnTypeElement.hasAnyAnnotation(subcomponentAnnotations())) {
- // It's a subcomponent factory method. There is no dependency request, and there could be
- // any number of parameters. Just return the descriptor.
- return descriptor.subcomponent(subcomponentDescriptor(returnTypeElement)).build();
- }
- if (isSubcomponentCreator(returnTypeElement)) {
- descriptor.subcomponent(
- subcomponentDescriptor(returnTypeElement.getEnclosingTypeElement()));
- }
- }
-
- switch (componentMethod.getParameters().size()) {
- case 0:
- checkArgument(!isVoid(returnType), "component method cannot be void: %s", componentMethod);
- descriptor.dependencyRequest(
- componentAnnotation.isProduction()
- ? dependencyRequestFactory.forComponentProductionMethod(
- componentMethod, resolvedComponentMethod)
- : dependencyRequestFactory.forComponentProvisionMethod(
- componentMethod, resolvedComponentMethod));
- break;
-
- case 1:
- checkArgument(
- isVoid(returnType)
- // TODO(bcorso): Replace this with isSameType()?
- || returnType
- .getTypeName()
- .equals(resolvedComponentMethod.getParameterTypes().get(0).getTypeName()),
- "members injection method must return void or parameter type: %s",
- componentMethod);
- descriptor.dependencyRequest(
- dependencyRequestFactory.forComponentMembersInjectionMethod(
- componentMethod, resolvedComponentMethod));
- break;
-
- default:
- throw new IllegalArgumentException(
- "component method has too many parameters: " + componentMethod);
- }
-
- return descriptor.build();
- }
-}
diff --git a/java/dagger/internal/codegen/javac/BUILD b/java/dagger/internal/codegen/javac/BUILD
index ce31e42cec4..325dc99d0dc 100644
--- a/java/dagger/internal/codegen/javac/BUILD
+++ b/java/dagger/internal/codegen/javac/BUILD
@@ -25,9 +25,7 @@ java_library(
plugins = ["//java/dagger/internal/codegen:component-codegen"],
deps = [
"//java/dagger:core",
- "//java/dagger/internal/codegen/binding",
"//java/dagger/internal/codegen/compileroption",
- "//java/dagger/internal/codegen/langmodel",
"//java/dagger/internal/codegen/xprocessing",
"//third_party/java/guava/collect",
],
diff --git a/java/dagger/internal/codegen/javac/JavacPluginModule.java b/java/dagger/internal/codegen/javac/JavacPluginModule.java
index 5198164409d..f9e6da9bced 100644
--- a/java/dagger/internal/codegen/javac/JavacPluginModule.java
+++ b/java/dagger/internal/codegen/javac/JavacPluginModule.java
@@ -24,15 +24,13 @@
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
-import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
import dagger.internal.codegen.compileroption.CompilerOptions;
import javax.lang.model.util.Elements; // ALLOW_TYPES_ELEMENTS
import javax.lang.model.util.Types; // ALLOW_TYPES_ELEMENTS
/**
- * A module that provides a {@link BindingGraphFactory} and {@link ComponentDescriptorFactory} for
- * use in {@code javac} plugins. Requires a binding for the {@code javac} {@link Context}.
+ * A module that provides a {@link XMessager}, {@link XProcessingEnv}, and {@link CompilerOptions}
+ * for use in {@code javac} plugins. Requires a binding for the {@code javac} {@link Context}.
*/
@Module(includes = JavacPluginModule.BindsModule.class)
public final class JavacPluginModule {
diff --git a/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java b/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
index 3280b4f79da..0b8a5024bf1 100644
--- a/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
+++ b/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
@@ -40,7 +40,7 @@
import dagger.internal.codegen.binding.BindingDeclaration;
import dagger.internal.codegen.binding.BindingGraphFactory;
import dagger.internal.codegen.binding.BindingNode;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
+import dagger.internal.codegen.binding.ComponentDescriptor;
import dagger.internal.codegen.binding.ModuleDescriptor;
import dagger.internal.codegen.javac.JavacPluginModule;
import dagger.internal.codegen.javapoet.TypeNames;
@@ -64,7 +64,7 @@ public class DaggerKythePlugin extends Plugin.Scanner {
// TODO(ronshapiro): use flogger
private static final Logger logger = Logger.getLogger(DaggerKythePlugin.class.getCanonicalName());
private FactEmitter emitter;
- @Inject ComponentDescriptorFactory componentDescriptorFactory;
+ @Inject ComponentDescriptor.Factory componentDescriptorFactory;
@Inject BindingGraphFactory bindingGraphFactory;
@Inject XProcessingEnv xProcessingEnv;
diff --git a/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java b/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java
index 7a7e180da9d..864bd768d28 100644
--- a/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java
+++ b/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java
@@ -28,7 +28,6 @@
import dagger.internal.codegen.base.SourceFileGenerator;
import dagger.internal.codegen.binding.BindingGraph;
import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
import dagger.internal.codegen.validation.ComponentCreatorValidator;
import dagger.internal.codegen.validation.ComponentValidator;
import dagger.internal.codegen.validation.ValidationReport;
@@ -52,7 +51,7 @@ final class ComponentHjarProcessingStep extends TypeCheckingProcessingStep componentGenerator;
@Inject
@@ -60,7 +59,7 @@ final class ComponentHjarProcessingStep extends TypeCheckingProcessingStep componentGenerator) {
this.messager = messager;
this.componentValidator = componentValidator;
diff --git a/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java b/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java
index 5b17c0061b3..168e8946f18 100644
--- a/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java
+++ b/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java
@@ -34,7 +34,6 @@
import dagger.internal.codegen.binding.BindingGraph;
import dagger.internal.codegen.binding.BindingGraphFactory;
import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
import dagger.internal.codegen.validation.BindingGraphValidator;
import dagger.internal.codegen.validation.ComponentCreatorValidator;
import dagger.internal.codegen.validation.ComponentDescriptorValidator;
@@ -52,7 +51,7 @@ final class ComponentProcessingStep extends TypeCheckingProcessingStep componentGenerator;
private final BindingGraphValidator bindingGraphValidator;
@@ -63,7 +62,7 @@ final class ComponentProcessingStep extends TypeCheckingProcessingStep componentGenerator,
BindingGraphValidator bindingGraphValidator) {
@@ -132,7 +131,10 @@ private void processSubcomponent(XTypeElement subcomponent) {
return;
}
BindingGraph fullBindingGraph = bindingGraphFactory.create(subcomponentDescriptor, true);
- boolean isValid = bindingGraphValidator.isValid(fullBindingGraph.topLevelBindingGraph());
+ // In this case, we don't actually care about the return value. The important part here is that
+ // BindingGraphValidator#isValid() runs all of the SPI plugins and reports any errors.
+ // TODO(bcorso): Add a separate API with no return value for this particular case.
+ boolean unusedIsValid = bindingGraphValidator.isValid(fullBindingGraph.topLevelBindingGraph());
}
private void generateComponent(BindingGraph bindingGraph) {
diff --git a/java/dagger/internal/codegen/validation/ModuleValidator.java b/java/dagger/internal/codegen/validation/ModuleValidator.java
index a1d9b0d1167..38bce2b44a1 100644
--- a/java/dagger/internal/codegen/validation/ModuleValidator.java
+++ b/java/dagger/internal/codegen/validation/ModuleValidator.java
@@ -58,7 +58,7 @@
import dagger.internal.codegen.base.DaggerSuperficialValidation;
import dagger.internal.codegen.base.ModuleKind;
import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
+import dagger.internal.codegen.binding.ComponentDescriptor;
import dagger.internal.codegen.binding.InjectionAnnotations;
import dagger.internal.codegen.binding.MethodSignatureFormatter;
import dagger.internal.codegen.javapoet.TypeNames;
@@ -109,7 +109,7 @@ public final class ModuleValidator {
private final AnyBindingMethodValidator anyBindingMethodValidator;
private final MethodSignatureFormatter methodSignatureFormatter;
- private final ComponentDescriptorFactory componentDescriptorFactory;
+ private final ComponentDescriptor.Factory componentDescriptorFactory;
private final BindingGraphFactory bindingGraphFactory;
private final BindingGraphValidator bindingGraphValidator;
private final InjectionAnnotations injectionAnnotations;
@@ -122,7 +122,7 @@ public final class ModuleValidator {
ModuleValidator(
AnyBindingMethodValidator anyBindingMethodValidator,
MethodSignatureFormatter methodSignatureFormatter,
- ComponentDescriptorFactory componentDescriptorFactory,
+ ComponentDescriptor.Factory componentDescriptorFactory,
BindingGraphFactory bindingGraphFactory,
BindingGraphValidator bindingGraphValidator,
InjectionAnnotations injectionAnnotations,
diff --git a/java/dagger/internal/codegen/writing/ComponentImplementation.java b/java/dagger/internal/codegen/writing/ComponentImplementation.java
index dc7baf83bdd..5851818251b 100644
--- a/java/dagger/internal/codegen/writing/ComponentImplementation.java
+++ b/java/dagger/internal/codegen/writing/ComponentImplementation.java
@@ -73,9 +73,9 @@
import dagger.internal.codegen.binding.BindingGraph;
import dagger.internal.codegen.binding.BindingNode;
import dagger.internal.codegen.binding.BindingRequest;
+import dagger.internal.codegen.binding.CancellationPolicy;
import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptor.CancellationPolicy;
import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.binding.ComponentRequirement;
import dagger.internal.codegen.binding.KeyVariableNamer;