[Ahead-of-time Subcomponents] Add support for multibindings. Multibinding
methods are generated for every subcomponent implementation in which there are
new contributions available, and all implementations use their superclass
implementations when available.

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212015189
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index 25b7b72..b73e8e9 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -274,6 +274,7 @@
         "ModifiableConcreteMethodBindingExpression.java",
         "MonitoringModuleGenerator.java",
         "MonitoringModuleProcessingStep.java",
+        "MultibindingExpression.java",
         "OptionalBindingExpression.java",
         "OptionalFactories.java",
         "OptionalFactoryInstanceCreationExpression.java",
diff --git a/java/dagger/internal/codegen/ComponentBindingExpressions.java b/java/dagger/internal/codegen/ComponentBindingExpressions.java
index 24ad87e..f78a0e6 100644
--- a/java/dagger/internal/codegen/ComponentBindingExpressions.java
+++ b/java/dagger/internal/codegen/ComponentBindingExpressions.java
@@ -31,7 +31,6 @@
 import static dagger.model.BindingKind.DELEGATE;
 import static dagger.model.BindingKind.MULTIBOUND_MAP;
 import static dagger.model.BindingKind.MULTIBOUND_SET;
-import static java.util.function.Predicate.isEqual;
 import static javax.lang.model.element.Modifier.PUBLIC;
 
 import com.google.auto.common.MoreTypes;
@@ -72,7 +71,6 @@
   private final MembersInjectionMethods membersInjectionMethods;
   private final InnerSwitchingProviders innerSwitchingProviders;
   private final StaticSwitchingProviders staticSwitchingProviders;
-
   private final Map<BindingRequest, BindingExpression> expressions = new HashMap<>();
 
   ComponentBindingExpressions(
@@ -342,7 +340,9 @@
       return true;
     }
     // All currently supported modifiable types are finalized upon modification.
-    return shouldModifyBinding(newModifiableBindingType, modifiableBindingMethod.request());
+    return modifiableBindingWillBeFinalized(
+        newModifiableBindingType,
+        shouldModifyBinding(newModifiableBindingType, modifiableBindingMethod.request()));
   }
 
   /**
@@ -353,8 +353,30 @@
    */
   private boolean newModifiableBindingWillBeFinalized(
       ModifiableBindingType modifiableBindingType, BindingRequest request) {
-    // All currently supported modifiable types are finalized upon modification.
-    return shouldModifyBinding(modifiableBindingType, request);
+    return modifiableBindingWillBeFinalized(
+        modifiableBindingType, shouldModifyBinding(modifiableBindingType, request));
+  }
+
+  /**
+   * Returns true if we shouldn't attempt to further modify a modifiable binding once we complete
+   * the implementation for the current subcomponent.
+   */
+  private boolean modifiableBindingWillBeFinalized(
+      ModifiableBindingType modifiableBindingType, boolean modifyingBinding) {
+    switch (modifiableBindingType) {
+      case MISSING:
+      case GENERATED_INSTANCE:
+      case OPTIONAL:
+        // Once we modify any of the above a single time, then they are finalized.
+        return modifyingBinding;
+      case MULTIBINDING:
+        return false;
+      default:
+        throw new IllegalStateException(
+            String.format(
+                "Building binding expression for unsupported ModifiableBindingType [%s].",
+                modifiableBindingType));
+    }
   }
 
   private BindingExpression getBindingExpression(BindingRequest request) {
@@ -422,13 +444,9 @@
             matchingModifiableBindingMethod,
             matchingComponentMethod);
       case OPTIONAL:
