[Ahead-of-time subcomponents] Add support for missing bindings in abstract
subcomponent implementations. Wrap missing bindings in methods and implement
these methods where possible.
RELNOTES=n/a
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=208056862
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
index 92c0233..8ecf741 100644
--- a/java/dagger/internal/codegen/ComponentBindingExpressions.java
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -30,6 +30,7 @@
import static dagger.model.BindingKind.DELEGATE;
import static dagger.model.BindingKind.MULTIBOUND_MAP;
import static dagger.model.BindingKind.MULTIBOUND_SET;
+import static javax.lang.model.element.Modifier.PUBLIC;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.HashBasedTable;
@@ -40,6 +41,7 @@
import com.squareup.javapoet.MethodSpec;
import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
import dagger.internal.codegen.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import dagger.internal.codegen.MissingBindingMethods.MissingBindingMethod;
import dagger.model.DependencyRequest;
import dagger.model.Key;
import dagger.model.RequestKind;
@@ -248,6 +250,33 @@
.build();
}
+ /**
+ * Returns the implementation of a method encapsulating a missing binding in a supertype
+ * implementation of this subcomponent. Returns {@link Optional#empty()} when the binding cannot
+ * be satisfied by the current binding graph. This is only relevant for ahead-of-time
+ * subcomponents.
+ */
+ Optional<MethodSpec> getMissingBindingMethodImplementation(MissingBindingMethod missingBinding) {
+ // TODO(b/72748365): investigate beder@'s comment about having intermediate component ancestors
+ // satisfy missing bindings of their children with their own missing binding methods so that
+ // we can minimize the cases where we need to reach into doubly-nested descendant component
+ // implementations
+ if (resolvableBinding(missingBinding.key(), missingBinding.kind())) {
+ Expression bindingExpression =
+ getDependencyExpression(
+ missingBinding.key(), missingBinding.kind(), generatedComponentModel.name());
+ MethodSpec unimplementedMethod = missingBinding.unimplementedMethod();
+ return Optional.of(
+ MethodSpec.methodBuilder(unimplementedMethod.name)
+ .addModifiers(PUBLIC)
+ .returns(unimplementedMethod.returnType)
+ .addAnnotation(Override.class)
+ .addStatement("return $L", bindingExpression.codeBlock())
+ .build());
+ }
+ return Optional.empty();
+ }
+
private BindingExpression getBindingExpression(Key key, RequestKind requestKind) {
if (expressions.contains(key, requestKind)) {
return expressions.get(key, requestKind);
@@ -257,7 +286,8 @@
ResolvedBindings resolvedBindings = graph.resolvedBindings(requestKind, key);
expression = Optional.of(createBindingExpression(resolvedBindings, requestKind));
} else if (!resolvableBinding(key, requestKind) && generatedComponentModel.isAbstract()) {
- expression = Optional.of(new MissingBindingExpression(key));
+ expression =
+ Optional.of(new MissingBindingExpression(generatedComponentModel, key, requestKind));
}
if (expression.isPresent()) {
expressions.put(key, requestKind, expression.get());