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/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<>();
+ }
+}