-        BindingExpression expression = createBindingExpression(resolvedBindings, request);
-        // If the expression hasn't already been registered as a modifiable binding method then wrap
-        // the binding here.
-        if (!generatedComponentModel.getModifiableBindingMethod(request).isPresent()) {
-          return wrapInMethod(resolvedBindings, request, expression);
-        }
-        return expression;
+      case MULTIBINDING:
+        return wrapInMethod(
+            resolvedBindings, request, createBindingExpression(resolvedBindings, request));
       default:
         throw new IllegalStateException(
             String.format(
@@ -467,6 +485,11 @@
       if (binding.kind().equals(BindingKind.OPTIONAL)) {
         return ModifiableBindingType.OPTIONAL;
       }
+
+      if (resolvedBindings.bindingType().equals(BindingType.PROVISION)
+          && binding.isSyntheticMultibinding()) {
+        return ModifiableBindingType.MULTIBINDING;
+      }
     } else if (!resolvableBinding(request)) {
       return ModifiableBindingType.MISSING;
     }
@@ -496,6 +519,7 @@
    */
   private boolean shouldModifyBinding(
       ModifiableBindingType modifiableBindingType, BindingRequest request) {
+    ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
     switch (modifiableBindingType) {
       case GENERATED_INSTANCE:
         return !generatedComponentModel.isAbstract();
@@ -507,8 +531,12 @@
         return resolvableBinding(request);
       case OPTIONAL:
         // Only override optional binding methods if we have a non-empty binding.
-        ResolvedBindings resolvedBindings = graph.resolvedBindings(request);
         return !resolvedBindings.contributionBinding().dependencies().isEmpty();
+      case MULTIBINDING:
+        // Only modify a multibinding if there are new contributions.
+        return !generatedComponentModel
+            .superclassContributionsMade(request.key())
+            .containsAll(resolvedBindings.contributionBinding().dependencies());
       default:
         throw new IllegalStateException(
             String.format(
@@ -831,11 +859,13 @@
 
       case MULTIBOUND_SET:
         return Optional.of(
-            new SetBindingExpression(resolvedBindings, graph, this, types, elements));
+            new SetBindingExpression(
+                resolvedBindings, generatedComponentModel, graph, this, types, elements));
 
       case MULTIBOUND_MAP:
         return Optional.of(
-            new MapBindingExpression(resolvedBindings, graph, this, types, elements));
+            new MapBindingExpression(
+                resolvedBindings, generatedComponentModel, graph, this, types, elements));
 
       case OPTIONAL:
         return Optional.of(new OptionalBindingExpression(resolvedBindings, this, types));
@@ -912,13 +942,19 @@
       ResolvedBindings resolvedBindings,
       BindingRequest request,
       BindingExpression bindingExpression) {
+    // If we've already wrapped the expression, then use the delegate.
+    if (bindingExpression instanceof MethodBindingExpression) {
+      return bindingExpression;
+    }
+
     BindingMethodImplementation methodImplementation =
         methodImplementation(resolvedBindings, request, bindingExpression);
     Optional<ComponentMethodDescriptor> matchingComponentMethod =
         findMatchingComponentMethod(request);
 
     ModifiableBindingType modifiableBindingType = getModifiableBindingType(request);
-    if (modifiableBindingType.isModifiable() && !matchingComponentMethod.isPresent()) {
+    if (shouldUseAModifiableConcreteMethodBindingExpression(
+        modifiableBindingType, matchingComponentMethod)) {
       return new ModifiableConcreteMethodBindingExpression(
           resolvedBindings,
           request,
@@ -940,6 +976,23 @@
                     resolvedBindings, request, methodImplementation, generatedComponentModel));
   }
 
+  /**
+   * Returns true if we should wrap a binding expression using a {@link
+   * ModifiableConcreteMethodBindingExpression}. If we're generating the abstract base class of a
+   * subcomponent and the binding matches a component method, even if it is modifiable, then it
+   * should be "wrapped" by a {@link ComponentMethodBindingExpression}. If it isn't a base class
+   * then modifiable methods should be handled by a {@link
+   * ModifiableConcreteMethodBindingExpression}. When generating an inner subcomponent it doesn't
+   * matter whether the binding matches a component method: All modifiable bindings should be
+   * handled by a {@link ModifiableConcreteMethodBindingExpression}.
+   */
+  private boolean shouldUseAModifiableConcreteMethodBindingExpression(
+      ModifiableBindingType type, Optional<ComponentMethodDescriptor> matchingComponentMethod) {
+    return type.isModifiable()
+        && (generatedComponentModel.supermodel().isPresent()
+            || !matchingComponentMethod.isPresent());
+  }
+
   /** Returns the first component method associated with this request kind, if one exists. */
   private Optional<ComponentMethodDescriptor> findMatchingComponentMethod(BindingRequest request) {
     return graph.componentDescriptor().componentMethods().stream()
@@ -953,7 +1006,7 @@
     return componentMethod
         .dependencyRequest()
         .map(BindingRequest::forDependencyRequest)
-        .filter(isEqual(request))
+        .filter(request::equals)
         .isPresent();
   }
 
diff --git a/java/dagger/internal/codegen/GeneratedComponentModel.java b/java/dagger/internal/codegen/GeneratedComponentModel.java
index 69299e8..424ca53 100644
--- a/java/dagger/internal/codegen/GeneratedComponentModel.java
+++ b/java/dagger/internal/codegen/GeneratedComponentModel.java
@@ -19,6 +19,7 @@
 import static com.google.common.base.CaseFormat.LOWER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
+import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static com.squareup.javapoet.TypeSpec.classBuilder;
 import static dagger.internal.codegen.Accessibility.isTypeAccessibleFrom;
@@ -30,9 +31,12 @@
 
 import com.google.auto.common.MoreTypes;
 import com.google.common.base.Supplier;
+import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.SetMultimap;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
@@ -40,6 +44,8 @@
 import com.squareup.javapoet.TypeSpec;
 import dagger.internal.ReferenceReleasingProviderManager;
 import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.model.DependencyRequest;
+import dagger.model.Key;
 import dagger.model.RequestKind;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -145,6 +151,8 @@
       MultimapBuilder.enumKeys(TypeSpecKind.class).arrayListValues().build();
   private final List<Supplier<TypeSpec>> switchingProviderSupplier = new ArrayList<>();
   private final ModifiableBindingMethods modifiableBindingMethods = new ModifiableBindingMethods();
+  private final SetMultimap<Key, DependencyRequest> contributionsByMultibinding =
+      HashMultimap.create();
 
   private GeneratedComponentModel(
       ClassName name,
@@ -402,4 +410,43 @@
     switchingProviderSupplier.stream().map(Supplier::get).forEach(component::addType);
     return component;
   }
+
+  /**
+   * Registers a {@ProvisionBinding} representing a multibinding as having been implemented in this
+   * component. Multibindings are modifiable across subcomponent implementations and this allows us
+   * to know whether a contribution has been made by a superclass implementation. This is only
+   * relevant for ahead-of-time subcomponents.
+   */
+  void registerImplementedMultibinding(ContributionBinding multibinding) {
+    checkArgument(multibinding.isSyntheticMultibinding());
+    // We register a multibinding as implemented each time we request the multibinding expression,
+    // so only modify the set of contributions once.
+    if (!contributionsByMultibinding.containsKey(multibinding.key())) {
+      contributionsByMultibinding.putAll(multibinding.key(), multibinding.dependencies());
+    }
+  }
+
+  /**
+   * Returns the set of multibinding contributions associated with all superclass implementations of
+   * a multibinding.
+   */
+  ImmutableSet<DependencyRequest> superclassContributionsMade(Key key) {
+    ImmutableSet.Builder<DependencyRequest> contributionsBuilder = ImmutableSet.builder();
+    if (supermodel.isPresent()) {
+      contributionsBuilder.addAll(supermodel.get().getAllMultibindingContributions(key));
+    }
+    return contributionsBuilder.build();
+  }
+
+  /**
+   * Returns the set of multibinding contributions associated with all implementations of a
+   * multibinding.
+   */
+  private ImmutableSet<DependencyRequest> getAllMultibindingContributions(Key key) {
+    ImmutableSet.Builder<DependencyRequest> contributionsBuilder = ImmutableSet.builder();
+    if (contributionsByMultibinding.containsKey(key)) {
+      contributionsBuilder.addAll(contributionsByMultibinding.get(key));
+    }
+    return contributionsBuilder.addAll(superclassContributionsMade(key)).build();
+  }
 }
diff --git a/java/dagger/internal/codegen/MapBindingExpression.java b/java/dagger/internal/codegen/MapBindingExpression.java
index 25e2e00..4884d2b 100644
--- a/java/dagger/internal/codegen/MapBindingExpression.java
+++ b/java/dagger/internal/codegen/MapBindingExpression.java
@@ -32,11 +32,12 @@
 import dagger.model.BindingKind;
 import dagger.model.DependencyRequest;
 import java.util.Collections;
+import java.util.Optional;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeMirror;
 
 /** A {@link BindingExpression} for multibound maps. */
-final class MapBindingExpression extends SimpleInvocationBindingExpression {
+final class MapBindingExpression extends MultibindingExpression {
   /** Maximum number of key-value pairs that can be passed to ImmutableMap.of(K, V, K, V, ...). */
   private static final int MAX_IMMUTABLE_MAP_OF_KEY_VALUE_PAIRS = 5;
 
@@ -48,11 +49,12 @@
 
   MapBindingExpression(
       ResolvedBindings resolvedBindings,
+      GeneratedComponentModel generatedComponentModel,
       BindingGraph graph,
       ComponentBindingExpressions componentBindingExpressions,
       DaggerTypes types,
       DaggerElements elements) {
-    super(resolvedBindings);
+    super(resolvedBindings, generatedComponentModel);
     this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
     BindingKind bindingKind = this.binding.kind();
     checkArgument(bindingKind.equals(MULTIBOUND_MAP), bindingKind);
@@ -66,11 +68,14 @@
   }
 
   @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
+  protected Expression buildDependencyExpression(ClassName requestingClass) {
+    Optional<CodeBlock> superMethodCall = superMethodCall();
     // TODO(ronshapiro): We should also make an ImmutableMap version of MapFactory
     boolean isImmutableMapAvailable = isImmutableMapAvailable();
     // TODO(ronshapiro, gak): Use Maps.immutableEnumMap() if it's available?
-    if (isImmutableMapAvailable && dependencies.size() <= MAX_IMMUTABLE_MAP_OF_KEY_VALUE_PAIRS) {
+    if (isImmutableMapAvailable
+        && dependencies.size() <= MAX_IMMUTABLE_MAP_OF_KEY_VALUE_PAIRS
+        && !superMethodCall.isPresent()) {
       return Expression.create(
           immutableMapType(),
           CodeBlock.builder()
@@ -106,9 +111,12 @@
         } else {
           instantiation.add("newMapBuilder($L)", dependencies.size());
         }
-        for (DependencyRequest dependency : dependencies.keySet()) {
+        for (DependencyRequest dependency : getNewContributions(dependencies.keySet())) {
           instantiation.add(".put($L)", keyAndValueExpression(dependency, requestingClass));
         }
+        if (superMethodCall.isPresent()) {
+          instantiation.add(CodeBlock.of(".putAll($L)", superMethodCall.get()));
+        }
         return Expression.create(
             isImmutableMapAvailable ? immutableMapType() : binding.key().type(),
             instantiation.add(".build()").build());
diff --git a/java/dagger/internal/codegen/ModifiableBindingMethods.java b/java/dagger/internal/codegen/ModifiableBindingMethods.java
index 6e7ddc6..d83a5fc 100644
--- a/java/dagger/internal/codegen/ModifiableBindingMethods.java
+++ b/java/dagger/internal/codegen/ModifiableBindingMethods.java
@@ -108,5 +108,10 @@
     abstract MethodSpec methodSpec();
 
     abstract boolean finalized();
+
+    /** Whether a {@link ModifiableBindingMethod} is for the same binding request. */
+    boolean fulfillsSameRequestAs(ModifiableBindingMethod other) {
+      return request().equals(other.request());
+    }
   }
 }
diff --git a/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java b/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
index 975ed1a..fb2c1fd 100644
--- a/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
+++ b/java/dagger/internal/codegen/ModifiableConcreteMethodBindingExpression.java
@@ -22,6 +22,7 @@
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.PUBLIC;
 
+import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.TypeName;
 import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
 import java.util.Optional;
@@ -38,6 +39,7 @@
   private final BindingMethodImplementation methodImplementation;
   private final GeneratedComponentModel generatedComponentModel;
   private final boolean bindingFinalized;
+  private final Optional<ModifiableBindingMethod> matchingModifiableBindingMethod;
   private Optional<String> methodName;
 
   ModifiableConcreteMethodBindingExpression(
@@ -55,11 +57,26 @@
     this.methodImplementation = checkNotNull(methodImplementation);
     this.generatedComponentModel = checkNotNull(generatedComponentModel);
     this.bindingFinalized = bindingFinalized;
+    this.matchingModifiableBindingMethod = matchingModifiableBindingMethod;
     this.methodName =
         matchingModifiableBindingMethod.map(modifiableMethod -> modifiableMethod.methodSpec().name);
   }
 
   @Override
+  CodeBlock getModifiableBindingMethodImplementation(
+      ModifiableBindingMethod modifiableBindingMethod, GeneratedComponentModel component) {
+    // Only emit the method implementation if the binding was known when the expression was created
+    // (and not registered when calling 'getDependencyExpression'), and we're generating a
+    // modifiable binding method for the original component (and not an ancestor component).
+    if (matchingModifiableBindingMethod.isPresent() && generatedComponentModel.equals(component)) {
+      checkState(
+          matchingModifiableBindingMethod.get().fulfillsSameRequestAs(modifiableBindingMethod));
+      return methodImplementation.body();
+    }
+    return super.getModifiableBindingMethodImplementation(modifiableBindingMethod, component);
+  }
+
+  @Override
   protected void addMethod() {
     // Add the modifiable binding method to the component model if we haven't already.
     if (!methodName.isPresent()) {
diff --git a/java/dagger/internal/codegen/MultibindingExpression.java b/java/dagger/internal/codegen/MultibindingExpression.java
new file mode 100644
index 0000000..fdfd525
--- /dev/null
+++ b/java/dagger/internal/codegen/MultibindingExpression.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 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 com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
+import dagger.model.DependencyRequest;
+import dagger.model.RequestKind;
+import java.util.Optional;
+
+/** An abstract base class for multibinding {@link BindingExpression}s. */
+abstract class MultibindingExpression extends SimpleInvocationBindingExpression {
+  private final ProvisionBinding binding;
+  private final GeneratedComponentModel generatedComponentModel;
+
+  MultibindingExpression(
+      ResolvedBindings resolvedBindings, GeneratedComponentModel generatedComponentModel) {
+    super(resolvedBindings);
+    this.generatedComponentModel = generatedComponentModel;
+    this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
+  }
+
+  @Override
+  Expression getDependencyExpression(ClassName requestingClass) {
+    Expression expression = buildDependencyExpression(requestingClass);
+    generatedComponentModel.registerImplementedMultibinding(binding);
+    return expression;
+  }
+
+  /**
+   * Returns an expression that evaluates to the value of a multibinding request for the given
+   * requesting class.
+   */
+  protected abstract Expression buildDependencyExpression(ClassName requestingClass);
+
+  /**
+   * Returns the subset of {@code dependencies} that represent multibinding
+   * contributions that were not included in a superclass implementation of this multibinding
+   * method. This is relevant only for ahead-of-time subcomponents. When not generating
+   * ahead-of-time subcomponents there is only one implementation of a multibinding expression and
+   * all {@link DependencyRequest}s from the argment are returned.
+   */
+  protected SetView<DependencyRequest> getNewContributions(
+      ImmutableSet<DependencyRequest> dependencies) {
+    return Sets.difference(
+        dependencies, generatedComponentModel.superclassContributionsMade(binding.key()));
+  }
+
+  /**
+   * Returns the {@link CodeBlock} representing a call to a superclass implementation of the
+   * modifiable binding method that encapsulates this binding, if it exists. This is only possible
+   * when generating ahead-of-time subcomponents.
+   */
+  protected Optional<CodeBlock> superMethodCall() {
+    if (generatedComponentModel.supermodel().isPresent()) {
+      Optional<ModifiableBindingMethod> method =
+          generatedComponentModel.getModifiableBindingMethod(
+              BindingRequest.forDependencyRequest(binding.key(), RequestKind.INSTANCE));
+      checkState(
+          method.isPresent(),
+          "Generating a multibinding super method call when no method has been registered for the "
+              + "binding. Binding is for a %s in %s",
+          binding.key(),
+          generatedComponentModel.name());
+      ImmutableSet<DependencyRequest> superclassContributions =
+          generatedComponentModel.superclassContributionsMade(binding.key());
+      if (!superclassContributions.isEmpty()) {
+        return Optional.of(CodeBlock.of("super.$L()", method.get().methodSpec().name));
+      }
+    }
+    return Optional.empty();
+  }
+}
diff --git a/java/dagger/internal/codegen/SetBindingExpression.java b/java/dagger/internal/codegen/SetBindingExpression.java
index 2409541..d1f73dd 100644
--- a/java/dagger/internal/codegen/SetBindingExpression.java
+++ b/java/dagger/internal/codegen/SetBindingExpression.java
@@ -27,11 +27,12 @@
 import dagger.internal.SetBuilder;
 import dagger.model.DependencyRequest;
 import java.util.Collections;
+import java.util.Optional;
 import javax.lang.model.type.DeclaredType;
 import javax.lang.model.type.TypeMirror;
 
 /** A binding expression for multibound sets. */
-final class SetBindingExpression extends SimpleInvocationBindingExpression {
+final class SetBindingExpression extends MultibindingExpression {
   private final ProvisionBinding binding;
   private final BindingGraph graph;
   private final ComponentBindingExpressions componentBindingExpressions;
@@ -40,11 +41,12 @@
 
   SetBindingExpression(
       ResolvedBindings resolvedBindings,
+      GeneratedComponentModel generatedComponentModel,
       BindingGraph graph,
       ComponentBindingExpressions componentBindingExpressions,
       DaggerTypes types,
       DaggerElements elements) {
-    super(resolvedBindings);
+    super(resolvedBindings, generatedComponentModel);
     this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
     this.graph = graph;
     this.componentBindingExpressions = componentBindingExpressions;
@@ -53,11 +55,14 @@
   }
 
   @Override
-  Expression getDependencyExpression(ClassName requestingClass) {
+  protected Expression buildDependencyExpression(ClassName requestingClass) {
+    Optional<CodeBlock> superMethodCall = superMethodCall();
     // 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)) {
+    if (isImmutableSetAvailable
+        && binding.dependencies().stream().allMatch(this::isSingleValue)
+        && !superMethodCall.isPresent()) {
       return Expression.create(
           immutableSetType(),
           CodeBlock.builder()
@@ -105,11 +110,14 @@
         } else {
           instantiation.add("newSetBuilder($L)", binding.dependencies().size());
         }
-        for (DependencyRequest dependency : binding.dependencies()) {
+        for (DependencyRequest dependency : getNewContributions(binding.dependencies())) {
           String builderMethod = isSingleValue(dependency) ? "add" : "addAll";
           instantiation.add(
               ".$L($L)", builderMethod, getContributionExpression(dependency, requestingClass));
         }
+        if (superMethodCall.isPresent()) {
+          instantiation.add(CodeBlock.of(".addAll($L)", superMethodCall.get()));
+        }
         instantiation.add(".build()");
         return Expression.create(
             isImmutableSetAvailable ? immutableSetType() : binding.key().type(),