Split HasBindingExpressions into GeneratedComponentModel and ComponentBindingExpressions.
Make SingleBindingExpression a subclass of BindingExpression for one binding, so that ComponentBindingExpressions can be a composite BindingExpression.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=165367432
diff --git a/java/dagger/internal/codegen/AbstractComponentWriter.java b/java/dagger/internal/codegen/AbstractComponentWriter.java
index da72571..235a226 100644
--- a/java/dagger/internal/codegen/AbstractComponentWriter.java
+++ b/java/dagger/internal/codegen/AbstractComponentWriter.java
@@ -113,7 +113,7 @@
import javax.lang.model.util.Types;
/** Creates the implementation class for a component or subcomponent. */
-abstract class AbstractComponentWriter implements HasBindingExpressions {
+abstract class AbstractComponentWriter implements GeneratedComponentModel {
// TODO(dpb): Make all these fields private after refactoring is complete.
protected final Elements elements;
protected final Types types;
@@ -125,10 +125,9 @@
protected final TypeSpec.Builder component;
private final UniqueNameSet componentFieldNames = new UniqueNameSet();
private final UniqueNameSet componentMethodNames = new UniqueNameSet();
- // TODO(user): Merge these two maps if we refactor BindingKey to allow us to unify
- // these two key spaces
- private final Map<BindingKey, BindingExpression> bindingExpressions = new LinkedHashMap<>();
- private final Map<BindingKey, BindingExpression> producerFromProviderBindingExpressions =
+ private final ComponentBindingExpressions bindingExpressions;
+ // TODO(user): Merge into ComponentBindingExpressions after we refactor BindingKey.
+ private final Map<BindingKey, ProducerBindingExpression> producerFromProviderBindingExpressions =
new LinkedHashMap<>();
private final List<CodeBlock> initializations = new ArrayList<>();
protected final List<MethodSpec> interfaceMethods = new ArrayList<>();
@@ -169,7 +168,8 @@
ClassName name,
BindingGraph graph,
ImmutableMap<ComponentDescriptor, String> subcomponentNames,
- OptionalFactories optionalFactories) {
+ OptionalFactories optionalFactories,
+ ComponentBindingExpressions bindingExpressions) {
this.types = types;
this.elements = elements;
this.keyFactory = keyFactory;
@@ -179,11 +179,13 @@
this.graph = graph;
this.subcomponentNames = subcomponentNames;
this.optionalFactories = optionalFactories;
+ this.bindingExpressions = bindingExpressions;
this.bindingExpressionFactory =
new BindingExpression.Factory(
compilerOptions,
name,
componentFieldNames,
+ bindingExpressions,
this,
childComponentNames(keyFactory, subcomponentNames),
graph,
@@ -214,7 +216,8 @@
name,
graph,
parent.subcomponentNames,
- parent.optionalFactories);
+ parent.optionalFactories,
+ parent.bindingExpressions.forChildComponent());
}
protected final ClassName componentDefinitionTypeName() {
@@ -270,11 +273,6 @@
return FieldSpec.builder(type, componentFieldNames.getUniqueName(name));
}
- @Override
- public BindingExpression getBindingExpression(BindingKey key) {
- return bindingExpressions.get(key);
- }
-
/** Adds the given code block to the initialize methods of the component. */
@Override
public void addInitialization(CodeBlock codeBlock) {
@@ -447,7 +445,7 @@
Optional<BindingExpression> staticBindingExpression =
bindingExpressionFactory.forStaticMethod(resolvedBindings);
if (staticBindingExpression.isPresent()) {
- bindingExpressions.put(resolvedBindings.bindingKey(), staticBindingExpression.get());
+ bindingExpressions.addBindingExpression(staticBindingExpression.get());
return;
}
@@ -457,8 +455,7 @@
}
// TODO(gak): get rid of the field for unscoped delegated bindings
- bindingExpressions.put(
- resolvedBindings.bindingKey(), bindingExpressionFactory.forField(resolvedBindings));
+ bindingExpressions.addBindingExpression(bindingExpressionFactory.forField(resolvedBindings));
}
private boolean useRawType(Binding binding) {
@@ -510,7 +507,8 @@
"return $N($N)", getMembersInjectionMethod(binding.key()), parameter);
}
} else {
- interfaceMethod.addStatement("return $L", getDependencyExpression(interfaceRequest));
+ interfaceMethod.addStatement(
+ "return $L", bindingExpressions.getDependencyExpression(interfaceRequest, name));
}
interfaceMethods.add(interfaceMethod.build());
}
@@ -593,12 +591,11 @@
component.addMethods(interfaceMethods);
}
- // TODO(user): Move this method onto FieldBasedBindingExpression or subtypes of it.
@Override
public CodeBlock getFieldInitialization(FrameworkInstanceBindingExpression bindingExpression) {
if (bindingExpression.isProducerFromProvider()) {
- return getDependencyExpression(
- FrameworkDependency.create(bindingExpression.bindingKey(), PRODUCTION));
+ return bindingExpressions.getDependencyExpression(
+ FrameworkDependency.create(bindingExpression.bindingKey(), PRODUCTION), name);
}
switch (bindingExpression.bindingKey().kind()) {
@@ -611,7 +608,8 @@
}
}
- private CodeBlock contributionBindingInitialization(BindingExpression bindingExpression) {
+ private CodeBlock contributionBindingInitialization(
+ FrameworkInstanceBindingExpression bindingExpression) {
ContributionBinding binding =
graph.resolvedBindings().get(bindingExpression.bindingKey()).contributionBinding();
switch (binding.factoryCreationStrategy()) {
@@ -620,7 +618,8 @@
CodeBlock.of(
"($T) $L",
binding.bindingType().frameworkClass(),
- getDependencyExpression(getOnlyElement(binding.frameworkDependencies())));
+ bindingExpressions.getDependencyExpression(
+ getOnlyElement(binding.frameworkDependencies()), name));
return decorateForScope(delegatingCodeBlock, binding.scope());
case SINGLETON_INSTANCE:
checkState(binding.scope().isPresent());
@@ -677,9 +676,7 @@
instance,
membersInjectedType,
types,
- request ->
- getBindingExpression(request.bindingKey())
- .getDependencyArgumentExpression(request, name)));
+ request -> bindingExpressions.getDependencyArgumentExpression(request, name)));
method.addStatement("return $L", instance);
return method.build();
@@ -694,7 +691,8 @@
throw new IllegalArgumentException(binding.key().toString());
}
- private CodeBlock membersInjectionBindingInitialization(BindingExpression bindingExpression) {
+ private CodeBlock membersInjectionBindingInitialization(
+ FrameworkInstanceBindingExpression bindingExpression) {
BindingKey bindingKey = bindingExpression.bindingKey();
MembersInjectionBinding binding =
graph.resolvedBindings().get(bindingKey).membersInjectionBinding().get();
@@ -702,7 +700,7 @@
return membersInjectorForBindingInitialization(binding);
}
- private BindingExpression getProducerFromProviderBindingExpression(
+ private ProducerBindingExpression getProducerFromProviderBindingExpression(
FrameworkDependency frameworkDependency) {
checkState(isProducerFromProvider(frameworkDependency));
return producerFromProviderBindingExpressions.computeIfAbsent(
@@ -885,7 +883,7 @@
return CodeBlock.of(
"$T.create($L)",
mapFactoryClassName(binding),
- getDependencyExpression(frameworkDependency));
+ bindingExpressions.getDependencyExpression(frameworkDependency, name));
case SYNTHETIC_MULTIBOUND_SET:
return factoryForSetMultibindingInitialization(binding);
@@ -951,8 +949,8 @@
private CodeBlock getDependencyArgument(FrameworkDependency frameworkDependency) {
return isProducerFromProvider(frameworkDependency)
? getProducerFromProviderBindingExpression(frameworkDependency)
- .getDependencyExpression(frameworkDependency, name)
- : getDependencyExpression(frameworkDependency);
+ .getDependencyExpression(frameworkDependency.dependencyRequestKind(), name)
+ : bindingExpressions.getDependencyExpression(frameworkDependency, name);
}
private CodeBlock factoryForSetMultibindingInitialization(ContributionBinding binding) {
@@ -1172,14 +1170,4 @@
binding, getOnlyElement(getDependencyArguments(binding)));
}
}
-
- private CodeBlock getDependencyExpression(FrameworkDependency frameworkDependency) {
- return getBindingExpression(frameworkDependency.bindingKey())
- .getDependencyExpression(frameworkDependency, name);
- }
-
- private CodeBlock getDependencyExpression(DependencyRequest dependencyRequest) {
- return getBindingExpression(dependencyRequest.bindingKey())
- .getDependencyExpression(dependencyRequest, name);
- }
}
diff --git a/java/dagger/internal/codegen/BindingExpression.java b/java/dagger/internal/codegen/BindingExpression.java
index 720da39..e8df4f6 100644
--- a/java/dagger/internal/codegen/BindingExpression.java
+++ b/java/dagger/internal/codegen/BindingExpression.java
@@ -17,24 +17,19 @@
package dagger.internal.codegen;
import static com.google.common.base.Preconditions.checkNotNull;
-import static dagger.internal.codegen.Accessibility.isRawTypeAccessible;
-import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
import static dagger.internal.codegen.AnnotationSpecs.Suppression.RAWTYPES;
import static dagger.internal.codegen.MemberSelect.staticMemberSelect;
import static dagger.internal.codegen.TypeNames.PRODUCER;
-import static dagger.internal.codegen.TypeNames.rawTypeName;
import static javax.lang.model.element.Modifier.PRIVATE;
import com.google.common.collect.ImmutableMap;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.TypeName;
import java.util.Optional;
-import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
-/** The code expressions to declare, initialize, and/or access a binding in a component. */
+/** A factory of code expressions used to access a single binding in a component. */
abstract class BindingExpression {
private final BindingKey bindingKey;
@@ -48,51 +43,21 @@
}
/**
- * Returns an expression that evaluates to the value of a dependency request.
- *
- * @param requestingClass the class that will contain the expression
- */
- abstract CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass);
-
- /**
- * Returns an expression that evaluates to the value of a framework dependency.
+ * Returns an expression that evaluates to the value of a request for a given kind of dependency
+ * on this binding.
*
* @param requestingClass the class that will contain the expression
*/
abstract CodeBlock getDependencyExpression(
- FrameworkDependency frameworkDependency, ClassName requestingClass);
-
- /**
- * Returns an expression that evaluates to the value of a dependency request, for passing to a
- * binding method, an {@code @Inject}-annotated constructor or member, or a proxy for one.
- *
- * <p>If the method is a generated static {@link InjectionMethods injection method}, each
- * parameter will be {@link Object} if the dependency's raw type is inaccessible. If that is the
- * case for this dependency, the returned expression will use a cast to evaluate to the raw type.
- *
- * @param requestingClass the class that will contain the expression
- */
- // TODO(b/64024402) Merge with getDependencyExpression(DependencyRequest, ClassName) if possible.
- CodeBlock getDependencyArgumentExpression(
- DependencyRequest dependencyRequest, ClassName requestingClass) {
- CodeBlock.Builder argument = CodeBlock.builder();
-
- TypeMirror dependencyType = dependencyRequest.key().type();
- if (!isTypeAccessibleFrom(dependencyType, requestingClass.packageName())
- && isRawTypeAccessible(dependencyType, requestingClass.packageName())) {
- argument.add("($T) ", rawTypeName(TypeName.get(dependencyType)));
- }
-
- argument.add(getDependencyExpression(dependencyRequest, requestingClass));
- return argument.build();
- }
+ DependencyRequest.Kind requestKind, ClassName requestingClass);
/** Factory for building a {@link BindingExpression}. */
static final class Factory {
private final CompilerOptions compilerOptions;
private final ClassName componentName;
private final UniqueNameSet componentFieldNames;
- private final HasBindingExpressions hasBindingExpressions;
+ private final ComponentBindingExpressions componentBindingExpressions;
+ private final GeneratedComponentModel generatedComponentModel;
private final ImmutableMap<BindingKey, String> subcomponentNames;
private final BindingGraph graph;
private final Elements elements;
@@ -101,14 +66,16 @@
CompilerOptions compilerOptions,
ClassName componentName,
UniqueNameSet componentFieldNames,
- HasBindingExpressions hasBindingExpressions,
+ ComponentBindingExpressions componentBindingExpressions,
+ GeneratedComponentModel generatedComponentModel,
ImmutableMap<BindingKey, String> subcomponentNames,
BindingGraph graph,
Elements elements) {
this.compilerOptions = checkNotNull(compilerOptions);
this.componentName = checkNotNull(componentName);
this.componentFieldNames = checkNotNull(componentFieldNames);
- this.hasBindingExpressions = checkNotNull(hasBindingExpressions);
+ this.componentBindingExpressions = checkNotNull(componentBindingExpressions);
+ this.generatedComponentModel = checkNotNull(generatedComponentModel);
this.subcomponentNames = checkNotNull(subcomponentNames);
this.graph = checkNotNull(graph);
this.elements = checkNotNull(elements);
@@ -121,20 +88,18 @@
return create(resolvedBindings, Optional.of(fieldSpec), memberSelect);
}
- BindingExpression forProducerFromProviderField(ResolvedBindings resolvedBindings) {
+ ProducerBindingExpression forProducerFromProviderField(ResolvedBindings resolvedBindings) {
FieldSpec fieldSpec = generateFrameworkField(resolvedBindings, Optional.of(PRODUCER));
MemberSelect memberSelect = MemberSelect.localField(componentName, fieldSpec.name);
return new ProducerBindingExpression(
resolvedBindings.bindingKey(),
Optional.of(fieldSpec),
- hasBindingExpressions,
+ generatedComponentModel,
memberSelect,
true);
}
- /**
- * Creates a binding expression for a static method call.
- */
+ /** Creates a binding expression for a static method call. */
Optional<BindingExpression> forStaticMethod(ResolvedBindings resolvedBindings) {
return staticMemberSelect(resolvedBindings)
.map(memberSelect -> create(resolvedBindings, Optional.empty(), memberSelect));
@@ -178,17 +143,17 @@
switch (resolvedBindings.bindingType()) {
case MEMBERS_INJECTION:
return new MembersInjectorBindingExpression(
- bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+ bindingKey, fieldSpec, generatedComponentModel, memberSelect);
case PRODUCTION:
return new ProducerBindingExpression(
- bindingKey, fieldSpec, hasBindingExpressions, memberSelect, false);
+ bindingKey, fieldSpec, generatedComponentModel, memberSelect, false);
case PROVISION:
ProvisionBinding provisionBinding =
(ProvisionBinding) resolvedBindings.contributionBinding();
ProviderBindingExpression providerBindingExpression =
new ProviderBindingExpression(
- bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+ bindingKey, fieldSpec, generatedComponentModel, memberSelect);
switch (provisionBinding.bindingKind()) {
case SUBCOMPONENT_BUILDER:
@@ -198,12 +163,12 @@
return new SetBindingExpression(
provisionBinding,
graph,
- hasBindingExpressions,
+ componentBindingExpressions,
providerBindingExpression,
elements);
case SYNTHETIC_OPTIONAL_BINDING:
return new OptionalBindingExpression(
- provisionBinding, providerBindingExpression, hasBindingExpressions);
+ provisionBinding, providerBindingExpression, componentBindingExpressions);
case INJECTION:
case PROVISION:
if (!provisionBinding.scope().isPresent()
@@ -213,7 +178,8 @@
compilerOptions,
provisionBinding,
providerBindingExpression,
- hasBindingExpressions);
+ componentBindingExpressions,
+ generatedComponentModel);
}
// fall through
default:
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
new file mode 100644
index 0000000..32f053c
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 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;
+
+import static dagger.internal.codegen.Accessibility.isRawTypeAccessible;
+import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
+import static dagger.internal.codegen.TypeNames.rawTypeName;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
+import java.util.HashMap;
+import java.util.Map;
+import javax.lang.model.type.TypeMirror;
+
+/** A factory of code expressions used to access any binding available to a component. */
+final class ComponentBindingExpressions {
+
+ // TODO(dpb): Can this use a flattened ImmutableMap, built from its parents? Maybe make
+ // BindingExpression.Factory create it.
+
+ /**
+ * A list of binding expression maps. The first element contains the bindings owned by this
+ * component; the second contains the bindings owned by its parent; and so on.
+ */
+ private final ImmutableList<Map<BindingKey, BindingExpression>> bindingExpressionsMaps;
+
+ private ComponentBindingExpressions(
+ ImmutableList<Map<BindingKey, BindingExpression>> bindingExpressionsMaps) {
+ this.bindingExpressionsMaps = bindingExpressionsMaps;
+ }
+
+ ComponentBindingExpressions() {
+ this(ImmutableList.of(newBindingExpressionMap()));
+ }
+
+ /**
+ * Returns an expression that evaluates to the value of a dependency request for a binding owned
+ * by this component or an ancestor.
+ *
+ * @param requestingClass the class that will contain the expression
+ * @throws IllegalStateException if there is no binding expression that satisfies the dependency
+ * request
+ */
+ CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+ return getBindingExpression(request.bindingKey())
+ .getDependencyExpression(request.kind(), requestingClass);
+ }
+
+ /**
+ * Returns an expression that evaluates to the value of a framework dependency for a binding owned
+ * in this component or an ancestor.
+ *
+ * @param requestingClass the class that will contain the expression
+ * @throws IllegalStateException if there is no binding expression that satisfies the dependency
+ * request
+ */
+ CodeBlock getDependencyExpression(
+ FrameworkDependency frameworkDependency, ClassName requestingClass) {
+ return getBindingExpression(frameworkDependency.bindingKey())
+ .getDependencyExpression(frameworkDependency.dependencyRequestKind(), requestingClass);
+ }
+
+ /**
+ * Returns an expression that evaluates to the value of a dependency request, for passing to a
+ * binding method, an {@code @Inject}-annotated constructor or member, or a proxy for one.
+ *
+ * <p>If the method is a generated static {@link InjectionMethods injection method}, each
+ * parameter will be {@link Object} if the dependency's raw type is inaccessible. If that is the
+ * case for this dependency, the returned expression will use a cast to evaluate to the raw type.
+ *
+ * @param requestingClass the class that will contain the expression
+ */
+ // TODO(b/64024402) Merge with getDependencyExpression(DependencyRequest, ClassName) if possible.
+ CodeBlock getDependencyArgumentExpression(
+ DependencyRequest dependencyRequest, ClassName requestingClass) {
+ CodeBlock.Builder argument = CodeBlock.builder();
+
+ TypeMirror dependencyType = dependencyRequest.key().type();
+ if (!isTypeAccessibleFrom(dependencyType, requestingClass.packageName())
+ && isRawTypeAccessible(dependencyType, requestingClass.packageName())) {
+ argument.add("($T) ", rawTypeName(TypeName.get(dependencyType)));
+ }
+
+ argument.add(getDependencyExpression(dependencyRequest, requestingClass));
+ return argument.build();
+ }
+
+ private BindingExpression getBindingExpression(BindingKey bindingKey) {
+ for (Map<BindingKey, BindingExpression> bindingExpressionsMap : bindingExpressionsMaps) {
+ BindingExpression expression = bindingExpressionsMap.get(bindingKey);
+ if (expression != null) {
+ return expression;
+ }
+ }
+ throw new IllegalStateException("no binding expression found for " + bindingKey);
+ }
+
+ /** Adds a binding expression for a single binding owned by this component. */
+ void addBindingExpression(BindingExpression bindingExpression) {
+ bindingExpressionsMaps.get(0).put(bindingExpression.bindingKey(), bindingExpression);
+ }
+
+ /**
+ * Returns a new object representing the bindings available from a child component of this one.
+ */
+ ComponentBindingExpressions forChildComponent() {
+ return new ComponentBindingExpressions(
+ FluentIterable.of(newBindingExpressionMap()).append(bindingExpressionsMaps).toList());
+ }
+
+ private static Map<BindingKey, BindingExpression> newBindingExpressionMap() {
+ return new HashMap<>();
+ }
+}
diff --git a/java/dagger/internal/codegen/ComponentWriter.java b/java/dagger/internal/codegen/ComponentWriter.java
index 06f4fb0..53b10c7 100644
--- a/java/dagger/internal/codegen/ComponentWriter.java
+++ b/java/dagger/internal/codegen/ComponentWriter.java
@@ -64,7 +64,8 @@
name,
graph,
new UniqueSubcomponentNamesGenerator(graph).generate(),
- new OptionalFactories());
+ new OptionalFactories(),
+ new ComponentBindingExpressions());
}
/**
diff --git a/java/dagger/internal/codegen/FrameworkDependency.java b/java/dagger/internal/codegen/FrameworkDependency.java
index 0cd593d..f5efe77 100644
--- a/java/dagger/internal/codegen/FrameworkDependency.java
+++ b/java/dagger/internal/codegen/FrameworkDependency.java
@@ -51,6 +51,23 @@
/** The binding type of the framework dependency. */
abstract BindingType bindingType();
+ /** The dependency request kind that is equivalent to requesting the framework dependency. */
+ DependencyRequest.Kind dependencyRequestKind() {
+ switch (bindingType()) {
+ case PROVISION:
+ return DependencyRequest.Kind.PROVIDER;
+
+ case PRODUCTION:
+ return DependencyRequest.Kind.PRODUCER;
+
+ case MEMBERS_INJECTION:
+ return DependencyRequest.Kind.MEMBERS_INJECTOR;
+
+ default:
+ throw new AssertionError(bindingType());
+ }
+ }
+
/** The framework class to use for these requests. */
final Class<?> frameworkClass() {
return bindingType().frameworkClass();
diff --git a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
index 2cd0b91..88bd248 100644
--- a/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
+++ b/java/dagger/internal/codegen/FrameworkInstanceBindingExpression.java
@@ -26,33 +26,30 @@
import dagger.internal.DelegateFactory;
import java.util.Optional;
-/**
- * A {@link BindingExpression} that is always satisfied in components by using an instance of a
- * {@link FrameworkType}.
- */
+/** A binding expression that uses an instance of a {@link FrameworkType}. */
// TODO(user): consider removing this class and making it a strategy that is created by
// {Provider,Producer,MembersInjector}BindingExpression
abstract class FrameworkInstanceBindingExpression extends BindingExpression {
private final Optional<FieldSpec> fieldSpec;
- private final HasBindingExpressions hasBindingExpressions;
+ private final GeneratedComponentModel generatedComponentModel;
private final MemberSelect memberSelect;
private InitializationState fieldInitializationState = InitializationState.UNINITIALIZED;
protected FrameworkInstanceBindingExpression(
BindingKey bindingKey,
Optional<FieldSpec> fieldSpec,
- HasBindingExpressions hasBindingExpressions,
+ GeneratedComponentModel generatedComponentModel,
MemberSelect memberSelect) {
super(bindingKey);
- this.hasBindingExpressions = hasBindingExpressions;
+ this.generatedComponentModel = generatedComponentModel;
this.memberSelect = memberSelect;
this.fieldSpec = fieldSpec;
}
/**
* The expression for the framework instance for this binding. If the instance comes from a
- * component field, it will be {@link HasBindingExpressions#addInitialization(CodeBlock)
- * initialized} and {@link HasBindingExpressions#addField(FieldSpec) added} to the component the
+ * component field, it will be {@link GeneratedComponentModel#addInitialization(CodeBlock)
+ * initialized} and {@link GeneratedComponentModel#addField(FieldSpec) added} to the component the
* first time this method is invoked.
*/
final CodeBlock getFrameworkTypeInstance(ClassName requestingClass) {
@@ -106,7 +103,7 @@
CodeBlock.of(
"this.$L = $L;",
fieldName(),
- checkNotNull(hasBindingExpressions.getFieldInitialization(this)));
+ checkNotNull(generatedComponentModel.getFieldInitialization(this)));
if (fieldInitializationState == InitializationState.DELEGATED) {
// If we were recursively invoked, set the delegate factory as part of our initialization
@@ -119,15 +116,15 @@
} else {
codeBuilder.add(initCode);
}
- hasBindingExpressions.addInitialization(codeBuilder.build());
- hasBindingExpressions.addField(fieldSpec.get());
+ generatedComponentModel.addInitialization(codeBuilder.build());
+ generatedComponentModel.addField(fieldSpec.get());
setFieldInitializationState(InitializationState.INITIALIZED);
break;
case INITIALIZING:
// We were recursively invoked, so create a delegate factory instead
- hasBindingExpressions.addInitialization(
+ generatedComponentModel.addInitialization(
CodeBlock.of("this.$L = new $T();", fieldName(), DELEGATE_FACTORY));
setFieldInitializationState(InitializationState.DELEGATED);
break;
diff --git a/java/dagger/internal/codegen/HasBindingExpressions.java b/java/dagger/internal/codegen/GeneratedComponentModel.java
similarity index 68%
rename from java/dagger/internal/codegen/HasBindingExpressions.java
rename to java/dagger/internal/codegen/GeneratedComponentModel.java
index 3a0d3bb..e215332 100644
--- a/java/dagger/internal/codegen/HasBindingExpressions.java
+++ b/java/dagger/internal/codegen/GeneratedComponentModel.java
@@ -19,22 +19,12 @@
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
-import javax.annotation.Nullable;
-/** An object which associates a {@link BindingExpression} instance with a {@link BindingKey}. */
-// TODO(dpb): Rename and/or split up this type.
-interface HasBindingExpressions {
-
- /**
- * Returns the {@link BindingExpression} associated with the given {@link BindingKey} or {@code
- * null} if no association exists.
- */
- // TODO(dpb): Move the hierarchical map of binding expressions out into a separate class.
- // This should remove the need for HasBindingExpressions
- @Nullable
- BindingExpression getBindingExpression(BindingKey bindingKey);
+/** The model of the component being generated. */
+interface GeneratedComponentModel {
/** Returns the expression used to initialize a binding expression field. */
+ // TODO(user): Move this method onto FrameworkInstanceBindingExpression and subtypes.
CodeBlock getFieldInitialization(FrameworkInstanceBindingExpression bindingExpression);
/** Adds the given field to the component. */
diff --git a/java/dagger/internal/codegen/MembersInjectorBindingExpression.java b/java/dagger/internal/codegen/MembersInjectorBindingExpression.java
index a620f0d..9134ed0 100644
--- a/java/dagger/internal/codegen/MembersInjectorBindingExpression.java
+++ b/java/dagger/internal/codegen/MembersInjectorBindingExpression.java
@@ -24,25 +24,19 @@
import dagger.internal.codegen.DependencyRequest.Kind;
import java.util.Optional;
+/** A binding expression that uses a {@link dagger.MembersInjector} instance. */
final class MembersInjectorBindingExpression extends FrameworkInstanceBindingExpression {
MembersInjectorBindingExpression(
BindingKey bindingKey,
Optional<FieldSpec> fieldSpec,
- HasBindingExpressions hasBindingExpressions,
+ GeneratedComponentModel generatedComponentModel,
MemberSelect memberSelect) {
- super(bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+ super(bindingKey, fieldSpec, generatedComponentModel, memberSelect);
}
@Override
- CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
- checkArgument(request.kind().equals(Kind.MEMBERS_INJECTOR));
- return getFrameworkTypeInstance(requestingClass);
- }
-
- @Override
- CodeBlock getDependencyExpression(
- FrameworkDependency frameworkDependency, ClassName requestingClass) {
- checkArgument(frameworkDependency.bindingType().equals(BindingType.MEMBERS_INJECTION));
+ CodeBlock getDependencyExpression(DependencyRequest.Kind requestKind, ClassName requestingClass) {
+ checkArgument(requestKind.equals(Kind.MEMBERS_INJECTOR));
return getFrameworkTypeInstance(requestingClass);
}
diff --git a/java/dagger/internal/codegen/OptionalBindingExpression.java b/java/dagger/internal/codegen/OptionalBindingExpression.java
index 34cbc3d..f2d8efd 100644
--- a/java/dagger/internal/codegen/OptionalBindingExpression.java
+++ b/java/dagger/internal/codegen/OptionalBindingExpression.java
@@ -23,31 +23,29 @@
import com.squareup.javapoet.CodeBlock;
import dagger.internal.codegen.OptionalType.OptionalKind;
-/**
- * A {@link BindingExpression} for {@link
- * ContributionBinding.Kind#SYNTHETIC_OPTIONAL_BINDING}
- */
+/** A binding expression for optional bindings. */
final class OptionalBindingExpression extends SimpleInvocationBindingExpression {
private final ProvisionBinding binding;
- private final HasBindingExpressions hasBindingExpressions;
+ private final ComponentBindingExpressions componentBindingExpressions;
OptionalBindingExpression(
ProvisionBinding binding,
BindingExpression delegate,
- HasBindingExpressions hasBindingExpressions) {
+ ComponentBindingExpressions componentBindingExpressions) {
super(delegate);
this.binding = binding;
- this.hasBindingExpressions = hasBindingExpressions;
+ this.componentBindingExpressions = componentBindingExpressions;
}
@Override
- CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+ CodeBlock getInstanceDependencyExpression(
+ DependencyRequest.Kind requestKind, ClassName requestingClass) {
OptionalType optionalType = OptionalType.from(binding.key());
OptionalKind optionalKind = optionalType.kind();
if (binding.dependencies().isEmpty()) {
// When compiling with -source 7, javac's type inference isn't strong enough to detect
// Futures.immediateFuture(Optional.absent()) for keys that aren't Object
- if (request.kind().equals(DependencyRequest.Kind.FUTURE)
+ if (requestKind.equals(DependencyRequest.Kind.FUTURE)
&& isTypeAccessibleFrom(binding.key().type(), requestingClass.packageName())) {
return optionalKind.parameterizedAbsentValueExpression(optionalType);
}
@@ -56,9 +54,7 @@
DependencyRequest dependency = getOnlyElement(binding.dependencies());
CodeBlock dependencyExpression =
- hasBindingExpressions
- .getBindingExpression(dependency.bindingKey())
- .getDependencyExpression(dependency, requestingClass);
+ componentBindingExpressions.getDependencyExpression(dependency, requestingClass);
// If the dependency type is inaccessible, then we have to use Optional.<Object>of(...), or else
// we will get "incompatible types: inference variable has incompatible bounds.
diff --git a/java/dagger/internal/codegen/ProducerBindingExpression.java b/java/dagger/internal/codegen/ProducerBindingExpression.java
index 208a408..7fdef71 100644
--- a/java/dagger/internal/codegen/ProducerBindingExpression.java
+++ b/java/dagger/internal/codegen/ProducerBindingExpression.java
@@ -16,40 +16,28 @@
package dagger.internal.codegen;
-import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.BindingType.PRODUCTION;
-
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.FieldSpec;
import java.util.Optional;
+/** A binding expression that uses a {@link dagger.producers.Producer} instance. */
final class ProducerBindingExpression extends FrameworkInstanceBindingExpression {
private final boolean isProducerFromProvider;
ProducerBindingExpression(
BindingKey bindingKey,
Optional<FieldSpec> fieldSpec,
- HasBindingExpressions hasBindingExpressions,
+ GeneratedComponentModel generatedComponentModel,
MemberSelect memberSelect,
boolean isProducerFromProvider) {
- super(bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+ super(bindingKey, fieldSpec, generatedComponentModel, memberSelect);
this.isProducerFromProvider = isProducerFromProvider;
}
@Override
- CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
- return FrameworkType.PRODUCER.to(request.kind(), getFrameworkTypeInstance(requestingClass));
- }
-
- @Override
- CodeBlock getDependencyExpression(
- FrameworkDependency frameworkDependency, ClassName requestingClass) {
- checkArgument(
- frameworkDependency.bindingType().equals(PRODUCTION),
- "%s is not a production dependency",
- frameworkDependency);
- return getFrameworkTypeInstance(requestingClass);
+ CodeBlock getDependencyExpression(DependencyRequest.Kind requestKind, ClassName requestingClass) {
+ return FrameworkType.PRODUCER.to(requestKind, getFrameworkTypeInstance(requestingClass));
}
@Override
diff --git a/java/dagger/internal/codegen/ProviderBindingExpression.java b/java/dagger/internal/codegen/ProviderBindingExpression.java
index 107b470..0d6e70c 100644
--- a/java/dagger/internal/codegen/ProviderBindingExpression.java
+++ b/java/dagger/internal/codegen/ProviderBindingExpression.java
@@ -21,34 +21,19 @@
import com.squareup.javapoet.FieldSpec;
import java.util.Optional;
+/** A binding expression that uses a {@link javax.inject.Provider} instance. */
final class ProviderBindingExpression extends FrameworkInstanceBindingExpression {
ProviderBindingExpression(
BindingKey bindingKey,
Optional<FieldSpec> fieldSpec,
- HasBindingExpressions hasBindingExpressions,
+ GeneratedComponentModel generatedComponentModel,
MemberSelect memberSelect) {
- super(bindingKey, fieldSpec, hasBindingExpressions, memberSelect);
+ super(bindingKey, fieldSpec, generatedComponentModel, memberSelect);
}
@Override
- CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
- return FrameworkType.PROVIDER.to(request.kind(), getFrameworkTypeInstance(requestingClass));
- }
-
- @Override
- CodeBlock getDependencyExpression(
- FrameworkDependency frameworkDependency, ClassName requestingClass) {
- switch (frameworkDependency.bindingType()) {
- case PROVISION:
- return getFrameworkTypeInstance(requestingClass);
- case MEMBERS_INJECTION:
- throw new IllegalArgumentException();
- case PRODUCTION:
- return FrameworkType.PROVIDER.to(
- DependencyRequest.Kind.PRODUCER, getFrameworkTypeInstance(requestingClass));
- default:
- throw new AssertionError();
- }
+ CodeBlock getDependencyExpression(DependencyRequest.Kind requestKind, ClassName requestingClass) {
+ return FrameworkType.PROVIDER.to(requestKind, getFrameworkTypeInstance(requestingClass));
}
@Override
diff --git a/java/dagger/internal/codegen/SetBindingExpression.java b/java/dagger/internal/codegen/SetBindingExpression.java
index d94660c..71ef367 100644
--- a/java/dagger/internal/codegen/SetBindingExpression.java
+++ b/java/dagger/internal/codegen/SetBindingExpression.java
@@ -30,38 +30,36 @@
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
-/**
- * A {@link BindingExpression} for {@link
- * ContributionBinding.Kind#SYNTHETIC_MULTIBOUND_SET}
- */
+/** A binding expression for multibound sets. */
final class SetBindingExpression extends SimpleInvocationBindingExpression {
private final ProvisionBinding binding;
private final BindingGraph graph;
- private final HasBindingExpressions hasBindingExpressions;
+ private final ComponentBindingExpressions componentBindingExpressions;
private final Elements elements;
SetBindingExpression(
ProvisionBinding binding,
BindingGraph graph,
- HasBindingExpressions hasBindingExpressions,
+ ComponentBindingExpressions componentBindingExpressions,
BindingExpression delegate,
Elements elements) {
super(delegate);
this.binding = binding;
this.graph = graph;
- this.hasBindingExpressions = hasBindingExpressions;
+ this.componentBindingExpressions = componentBindingExpressions;
this.elements = elements;
}
@Override
- CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+ CodeBlock getInstanceDependencyExpression(
+ DependencyRequest.Kind requestKind, ClassName requestingClass) {
// TODO(ronshapiro): We should also make an ImmutableSet version of SetFactory
boolean isImmutableSetAvailable = isImmutableSetAvailable();
// TODO(ronshapiro, gak): Use Sets.immutableEnumSet() if it's available?
if (isImmutableSetAvailable && binding.dependencies().stream().allMatch(this::isSingleValue)) {
return CodeBlock.builder()
.add("$T.", ImmutableSet.class)
- .add(maybeTypeParameter(request, requestingClass))
+ .add(maybeTypeParameter(requestingClass))
.add(
"of($L)",
binding
@@ -73,19 +71,18 @@
}
switch (binding.dependencies().size()) {
case 0:
- return collectionsStaticFactoryInvocation(
- request, requestingClass, CodeBlock.of("emptySet()"));
+ return collectionsStaticFactoryInvocation(requestingClass, CodeBlock.of("emptySet()"));
case 1:
{
DependencyRequest dependency = getOnlyElement(binding.dependencies());
CodeBlock contributionExpression = getContributionExpression(dependency, requestingClass);
if (isSingleValue(dependency)) {
return collectionsStaticFactoryInvocation(
- request, requestingClass, CodeBlock.of("singleton($L)", contributionExpression));
+ requestingClass, CodeBlock.of("singleton($L)", contributionExpression));
} else if (isImmutableSetAvailable) {
return CodeBlock.builder()
.add("$T.", ImmutableSet.class)
- .add(maybeTypeParameter(request, requestingClass))
+ .add(maybeTypeParameter(requestingClass))
.add("copyOf($L)", contributionExpression)
.build();
}
@@ -95,7 +92,7 @@
CodeBlock.Builder instantiation = CodeBlock.builder();
instantiation
.add("$T.", isImmutableSetAvailable ? ImmutableSet.class : SetBuilder.class)
- .add(maybeTypeParameter(request, requestingClass));
+ .add(maybeTypeParameter(requestingClass));
if (isImmutableSetAvailable) {
instantiation.add("builder()");
} else {
@@ -112,23 +109,20 @@
private CodeBlock getContributionExpression(
DependencyRequest dependency, ClassName requestingClass) {
- return hasBindingExpressions
- .getBindingExpression(dependency.bindingKey())
- .getDependencyExpression(dependency, requestingClass);
+ return componentBindingExpressions.getDependencyExpression(dependency, requestingClass);
}
- private static CodeBlock collectionsStaticFactoryInvocation(
- DependencyRequest request, ClassName requestingClass, CodeBlock methodInvocation) {
+ private CodeBlock collectionsStaticFactoryInvocation(
+ ClassName requestingClass, CodeBlock methodInvocation) {
return CodeBlock.builder()
.add("$T.", Collections.class)
- .add(maybeTypeParameter(request, requestingClass))
+ .add(maybeTypeParameter(requestingClass))
.add(methodInvocation)
.build();
}
- private static CodeBlock maybeTypeParameter(
- DependencyRequest request, ClassName requestingClass) {
- TypeMirror elementType = SetType.from(request.key()).elementType();
+ private CodeBlock maybeTypeParameter(ClassName requestingClass) {
+ TypeMirror elementType = SetType.from(binding.key()).elementType();
return isTypeAccessibleFrom(elementType, requestingClass.packageName())
? CodeBlock.of("<$T>", elementType)
: CodeBlock.of("");
diff --git a/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java b/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
index 62eee5f..a56bf25 100644
--- a/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
+++ b/java/dagger/internal/codegen/SimpleInvocationBindingExpression.java
@@ -21,8 +21,8 @@
import com.squareup.javapoet.CodeBlock;
/**
- * A {@link BindingExpression} that can fulfill its request with a simple call when possible, and
- * otherwise delegates to a backing provider field.
+ * A binding expression that can use a simple expression for instance requests, and delegates to
+ * another expression for other requests.
*/
abstract class SimpleInvocationBindingExpression extends BindingExpression {
private final BindingExpression delegate;
@@ -38,7 +38,7 @@
* @param requestingClass the class that will contain the expression
*/
abstract CodeBlock getInstanceDependencyExpression(
- DependencyRequest request, ClassName requestingClass);
+ DependencyRequest.Kind requestKind, ClassName requestingClass);
/**
* Java 7 type inference is not as strong as in Java 8, and therefore some generated code must
@@ -52,24 +52,21 @@
}
@Override
- final CodeBlock getDependencyExpression(DependencyRequest request, ClassName requestingClass) {
- switch (request.kind()) {
+ final CodeBlock getDependencyExpression(
+ DependencyRequest.Kind requestKind, ClassName requestingClass) {
+ switch (requestKind) {
case INSTANCE:
- return getInstanceDependencyExpression(request, requestingClass);
+ return getInstanceDependencyExpression(requestKind, requestingClass);
case FUTURE:
return CodeBlock.builder()
.add("$T.", Futures.class)
.add(explicitTypeParameter(requestingClass))
- .add("immediateFuture($L)", getInstanceDependencyExpression(request, requestingClass))
+ .add(
+ "immediateFuture($L)",
+ getInstanceDependencyExpression(requestKind, requestingClass))
.build();
default:
- return delegate.getDependencyExpression(request, requestingClass);
+ return delegate.getDependencyExpression(requestKind, requestingClass);
}
}
-
- @Override
- final CodeBlock getDependencyExpression(
- FrameworkDependency frameworkDependency, ClassName requestingClass) {
- return delegate.getDependencyExpression(frameworkDependency, requestingClass);
- }
}
diff --git a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
index bb72db0..ec9d208 100644
--- a/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/SimpleMethodBindingExpression.java
@@ -36,34 +36,37 @@
import javax.lang.model.type.DeclaredType;
/**
- * A request fulfillment implementation that invokes methods or constructors directly to fulfill
- * requests whenever possible. In cases where direct invocation is not possible, this implementation
- * delegates to one that uses a {@link javax.inject.Provider}.
+ * A binding expression that invokes methods or constructors directly for a provision binding when
+ * possible.
*/
final class SimpleMethodBindingExpression extends SimpleInvocationBindingExpression {
private final CompilerOptions compilerOptions;
private final ProvisionBinding provisionBinding;
- private final HasBindingExpressions hasBindingExpressions;
+ private final ComponentBindingExpressions componentBindingExpressions;
+ private final GeneratedComponentModel generatedComponentModel;
SimpleMethodBindingExpression(
CompilerOptions compilerOptions,
ProvisionBinding provisionBinding,
BindingExpression delegate,
- HasBindingExpressions hasBindingExpressions) {
+ ComponentBindingExpressions componentBindingExpressions,
+ GeneratedComponentModel generatedComponentModel) {
super(delegate);
- this.compilerOptions = compilerOptions;
checkArgument(
provisionBinding.implicitDependencies().isEmpty(),
"framework deps are not currently supported");
checkArgument(!provisionBinding.scope().isPresent());
checkArgument(!provisionBinding.requiresModuleInstance());
checkArgument(provisionBinding.bindingElement().isPresent());
+ this.compilerOptions = compilerOptions;
this.provisionBinding = provisionBinding;
- this.hasBindingExpressions = hasBindingExpressions;
+ this.componentBindingExpressions = componentBindingExpressions;
+ this.generatedComponentModel = generatedComponentModel;
}
@Override
- CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+ CodeBlock getInstanceDependencyExpression(
+ DependencyRequest.Kind requestKind, ClassName requestingClass) {
return requiresInjectionMethod(provisionBinding, requestingClass.packageName())
? invokeInjectionMethod(requestingClass)
: invokeMethod(requestingClass);
@@ -115,9 +118,7 @@
}
private CodeBlock dependencyArgument(DependencyRequest dependency, ClassName requestingClass) {
- return hasBindingExpressions
- .getBindingExpression(dependency.bindingKey())
- .getDependencyArgumentExpression(dependency, requestingClass);
+ return componentBindingExpressions.getDependencyArgumentExpression(dependency, requestingClass);
}
private CodeBlock maybeCheckForNulls(CodeBlock methodCall) {
@@ -141,7 +142,7 @@
return CodeBlock.of(
"$N($L)",
- hasBindingExpressions.getMembersInjectionMethod(provisionBinding.key()),
+ generatedComponentModel.getMembersInjectionMethod(provisionBinding.key()),
instance);
}
}
diff --git a/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java b/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java
index 53fd28b..1e87fe7 100644
--- a/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java
+++ b/java/dagger/internal/codegen/SubcomponentBuilderBindingExpression.java
@@ -19,6 +19,7 @@
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
+/** A binding expression for a subcomponent builder that just invokes the constructor. */
final class SubcomponentBuilderBindingExpression extends SimpleInvocationBindingExpression {
private final String subcomponentBuilderName;
@@ -28,7 +29,8 @@
}
@Override
- CodeBlock getInstanceDependencyExpression(DependencyRequest request, ClassName requestingClass) {
+ CodeBlock getInstanceDependencyExpression(
+ DependencyRequest.Kind requestKind, ClassName requestingClass) {
return CodeBlock.of("new $LBuilder()", subcomponentBuilderName);
}
}
diff --git a/java/dagger/internal/codegen/SubcomponentWriter.java b/java/dagger/internal/codegen/SubcomponentWriter.java
index bfa3a23..48e674f 100644
--- a/java/dagger/internal/codegen/SubcomponentWriter.java
+++ b/java/dagger/internal/codegen/SubcomponentWriter.java
@@ -84,12 +84,6 @@
}
@Override
- public BindingExpression getBindingExpression(BindingKey key) {
- BindingExpression bindingExpression = super.getBindingExpression(key);
- return bindingExpression == null ? parent.getBindingExpression(key) : bindingExpression;
- }
-
- @Override
protected CodeBlock getReferenceReleasingProviderManagerExpression(Scope scope) {
return parent.getReferenceReleasingProviderManagerExpression(scope);
}