[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(),