blob: ba01bb723cbf15e569cb9c17c5988594c261b118 [file] [log] [blame]
gak16e0cd42014-09-18 09:24:04 -07001/*
ronshapiro5dde42d2016-06-17 09:03:35 -07002 * Copyright (C) 2014 The Dagger Authors.
gak16e0cd42014-09-18 09:24:04 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
dpb1b65b6a2016-07-11 12:11:24 -070016
gak16e0cd42014-09-18 09:24:04 -070017package dagger.internal.codegen;
18
gake55f0742016-07-12 15:36:42 -070019import static com.google.common.base.Preconditions.checkArgument;
ronshapirod6973272016-07-20 15:41:23 -070020import static com.google.common.base.Preconditions.checkNotNull;
gake55f0742016-07-12 15:36:42 -070021import static com.google.common.base.Verify.verify;
22import static com.google.common.collect.Iterables.isEmpty;
dpbe0998bd2016-09-09 12:40:48 -070023import static dagger.internal.codegen.BindingKey.contribution;
gake55f0742016-07-12 15:36:42 -070024import static dagger.internal.codegen.ComponentDescriptor.Kind.PRODUCTION_COMPONENT;
25import static dagger.internal.codegen.ComponentDescriptor.isComponentContributionMethod;
26import static dagger.internal.codegen.ComponentDescriptor.isComponentProductionMethod;
gak66241102016-09-13 12:23:00 -070027import static dagger.internal.codegen.ContributionBinding.Kind.SYNTHETIC_MULTIBOUND_KINDS;
dpbd8d950a2016-08-30 09:24:37 -070028import static dagger.internal.codegen.ContributionBinding.Kind.SYNTHETIC_OPTIONAL_BINDING;
gake55f0742016-07-12 15:36:42 -070029import static dagger.internal.codegen.Key.indexByKey;
30import static dagger.internal.codegen.Scope.reusableScope;
ronshapiroac6dd2b2017-08-04 12:48:07 -070031import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
dpb141148b2016-10-20 12:31:34 -070032import static dagger.internal.codegen.Util.toImmutableSet;
dpb08350312016-09-27 10:12:41 -070033import static java.util.function.Predicate.isEqual;
gake55f0742016-07-12 15:36:42 -070034import static javax.lang.model.element.Modifier.ABSTRACT;
35
gak16e0cd42014-09-18 09:24:04 -070036import com.google.auto.common.MoreTypes;
37import com.google.auto.value.AutoValue;
ronshapiro76fe9b92016-11-07 14:55:51 -080038import com.google.auto.value.extension.memoized.Memoized;
dpb1da29992016-06-24 07:54:52 -070039import com.google.common.base.VerifyException;
gak3a5e81e2015-08-25 16:22:26 -070040import com.google.common.collect.FluentIterable;
gak959f5cd2015-01-29 12:42:09 -080041import com.google.common.collect.ImmutableList;
gak16e0cd42014-09-18 09:24:04 -070042import com.google.common.collect.ImmutableMap;
43import com.google.common.collect.ImmutableSet;
44import com.google.common.collect.ImmutableSetMultimap;
dpb99d64082015-11-12 11:27:12 -080045import com.google.common.collect.Iterables;
gak959f5cd2015-01-29 12:42:09 -080046import com.google.common.collect.Lists;
gak16e0cd42014-09-18 09:24:04 -070047import com.google.common.collect.Maps;
gakd296d892015-03-10 23:34:03 -070048import com.google.common.collect.Sets;
gak9b81e102015-09-15 14:45:43 -070049import com.google.common.collect.TreeTraverser;
dpb4cd56e82016-03-30 10:12:27 -070050import dagger.Reusable;
gak60ebd652016-08-17 12:48:52 -070051import dagger.Subcomponent;
bederb50b8ae2016-12-07 08:36:26 -080052import dagger.internal.codegen.ComponentDescriptor.BuilderRequirementMethod;
gak6322fe72015-04-03 14:57:16 -070053import dagger.internal.codegen.ComponentDescriptor.ComponentMethodDescriptor;
ronshapirofbb68402016-08-31 06:44:45 -070054import dagger.internal.codegen.ContributionBinding.Kind;
ronshapiro846fd942016-06-01 11:50:01 -070055import dagger.internal.codegen.Key.HasKey;
dpb1da29992016-06-24 07:54:52 -070056import dagger.producers.Produced;
57import dagger.producers.Producer;
jneufeld1756a902015-07-01 15:22:25 -070058import java.util.ArrayDeque;
dpbf0255312015-07-27 15:43:19 -070059import java.util.Collection;
gak16e0cd42014-09-18 09:24:04 -070060import java.util.Deque;
dpb9563a022017-06-05 08:39:15 -070061import java.util.HashMap;
dpb67c87972015-08-12 09:43:27 -070062import java.util.HashSet;
dpb51bf8b42015-12-18 09:59:56 -080063import java.util.LinkedHashSet;
gak16e0cd42014-09-18 09:24:04 -070064import java.util.List;
65import java.util.Map;
dpbffd98f62016-12-20 10:05:16 -080066import java.util.Optional;
ronshapirofbb68402016-08-31 06:44:45 -070067import java.util.Queue;
dpb67c87972015-08-12 09:43:27 -070068import java.util.Set;
bederb50b8ae2016-12-07 08:36:26 -080069import java.util.stream.Stream;
70import java.util.stream.StreamSupport;
dpbba28f412015-09-24 13:11:21 -070071import javax.inject.Inject;
dpb1da29992016-06-24 07:54:52 -070072import javax.inject.Provider;
cgruber1fef5762014-11-09 13:00:07 -080073import javax.lang.model.element.AnnotationMirror;
gak16e0cd42014-09-18 09:24:04 -070074import javax.lang.model.element.ExecutableElement;
gak16e0cd42014-09-18 09:24:04 -070075import javax.lang.model.element.TypeElement;
gak16e0cd42014-09-18 09:24:04 -070076import javax.lang.model.util.ElementFilter;
77import javax.lang.model.util.Elements;
gak16e0cd42014-09-18 09:24:04 -070078
gak16e0cd42014-09-18 09:24:04 -070079/**
80 * The canonical representation of a full-resolved graph.
81 *
82 * @author Gregory Kick
83 */
84@AutoValue
85abstract class BindingGraph {
86 abstract ComponentDescriptor componentDescriptor();
beder3e950f32014-12-19 17:48:47 -080087 abstract ImmutableMap<BindingKey, ResolvedBindings> resolvedBindings();
ronshapirofbb68402016-08-31 06:44:45 -070088 abstract ImmutableSet<BindingGraph> subgraphs();
gak16e0cd42014-09-18 09:24:04 -070089
dpb141148b2016-10-20 12:31:34 -070090 /** Returns the resolved bindings for the dependencies of {@code binding}. */
91 ImmutableSet<ResolvedBindings> resolvedDependencies(ContributionBinding binding) {
92 return binding
93 .dependencies()
94 .stream()
95 .map(
96 dependencyRequest ->
97 resolvedBindings()
98 .getOrDefault(
99 dependencyRequest.bindingKey(),
100 ResolvedBindings.noBindings(
101 dependencyRequest.bindingKey(), componentDescriptor())))
102 .collect(toImmutableSet());
103 }
gak5721a932015-07-16 11:40:57 -0700104 /**
dpb86fe3c72016-10-07 10:50:45 -0700105 * The type that defines the component for this graph.
106 *
107 * @see ComponentDescriptor#componentDefinitionType()
108 */
109 TypeElement componentType() {
110 return componentDescriptor().componentDefinitionType();
111 }
112
113 /**
gak3a5e81e2015-08-25 16:22:26 -0700114 * Returns the set of modules that are owned by this graph regardless of whether or not any of
dpbb37b9ed2016-11-11 14:17:07 -0800115 * their bindings are used in this graph. For graphs representing top-level {@link
116 * dagger.Component components}, this set will be the same as
gak3a5e81e2015-08-25 16:22:26 -0700117 * {@linkplain ComponentDescriptor#transitiveModules the component's transitive modules}. For
118 * {@linkplain Subcomponent subcomponents}, this set will be the transitive modules that are not
119 * owned by any of their ancestors.
120 */
121 abstract ImmutableSet<ModuleDescriptor> ownedModules();
122
123 ImmutableSet<TypeElement> ownedModuleTypes() {
gak66241102016-09-13 12:23:00 -0700124 return FluentIterable.from(ownedModules()).transform(ModuleDescriptor::moduleElement).toSet();
gak3a5e81e2015-08-25 16:22:26 -0700125 }
126
gak9b81e102015-09-15 14:45:43 -0700127 private static final TreeTraverser<BindingGraph> SUBGRAPH_TRAVERSER =
128 new TreeTraverser<BindingGraph>() {
129 @Override
130 public Iterable<BindingGraph> children(BindingGraph node) {
ronshapirofbb68402016-08-31 06:44:45 -0700131 return node.subgraphs();
gak9b81e102015-09-15 14:45:43 -0700132 }
133 };
134
gak3a5e81e2015-08-25 16:22:26 -0700135 /**
dpbf7647002016-04-21 14:31:35 -0700136 * The types for which the component needs instances.
bederb50b8ae2016-12-07 08:36:26 -0800137 *
dpbf7647002016-04-21 14:31:35 -0700138 * <ul>
bederb50b8ae2016-12-07 08:36:26 -0800139 * <li>component dependencies
140 * <li>{@linkplain #ownedModules() owned modules} with concrete instance bindings that are used
141 * in the graph
142 * <li>bound instances
dpbf7647002016-04-21 14:31:35 -0700143 * </ul>
gak5721a932015-07-16 11:40:57 -0700144 */
ronshapiro76fe9b92016-11-07 14:55:51 -0800145 @Memoized
bederb50b8ae2016-12-07 08:36:26 -0800146 ImmutableSet<ComponentRequirement> componentRequirements() {
147 ImmutableSet.Builder<ComponentRequirement> requirements = ImmutableSet.builder();
148 StreamSupport.stream(SUBGRAPH_TRAVERSER.preOrderTraversal(this).spliterator(), false)
149 .flatMap(graph -> graph.resolvedBindings().values().stream())
150 .flatMap(bindings -> bindings.contributionBindings().stream())
gak66241102016-09-13 12:23:00 -0700151 .filter(ContributionBinding::requiresModuleInstance)
dpbffd98f62016-12-20 10:05:16 -0800152 .map(bindingDeclaration -> bindingDeclaration.contributingModule())
153 .filter(Optional::isPresent)
154 .map(Optional::get)
bederb50b8ae2016-12-07 08:36:26 -0800155 .filter(module -> ownedModuleTypes().contains(module))
156 .map(module -> ComponentRequirement.forModule(module.asType()))
157 .forEach(requirements::add);
158 componentDescriptor()
159 .dependencies()
160 .stream()
161 .map(dep -> ComponentRequirement.forDependency(dep.asType()))
162 .forEach(requirements::add);
163 if (componentDescriptor().builderSpec().isPresent()) {
164 componentDescriptor()
165 .builderSpec()
166 .get()
167 .requirementMethods()
168 .stream()
169 .map(BuilderRequirementMethod::requirement)
170 .filter(req -> req.kind().equals(ComponentRequirement.Kind.BINDING))
171 .forEach(requirements::add);
172 }
173 return requirements.build();
gak3a5e81e2015-08-25 16:22:26 -0700174 }
bederb50b8ae2016-12-07 08:36:26 -0800175 /** Returns the {@link ComponentDescriptor}s for this component and its subcomponents. */
ronshapiro0771bf02015-11-30 10:11:23 -0800176 ImmutableSet<ComponentDescriptor> componentDescriptors() {
gak66241102016-09-13 12:23:00 -0700177 return SUBGRAPH_TRAVERSER
178 .preOrderTraversal(this)
179 .transform(BindingGraph::componentDescriptor)
180 .toSet();
ronshapiro0771bf02015-11-30 10:11:23 -0800181 }
182
bederb50b8ae2016-12-07 08:36:26 -0800183 ImmutableSet<ComponentRequirement> availableDependencies() {
184 return Stream.concat(
185 componentDescriptor()
186 .transitiveModuleTypes()
187 .stream()
188 .filter(dep -> !dep.getModifiers().contains(ABSTRACT))
189 .map(module -> ComponentRequirement.forModule(module.asType())),
190 componentDescriptor()
191 .dependencies()
192 .stream()
193 .map(dep -> ComponentRequirement.forDependency(dep.asType())))
194 .collect(toImmutableSet());
gak5721a932015-07-16 11:40:57 -0700195 }
196
gak16e0cd42014-09-18 09:24:04 -0700197 static final class Factory {
198 private final Elements elements;
gak16e0cd42014-09-18 09:24:04 -0700199 private final InjectBindingRegistry injectBindingRegistry;
200 private final Key.Factory keyFactory;
gak16e0cd42014-09-18 09:24:04 -0700201 private final ProvisionBinding.Factory provisionBindingFactory;
bederca9c82b2015-01-23 18:30:22 -0800202 private final ProductionBinding.Factory productionBindingFactory;
gak16e0cd42014-09-18 09:24:04 -0700203
dpbd8d950a2016-08-30 09:24:37 -0700204 Factory(
205 Elements elements,
gak16e0cd42014-09-18 09:24:04 -0700206 InjectBindingRegistry injectBindingRegistry,
beder3e950f32014-12-19 17:48:47 -0800207 Key.Factory keyFactory,
bederca9c82b2015-01-23 18:30:22 -0800208 ProvisionBinding.Factory provisionBindingFactory,
209 ProductionBinding.Factory productionBindingFactory) {
gak16e0cd42014-09-18 09:24:04 -0700210 this.elements = elements;
gak16e0cd42014-09-18 09:24:04 -0700211 this.injectBindingRegistry = injectBindingRegistry;
212 this.keyFactory = keyFactory;
gak16e0cd42014-09-18 09:24:04 -0700213 this.provisionBindingFactory = provisionBindingFactory;
bederca9c82b2015-01-23 18:30:22 -0800214 this.productionBindingFactory = productionBindingFactory;
gak16e0cd42014-09-18 09:24:04 -0700215 }
216
217 BindingGraph create(ComponentDescriptor componentDescriptor) {
dpbffd98f62016-12-20 10:05:16 -0800218 return create(Optional.empty(), componentDescriptor);
gak959f5cd2015-01-29 12:42:09 -0800219 }
220
gak3a5e81e2015-08-25 16:22:26 -0700221 private BindingGraph create(
222 Optional<Resolver> parentResolver, ComponentDescriptor componentDescriptor) {
dpb6bd55de2015-09-28 07:58:09 -0700223 ImmutableSet.Builder<ContributionBinding> explicitBindingsBuilder = ImmutableSet.builder();
gake1b68a22016-04-07 11:54:06 -0700224 ImmutableSet.Builder<DelegateDeclaration> delegatesBuilder = ImmutableSet.builder();
dpbd8d950a2016-08-30 09:24:37 -0700225 ImmutableSet.Builder<OptionalBindingDeclaration> optionalsBuilder = ImmutableSet.builder();
gak16e0cd42014-09-18 09:24:04 -0700226
227 // binding for the component itself
dpbb37b9ed2016-11-11 14:17:07 -0800228 explicitBindingsBuilder.add(
229 provisionBindingFactory.forComponent(componentDescriptor.componentDefinitionType()));
gak16e0cd42014-09-18 09:24:04 -0700230
231 // Collect Component dependencies.
dpbb37b9ed2016-11-11 14:17:07 -0800232 for (TypeElement componentDependency : componentDescriptor.dependencies()) {
ronshapirodc07ed52017-08-23 08:52:10 -0700233 explicitBindingsBuilder.add(
234 provisionBindingFactory.forComponentDependency(componentDependency));
gak16e0cd42014-09-18 09:24:04 -0700235 List<ExecutableElement> dependencyMethods =
236 ElementFilter.methodsIn(elements.getAllMembers(componentDependency));
237 for (ExecutableElement method : dependencyMethods) {
bederca9c82b2015-01-23 18:30:22 -0800238 // MembersInjection methods aren't "provided" explicitly, so ignore them.
239 if (isComponentContributionMethod(elements, method)) {
dpb6bd55de2015-09-28 07:58:09 -0700240 explicitBindingsBuilder.add(
241 componentDescriptor.kind().equals(PRODUCTION_COMPONENT)
242 && isComponentProductionMethod(elements, method)
243 ? productionBindingFactory.forComponentMethod(method)
244 : provisionBindingFactory.forComponentMethod(method));
gak16e0cd42014-09-18 09:24:04 -0700245 }
246 }
247 }
248
bederb50b8ae2016-12-07 08:36:26 -0800249 // Collect bindings on the builder.
250 if (componentDescriptor.builderSpec().isPresent()) {
251 for (BuilderRequirementMethod method :
252 componentDescriptor.builderSpec().get().requirementMethods()) {
253 if (method.requirement().kind().equals(ComponentRequirement.Kind.BINDING)) {
254 explicitBindingsBuilder.add(provisionBindingFactory.forBuilderBinding(method));
255 }
256 }
257 }
258
ronshapirofbb68402016-08-31 06:44:45 -0700259 for (Map.Entry<ComponentMethodDescriptor, ComponentDescriptor>
260 componentMethodAndSubcomponent :
261 componentDescriptor.subcomponentsByBuilderMethod().entrySet()) {
262 ComponentMethodDescriptor componentMethod = componentMethodAndSubcomponent.getKey();
263 ComponentDescriptor subcomponentDescriptor = componentMethodAndSubcomponent.getValue();
264 if (!componentDescriptor.subcomponentsFromModules().contains(subcomponentDescriptor)) {
265 explicitBindingsBuilder.add(
266 provisionBindingFactory.forSubcomponentBuilderMethod(
267 componentMethod.methodElement(),
268 componentDescriptor.componentDefinitionType()));
269 }
dpb99d64082015-11-12 11:27:12 -0800270 }
271
dpb51bf8b42015-12-18 09:59:56 -0800272 ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations =
273 ImmutableSet.builder();
ronshapirofbb68402016-08-31 06:44:45 -0700274 ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations =
275 ImmutableSet.builder();
dpb51bf8b42015-12-18 09:59:56 -0800276
277 // Collect transitive module bindings and multibinding declarations.
gak5721a932015-07-16 11:40:57 -0700278 for (ModuleDescriptor moduleDescriptor : componentDescriptor.transitiveModules()) {
dpb51bf8b42015-12-18 09:59:56 -0800279 explicitBindingsBuilder.addAll(moduleDescriptor.bindings());
280 multibindingDeclarations.addAll(moduleDescriptor.multibindingDeclarations());
ronshapirofbb68402016-08-31 06:44:45 -0700281 subcomponentDeclarations.addAll(moduleDescriptor.subcomponentDeclarations());
gake1b68a22016-04-07 11:54:06 -0700282 delegatesBuilder.addAll(moduleDescriptor.delegateDeclarations());
dpbd8d950a2016-08-30 09:24:37 -0700283 optionalsBuilder.addAll(moduleDescriptor.optionalDeclarations());
gak16e0cd42014-09-18 09:24:04 -0700284 }
285
ronshapirod804a302016-11-08 10:21:56 -0800286 // TODO(dpb,gak): Do we need to bind an empty Set<ReleasableReferenceManager> if there are
287 // none?
288 for (Scope scope : componentDescriptor.releasableReferencesScopes()) {
289 // Add a binding for @ForReleasableReferences(scope) ReleasableReferenceManager.
290 explicitBindingsBuilder.add(
291 provisionBindingFactory.provideReleasableReferenceManager(scope));
292
293 /* Add a binding for Set<ReleasableReferenceManager>. Even if these are added more than
294 * once, each instance will be equal to the rest. Since they're being added to a set, there
295 * will be only one instance. */
296 explicitBindingsBuilder.add(
297 provisionBindingFactory.provideSetOfReleasableReferenceManagers());
298
299 for (AnnotationMirror metadata : scope.releasableReferencesMetadata()) {
300 // Add a binding for @ForReleasableReferences(scope) TypedReleasableReferenceManager<M>.
301 explicitBindingsBuilder.add(
302 provisionBindingFactory.provideTypedReleasableReferenceManager(
303 scope, metadata.getAnnotationType()));
304
305 /* Add a binding for Set<TypedReleasableReferenceManager<M>>. Even if these are added more
306 * than once, each instance will be equal to the rest. Since they're being added to a set,
307 * there will be only one instance. */
308 explicitBindingsBuilder.add(
309 provisionBindingFactory.provideSetOfTypedReleasableReferenceManagers(
310 metadata.getAnnotationType()));
311 }
312 }
313
ronshapirofbb68402016-08-31 06:44:45 -0700314 final Resolver requestResolver =
gak3a5e81e2015-08-25 16:22:26 -0700315 new Resolver(
dpb51bf8b42015-12-18 09:59:56 -0800316 parentResolver,
317 componentDescriptor,
318 indexByKey(explicitBindingsBuilder.build()),
gake1b68a22016-04-07 11:54:06 -0700319 indexByKey(multibindingDeclarations.build()),
ronshapirofbb68402016-08-31 06:44:45 -0700320 indexByKey(subcomponentDeclarations.build()),
dpbd8d950a2016-08-30 09:24:37 -0700321 indexByKey(delegatesBuilder.build()),
322 indexByKey(optionalsBuilder.build()));
gak6322fe72015-04-03 14:57:16 -0700323 for (ComponentMethodDescriptor componentMethod : componentDescriptor.componentMethods()) {
324 Optional<DependencyRequest> componentMethodRequest = componentMethod.dependencyRequest();
325 if (componentMethodRequest.isPresent()) {
gakf53c3f92016-08-17 09:55:56 -0700326 requestResolver.resolve(componentMethodRequest.get().bindingKey());
gak6322fe72015-04-03 14:57:16 -0700327 }
gak16e0cd42014-09-18 09:24:04 -0700328 }
329
ronshapirofbb68402016-08-31 06:44:45 -0700330 // Resolve all bindings for subcomponents, creating subgraphs for all subcomponents that have
331 // been detected during binding resolution. If a binding for a subcomponent is never resolved,
332 // no BindingGraph will be created for it and no implementation will be generated. This is
333 // done in a queue since resolving one subcomponent might resolve a key for a subcomponent
334 // from a parent graph. This is done until no more new subcomponents are resolved.
335 Set<ComponentDescriptor> resolvedSubcomponents = new HashSet<>();
336 ImmutableSet.Builder<BindingGraph> subgraphs = ImmutableSet.builder();
337 for (ComponentDescriptor subcomponent :
338 Iterables.consumingIterable(requestResolver.subcomponentsToResolve)) {
339 if (resolvedSubcomponents.add(subcomponent)) {
340 subgraphs.add(create(Optional.of(requestResolver), subcomponent));
341 }
gak959f5cd2015-01-29 12:42:09 -0800342 }
343
gak924b5f42015-08-25 13:27:02 -0700344 for (ResolvedBindings resolvedBindings : requestResolver.getResolvedBindings().values()) {
345 verify(
346 resolvedBindings.owningComponent().equals(componentDescriptor),
347 "%s is not owned by %s",
348 resolvedBindings,
349 componentDescriptor);
350 }
351
gak16e0cd42014-09-18 09:24:04 -0700352 return new AutoValue_BindingGraph(
353 componentDescriptor,
gak78ac3682015-03-30 15:48:00 -0700354 requestResolver.getResolvedBindings(),
ronshapirofbb68402016-08-31 06:44:45 -0700355 subgraphs.build(),
gak3a5e81e2015-08-25 16:22:26 -0700356 requestResolver.getOwnedModules());
gak16e0cd42014-09-18 09:24:04 -0700357 }
358
gak3a5e81e2015-08-25 16:22:26 -0700359 private final class Resolver {
360 final Optional<Resolver> parentResolver;
gak924b5f42015-08-25 13:27:02 -0700361 final ComponentDescriptor componentDescriptor;
dpb6bd55de2015-09-28 07:58:09 -0700362 final ImmutableSetMultimap<Key, ContributionBinding> explicitBindings;
363 final ImmutableSet<ContributionBinding> explicitBindingsSet;
dpbdb240722016-01-25 14:06:41 -0800364 final ImmutableSetMultimap<Key, ContributionBinding> explicitMultibindings;
dpb51bf8b42015-12-18 09:59:56 -0800365 final ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations;
ronshapirofbb68402016-08-31 06:44:45 -0700366 final ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations;
gake1b68a22016-04-07 11:54:06 -0700367 final ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations;
dpbd8d950a2016-08-30 09:24:37 -0700368 final ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations;
ronshapiro846fd942016-06-01 11:50:01 -0700369 final ImmutableSetMultimap<Key, DelegateDeclaration> delegateMultibindingDeclarations;
beder3e950f32014-12-19 17:48:47 -0800370 final Map<BindingKey, ResolvedBindings> resolvedBindings;
jneufeld1756a902015-07-01 15:22:25 -0700371 final Deque<BindingKey> cycleStack = new ArrayDeque<>();
dpb9563a022017-06-05 08:39:15 -0700372 final Map<BindingKey, Boolean> bindingKeyDependsOnLocalBindingsCache = new HashMap<>();
373 final Map<Binding, Boolean> bindingDependsOnLocalBindingsCache = new HashMap<>();
ronshapirofbb68402016-08-31 06:44:45 -0700374 final Queue<ComponentDescriptor> subcomponentsToResolve = new ArrayDeque<>();
dpb778d5222015-12-22 08:33:07 -0800375
gak3a5e81e2015-08-25 16:22:26 -0700376 Resolver(
377 Optional<Resolver> parentResolver,
gak924b5f42015-08-25 13:27:02 -0700378 ComponentDescriptor componentDescriptor,
dpb51bf8b42015-12-18 09:59:56 -0800379 ImmutableSetMultimap<Key, ContributionBinding> explicitBindings,
gake1b68a22016-04-07 11:54:06 -0700380 ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations,
ronshapirofbb68402016-08-31 06:44:45 -0700381 ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations,
dpbd8d950a2016-08-30 09:24:37 -0700382 ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations,
383 ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations) {
ronshapirod6973272016-07-20 15:41:23 -0700384 this.parentResolver = checkNotNull(parentResolver);
385 this.componentDescriptor = checkNotNull(componentDescriptor);
386 this.explicitBindings = checkNotNull(explicitBindings);
dpb6bd55de2015-09-28 07:58:09 -0700387 this.explicitBindingsSet = ImmutableSet.copyOf(explicitBindings.values());
ronshapirod6973272016-07-20 15:41:23 -0700388 this.multibindingDeclarations = checkNotNull(multibindingDeclarations);
ronshapirofbb68402016-08-31 06:44:45 -0700389 this.subcomponentDeclarations = checkNotNull(subcomponentDeclarations);
ronshapirod6973272016-07-20 15:41:23 -0700390 this.delegateDeclarations = checkNotNull(delegateDeclarations);
dpbd8d950a2016-08-30 09:24:37 -0700391 this.optionalBindingDeclarations = checkNotNull(optionalBindingDeclarations);
gak16e0cd42014-09-18 09:24:04 -0700392 this.resolvedBindings = Maps.newLinkedHashMap();
ronshapiro846fd942016-06-01 11:50:01 -0700393 this.explicitMultibindings =
dpb90263a52016-07-13 07:52:41 -0700394 multibindingContributionsByMultibindingKey(explicitBindingsSet);
ronshapiro846fd942016-06-01 11:50:01 -0700395 this.delegateMultibindingDeclarations =
dpb90263a52016-07-13 07:52:41 -0700396 multibindingContributionsByMultibindingKey(delegateDeclarations.values());
ronshapirofbb68402016-08-31 06:44:45 -0700397 subcomponentsToResolve.addAll(componentDescriptor.subcomponentsFromEntryPoints());
gak16e0cd42014-09-18 09:24:04 -0700398 }
399
gak959f5cd2015-01-29 12:42:09 -0800400 /**
gakf53c3f92016-08-17 09:55:56 -0700401 * Returns the bindings for the given {@link BindingKey}.
dpbba28f412015-09-24 13:11:21 -0700402 *
dpbdb8fa1a2015-12-04 07:22:14 -0800403 * <p>For {@link BindingKey.Kind#CONTRIBUTION} requests, returns all of:
gakf53c3f92016-08-17 09:55:56 -0700404 *
dpbdb8fa1a2015-12-04 07:22:14 -0800405 * <ul>
dpb828b1a22016-06-14 08:22:11 -0700406 * <li>All explicit bindings for:
407 * <ul>
408 * <li>the requested key
409 * <li>{@code Set<T>} if the requested key's type is {@code Set<Produced<T>>}
gakf53c3f92016-08-17 09:55:56 -0700410 * <li>{@code Map<K, Provider<V>>} if the requested key's type is {@code Map<K,
411 * Producer<V>>}.
dpb828b1a22016-06-14 08:22:11 -0700412 * </ul>
413 *
dpbdb8fa1a2015-12-04 07:22:14 -0800414 * <li>A synthetic binding that depends on {@code Map<K, Producer<V>>} if the requested key's
gakf53c3f92016-08-17 09:55:56 -0700415 * type is {@code Map<K, V>} and there are some explicit bindings for {@code Map<K,
416 * Producer<V>>}.
dpbdb8fa1a2015-12-04 07:22:14 -0800417 * <li>A synthetic binding that depends on {@code Map<K, Provider<V>>} if the requested key's
gakf53c3f92016-08-17 09:55:56 -0700418 * type is {@code Map<K, V>} and there are some explicit bindings for {@code Map<K,
419 * Provider<V>>} but no explicit bindings for {@code Map<K, Producer<V>>}.
dpbdb8fa1a2015-12-04 07:22:14 -0800420 * <li>An implicit {@link Inject @Inject}-annotated constructor binding if there is one and
421 * there are no explicit bindings or synthetic bindings.
422 * </ul>
dpbba28f412015-09-24 13:11:21 -0700423 *
gakf53c3f92016-08-17 09:55:56 -0700424 * <p>For {@link BindingKey.Kind#MEMBERS_INJECTION} requests, returns the {@link
425 * MembersInjectionBinding} for the type.
gak959f5cd2015-01-29 12:42:09 -0800426 */
gakf53c3f92016-08-17 09:55:56 -0700427 ResolvedBindings lookUpBindings(BindingKey bindingKey) {
dpb828b1a22016-06-14 08:22:11 -0700428 Key requestKey = bindingKey.key();
bederdbe0e9c2015-01-06 12:19:22 -0800429 switch (bindingKey.kind()) {
430 case CONTRIBUTION:
dpb51bf8b42015-12-18 09:59:56 -0800431 Set<ContributionBinding> contributionBindings = new LinkedHashSet<>();
dpb1da29992016-06-24 07:54:52 -0700432 ImmutableSet.Builder<ContributionBinding> multibindingContributionsBuilder =
433 ImmutableSet.builder();
dpb51bf8b42015-12-18 09:59:56 -0800434 ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarationsBuilder =
dpbbf29ab32015-12-09 07:37:21 -0800435 ImmutableSet.builder();
ronshapirofbb68402016-08-31 06:44:45 -0700436 ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarationsBuilder =
437 ImmutableSet.builder();
dpbd8d950a2016-08-30 09:24:37 -0700438 ImmutableSet.Builder<OptionalBindingDeclaration> optionalBindingDeclarationsBuilder =
439 ImmutableSet.builder();
bederca9c82b2015-01-23 18:30:22 -0800440
dpb828b1a22016-06-14 08:22:11 -0700441 for (Key key : keysMatchingRequest(requestKey)) {
442 contributionBindings.addAll(getExplicitBindings(key));
ronshapirod6973272016-07-20 15:41:23 -0700443 multibindingContributionsBuilder.addAll(getExplicitMultibindings(key));
dpb828b1a22016-06-14 08:22:11 -0700444 multibindingDeclarationsBuilder.addAll(getMultibindingDeclarations(key));
ronshapirofbb68402016-08-31 06:44:45 -0700445 subcomponentDeclarationsBuilder.addAll(getSubcomponentDeclarations(key));
dpbd8d950a2016-08-30 09:24:37 -0700446 optionalBindingDeclarationsBuilder.addAll(getOptionalBindingDeclarations(key));
ronshapiro846fd942016-06-01 11:50:01 -0700447 }
dpb51bf8b42015-12-18 09:59:56 -0800448
dpb1da29992016-06-24 07:54:52 -0700449 ImmutableSet<ContributionBinding> multibindingContributions =
450 multibindingContributionsBuilder.build();
ronshapiro23c17b82016-06-10 09:57:13 -0700451 ImmutableSet<MultibindingDeclaration> multibindingDeclarations =
452 multibindingDeclarationsBuilder.build();
ronshapirofbb68402016-08-31 06:44:45 -0700453 ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations =
454 subcomponentDeclarationsBuilder.build();
dpbd8d950a2016-08-30 09:24:37 -0700455 ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations =
456 optionalBindingDeclarationsBuilder.build();
ronshapiro23c17b82016-06-10 09:57:13 -0700457
dpbffd98f62016-12-20 10:05:16 -0800458 ImmutableSet.Builder<Optional<ContributionBinding>> maybeContributionBindings =
459 ImmutableSet.builder();
460 maybeContributionBindings.add(syntheticMapOfValuesBinding(requestKey));
461 maybeContributionBindings.add(
gakf53c3f92016-08-17 09:55:56 -0700462 syntheticMultibinding(
dpbffd98f62016-12-20 10:05:16 -0800463 requestKey, multibindingContributions, multibindingDeclarations));
464 syntheticSubcomponentBuilderBinding(subcomponentDeclarations)
465 .ifPresent(
466 binding -> {
467 contributionBindings.add(binding);
468 addSubcomponentToOwningResolver(binding);
469 });
470 maybeContributionBindings.add(
471 syntheticOptionalBinding(requestKey, optionalBindingDeclarations));
dpbdb240722016-01-25 14:06:41 -0800472
dpb1da29992016-06-24 07:54:52 -0700473 /* If there are no bindings, add the implicit @Inject-constructed binding if there is
474 * one. */
dpb828b1a22016-06-14 08:22:11 -0700475 if (contributionBindings.isEmpty()) {
dpbffd98f62016-12-20 10:05:16 -0800476 maybeContributionBindings.add(
477 injectBindingRegistry
478 .getOrFindProvisionBinding(requestKey)
479 .map((ContributionBinding b) -> b));
bederdbe0e9c2015-01-06 12:19:22 -0800480 }
dpb51bf8b42015-12-18 09:59:56 -0800481
dpbffd98f62016-12-20 10:05:16 -0800482 maybeContributionBindings
483 .build()
484 .stream()
485 .filter(Optional::isPresent)
486 .map(Optional::get)
487 .forEach(contributionBindings::add);
488
dpbdb8fa1a2015-12-04 07:22:14 -0800489 return ResolvedBindings.forContributionBindings(
490 bindingKey,
491 componentDescriptor,
gakf53c3f92016-08-17 09:55:56 -0700492 indexBindingsByOwningComponent(
493 bindingKey, ImmutableSet.copyOf(contributionBindings)),
dpbd8d950a2016-08-30 09:24:37 -0700494 multibindingDeclarations,
ronshapirofbb68402016-08-31 06:44:45 -0700495 subcomponentDeclarations,
dpbd8d950a2016-08-30 09:24:37 -0700496 optionalBindingDeclarations);
dpb6bd55de2015-09-28 07:58:09 -0700497
bederdbe0e9c2015-01-06 12:19:22 -0800498 case MEMBERS_INJECTION:
499 // no explicit deps for members injection, so just look it up
bederc82d8ab2015-12-30 06:45:27 -0800500 Optional<MembersInjectionBinding> binding =
dpb828b1a22016-06-14 08:22:11 -0700501 injectBindingRegistry.getOrFindMembersInjectionBinding(requestKey);
bederc82d8ab2015-12-30 06:45:27 -0800502 return binding.isPresent()
503 ? ResolvedBindings.forMembersInjectionBinding(
504 bindingKey, componentDescriptor, binding.get())
505 : ResolvedBindings.noBindings(bindingKey, componentDescriptor);
dpb1da29992016-06-24 07:54:52 -0700506
bederdbe0e9c2015-01-06 12:19:22 -0800507 default:
508 throw new AssertionError();
509 }
510 }
511
ronshapirofbb68402016-08-31 06:44:45 -0700512 /**
513 * When a binding is resolved for a {@link SubcomponentDeclaration}, adds corresponding
514 * {@link ComponentDescriptor subcomponent} to a queue in the owning component's resolver.
515 * The queue will be used to detect which subcomponents need to be resolved.
516 */
517 private void addSubcomponentToOwningResolver(ProvisionBinding subcomponentBuilderBinding) {
518 checkArgument(subcomponentBuilderBinding.bindingKind().equals(Kind.SUBCOMPONENT_BUILDER));
519 Resolver owningResolver = getOwningResolver(subcomponentBuilderBinding).get();
520
521 TypeElement builderType = MoreTypes.asTypeElement(subcomponentBuilderBinding.key().type());
522 owningResolver.subcomponentsToResolve.add(
523 owningResolver.componentDescriptor.subcomponentsByBuilderType().get(builderType));
524 }
525
dpb828b1a22016-06-14 08:22:11 -0700526 private Iterable<Key> keysMatchingRequest(Key requestKey) {
dpbffd98f62016-12-20 10:05:16 -0800527 ImmutableSet.Builder<Key> keys = ImmutableSet.builder();
528 keys.add(requestKey);
529 keyFactory.unwrapSetKey(requestKey, Produced.class).ifPresent(keys::add);
530 keyFactory.rewrapMapKey(requestKey, Producer.class, Provider.class).ifPresent(keys::add);
531 keyFactory.rewrapMapKey(requestKey, Provider.class, Producer.class).ifPresent(keys::add);
532 return keys.build();
ronshapiro846fd942016-06-01 11:50:01 -0700533 }
534
dpb1da29992016-06-24 07:54:52 -0700535 /**
gakf53c3f92016-08-17 09:55:56 -0700536 * If {@code key} is a {@code Map<K, V>} or {@code Map<K, Produced<V>>}, and there are any
537 * multibinding contributions or declarations that apply to that map, returns a synthetic
538 * binding for the {@code key} that depends on an {@linkplain #syntheticMultibinding(Key,
539 * Iterable, Iterable) underlying synthetic multibinding}.
dpb1da29992016-06-24 07:54:52 -0700540 *
541 * <p>The returned binding has the same {@link BindingType} as the underlying synthetic
542 * multibinding.
543 */
gakf53c3f92016-08-17 09:55:56 -0700544 private Optional<ContributionBinding> syntheticMapOfValuesBinding(final Key key) {
dpb1da29992016-06-24 07:54:52 -0700545 return syntheticMultibinding(
gakf53c3f92016-08-17 09:55:56 -0700546 key,
547 multibindingContributionsForValueMap(key),
548 multibindingDeclarationsForValueMap(key))
dpbffd98f62016-12-20 10:05:16 -0800549 .map(
gak66241102016-09-13 12:23:00 -0700550 syntheticMultibinding -> {
551 switch (syntheticMultibinding.bindingType()) {
552 case PROVISION:
553 return provisionBindingFactory.syntheticMapOfValuesBinding(key);
ronshapiro23c17b82016-06-10 09:57:13 -0700554
gak66241102016-09-13 12:23:00 -0700555 case PRODUCTION:
556 return productionBindingFactory.syntheticMapOfValuesOrProducedBinding(key);
ronshapiro23c17b82016-06-10 09:57:13 -0700557
gak66241102016-09-13 12:23:00 -0700558 default:
559 throw new VerifyException(syntheticMultibinding.toString());
dpb1da29992016-06-24 07:54:52 -0700560 }
561 });
562 }
563
564 /**
dpb08350312016-09-27 10:12:41 -0700565 * If {@code key} is for {@code Map<K, V>} or {@code Map<K, Produced<V>>}, returns all
dpb1da29992016-06-24 07:54:52 -0700566 * multibinding contributions whose key is for {@code Map<K, Provider<V>>} or {@code Map<K,
567 * Producer<V>>} with the same qualifier and {@code K} and {@code V}.
568 */
dpbffd98f62016-12-20 10:05:16 -0800569 private ImmutableSet<ContributionBinding> multibindingContributionsForValueMap(Key key) {
dpb1da29992016-06-24 07:54:52 -0700570 return keyFactory
dpb08350312016-09-27 10:12:41 -0700571 .implicitFrameworkMapKeys(key)
dpbffd98f62016-12-20 10:05:16 -0800572 .stream()
573 .flatMap(mapKey -> getExplicitMultibindings(mapKey).stream())
574 .collect(toImmutableSet());
dpb1da29992016-06-24 07:54:52 -0700575 }
576
577 /**
dpb08350312016-09-27 10:12:41 -0700578 * If {@code key} is for {@code Map<K, V>} or {@code Map<K, Produced<V>>}, returns all
dpb1da29992016-06-24 07:54:52 -0700579 * multibinding declarations whose key is for {@code Map<K, Provider<V>>} or {@code Map<K,
580 * Producer<V>>} with the same qualifier and {@code K} and {@code V}.
581 */
dpbffd98f62016-12-20 10:05:16 -0800582 private ImmutableSet<MultibindingDeclaration> multibindingDeclarationsForValueMap(Key key) {
dpb1da29992016-06-24 07:54:52 -0700583 return keyFactory
dpb08350312016-09-27 10:12:41 -0700584 .implicitFrameworkMapKeys(key)
dpbffd98f62016-12-20 10:05:16 -0800585 .stream()
586 .flatMap(mapKey -> getMultibindingDeclarations(mapKey).stream())
587 .collect(toImmutableSet());
dpb1da29992016-06-24 07:54:52 -0700588 }
589
590 /**
591 * Returns a synthetic binding that depends on individual multibinding contributions.
592 *
593 * <p>If there are no {@code multibindingContributions} or {@code multibindingDeclarations},
dpbffd98f62016-12-20 10:05:16 -0800594 * returns {@link Optional#empty()}.
dpb1da29992016-06-24 07:54:52 -0700595 *
596 * <p>If there are production {@code multibindingContributions} or the request is for any of
597 * the following types, returns a {@link ProductionBinding}.
598 *
599 * <ul>
dpbffd98f62016-12-20 10:05:16 -0800600 * <li>{@code Set<Produced<T>>}
601 * <li>{@code Map<K, Producer<V>>}
602 * <li>{@code Map<K, Produced<V>>}
dpb1da29992016-06-24 07:54:52 -0700603 * </ul>
604 *
605 * Otherwise, returns a {@link ProvisionBinding}.
606 */
dpbffd98f62016-12-20 10:05:16 -0800607 private Optional<ContributionBinding> syntheticMultibinding(
gakf53c3f92016-08-17 09:55:56 -0700608 Key key,
dpb1da29992016-06-24 07:54:52 -0700609 Iterable<ContributionBinding> multibindingContributions,
610 Iterable<MultibindingDeclaration> multibindingDeclarations) {
611 if (isEmpty(multibindingContributions) && isEmpty(multibindingDeclarations)) {
dpbffd98f62016-12-20 10:05:16 -0800612 return Optional.empty();
gakf53c3f92016-08-17 09:55:56 -0700613 } else if (multibindingsRequireProduction(multibindingContributions, key)) {
dpb1da29992016-06-24 07:54:52 -0700614 return Optional.of(
gakf53c3f92016-08-17 09:55:56 -0700615 productionBindingFactory.syntheticMultibinding(key, multibindingContributions));
dpb1da29992016-06-24 07:54:52 -0700616 } else {
617 return Optional.of(
gakf53c3f92016-08-17 09:55:56 -0700618 provisionBindingFactory.syntheticMultibinding(key, multibindingContributions));
dpb1da29992016-06-24 07:54:52 -0700619 }
620 }
621
622 private boolean multibindingsRequireProduction(
dpb08350312016-09-27 10:12:41 -0700623 Iterable<ContributionBinding> multibindingContributions, Key key) {
624 if (MapType.isMap(key)) {
625 MapType mapType = MapType.from(key);
gakb1b536b2016-08-17 09:40:33 -0700626 if (mapType.valuesAreTypeOf(Producer.class) || mapType.valuesAreTypeOf(Produced.class)) {
ronshapiro23c17b82016-06-10 09:57:13 -0700627 return true;
gakb1b536b2016-08-17 09:40:33 -0700628 }
dpb08350312016-09-27 10:12:41 -0700629 } else if (SetType.isSet(key) && SetType.from(key).elementsAreTypeOf(Produced.class)) {
gakb1b536b2016-08-17 09:40:33 -0700630 return true;
ronshapiro23c17b82016-06-10 09:57:13 -0700631 }
gak66241102016-09-13 12:23:00 -0700632 return Iterables.any(multibindingContributions,
633 hasBindingType -> hasBindingType.bindingType().equals(BindingType.PRODUCTION));
ronshapiro846fd942016-06-01 11:50:01 -0700634 }
635
ronshapirofbb68402016-08-31 06:44:45 -0700636 private Optional<ProvisionBinding> syntheticSubcomponentBuilderBinding(
637 ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
638 return subcomponentDeclarations.isEmpty()
dpbffd98f62016-12-20 10:05:16 -0800639 ? Optional.empty()
ronshapirofbb68402016-08-31 06:44:45 -0700640 : Optional.of(
dpbffd98f62016-12-20 10:05:16 -0800641 provisionBindingFactory.syntheticSubcomponentBuilder(subcomponentDeclarations));
ronshapirofbb68402016-08-31 06:44:45 -0700642 }
643
dpbd8d950a2016-08-30 09:24:37 -0700644 /**
645 * Returns a synthetic binding for {@code @Qualifier Optional<Type>} if there are any {@code
646 * optionalBindingDeclarations}.
dpbe0998bd2016-09-09 12:40:48 -0700647 *
648 * <p>If there are no bindings for the underlying key (the key for dependency requests for
dpbffd98f62016-12-20 10:05:16 -0800649 * {@code Type}), returns a provision binding that always returns {@link Optional#empty()}.
dpbe0998bd2016-09-09 12:40:48 -0700650 *
651 * <p>If there are any production bindings for the underlying key, returns a production
652 * binding. Otherwise returns a provision binding.
dpbd8d950a2016-08-30 09:24:37 -0700653 */
dpbffd98f62016-12-20 10:05:16 -0800654 private Optional<ContributionBinding> syntheticOptionalBinding(
dpbd8d950a2016-08-30 09:24:37 -0700655 Key key, ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations) {
656 if (optionalBindingDeclarations.isEmpty()) {
dpbffd98f62016-12-20 10:05:16 -0800657 return Optional.empty();
dpbd8d950a2016-08-30 09:24:37 -0700658 }
ronshapiro3a891dd2017-07-04 20:04:14 -0700659 DependencyRequest.Kind kind =
660 DependencyRequest.extractKindAndType(OptionalType.from(key).valueType()).kind();
dpbe0998bd2016-09-09 12:40:48 -0700661 ResolvedBindings underlyingKeyBindings =
662 lookUpBindings(contribution(keyFactory.unwrapOptional(key).get()));
663 if (underlyingKeyBindings.isEmpty()) {
dpbd8d950a2016-08-30 09:24:37 -0700664 return Optional.of(provisionBindingFactory.syntheticAbsentBinding(key));
ronshapiro3a891dd2017-07-04 20:04:14 -0700665 } else if (underlyingKeyBindings.bindingTypes().contains(BindingType.PRODUCTION)
666 // handles producerFromProvider cases
667 || kind.equals(DependencyRequest.Kind.PRODUCER)
668 || kind.equals(DependencyRequest.Kind.PRODUCED)) {
669 return Optional.of(productionBindingFactory.syntheticPresentBinding(key, kind));
dpbe0998bd2016-09-09 12:40:48 -0700670 } else {
ronshapiro3a891dd2017-07-04 20:04:14 -0700671 return Optional.of(provisionBindingFactory.syntheticPresentBinding(key, kind));
dpbd8d950a2016-08-30 09:24:37 -0700672 }
673 }
674
dpb828b1a22016-06-14 08:22:11 -0700675 private ImmutableSet<ContributionBinding> createDelegateBindings(
gake1b68a22016-04-07 11:54:06 -0700676 ImmutableSet<DelegateDeclaration> delegateDeclarations) {
677 ImmutableSet.Builder<ContributionBinding> builder = ImmutableSet.builder();
678 for (DelegateDeclaration delegateDeclaration : delegateDeclarations) {
ronshapiroa0bd7752016-08-10 09:48:51 -0700679 builder.add(createDelegateBinding(delegateDeclaration));
gake1b68a22016-04-07 11:54:06 -0700680 }
681 return builder.build();
682 }
683
ronshapiroa0bd7752016-08-10 09:48:51 -0700684 /**
685 * Creates one (and only one) delegate binding for a delegate declaration, based on the
686 * resolved bindings of the right-hand-side of a {@link dagger.Binds} method. If there are
687 * duplicate bindings for the dependency key, there should still be only one binding for the
688 * delegate key.
689 */
690 private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDeclaration) {
ronshapiro21e95422016-09-06 11:07:42 -0700691 BindingKey delegateBindingKey = delegateDeclaration.delegateRequest().bindingKey();
692
693 if (cycleStack.contains(delegateBindingKey)) {
694 return provisionBindingFactory.missingDelegate(delegateDeclaration);
695 }
696
697 ResolvedBindings resolvedDelegate;
698 try {
699 cycleStack.push(delegateBindingKey);
700 resolvedDelegate = lookUpBindings(delegateBindingKey);
701 } finally {
702 cycleStack.pop();
703 }
ronshapiroa0bd7752016-08-10 09:48:51 -0700704 if (resolvedDelegate.contributionBindings().isEmpty()) {
705 // This is guaranteed to result in a missing binding error, so it doesn't matter if the
706 // binding is a Provision or Production, except if it is a @IntoMap method, in which
707 // case the key will be of type Map<K, Provider<V>>, which will be "upgraded" into a
708 // Map<K, Producer<V>> if it's requested in a ProductionComponent. This may result in a
709 // strange error, that the RHS needs to be provided with an @Inject or @Provides
710 // annotated method, but a user should be able to figure out if a @Produces annotation
711 // is needed.
712 // TODO(gak): revisit how we model missing delegates if/when we clean up how we model
713 // binding declarations
714 return provisionBindingFactory.missingDelegate(delegateDeclaration);
715 }
716 // It doesn't matter which of these is selected, since they will later on produce a
717 // duplicate binding error.
718 // TODO(ronshapiro): Once compile-testing has a CompilationResult, add a test which asserts
719 // that a duplicate binding for the RHS does not result in a duplicate binding for the LHS.
720 ContributionBinding explicitDelegate =
721 resolvedDelegate.contributionBindings().iterator().next();
722 switch (explicitDelegate.bindingType()) {
723 case PRODUCTION:
724 return productionBindingFactory.delegate(
725 delegateDeclaration, (ProductionBinding) explicitDelegate);
726 case PROVISION:
727 return provisionBindingFactory.delegate(
728 delegateDeclaration, (ProvisionBinding) explicitDelegate);
729 default:
730 throw new AssertionError("bindingType: " + explicitDelegate);
731 }
732 }
733
dpbdb8fa1a2015-12-04 07:22:14 -0800734 private ImmutableSetMultimap<ComponentDescriptor, ContributionBinding>
735 indexBindingsByOwningComponent(
gakf53c3f92016-08-17 09:55:56 -0700736 BindingKey bindingKey, Iterable<? extends ContributionBinding> bindings) {
dpbdb8fa1a2015-12-04 07:22:14 -0800737 ImmutableSetMultimap.Builder<ComponentDescriptor, ContributionBinding> index =
738 ImmutableSetMultimap.builder();
739 for (ContributionBinding binding : bindings) {
gakf53c3f92016-08-17 09:55:56 -0700740 index.put(getOwningComponent(bindingKey, binding), binding);
dpbdb8fa1a2015-12-04 07:22:14 -0800741 }
742 return index.build();
743 }
744
dpb76e07472015-08-04 15:43:09 -0700745 /**
dpb2df89f92016-05-24 06:53:48 -0700746 * Returns the component that should contain the framework field for {@code binding}.
dpb778d5222015-12-22 08:33:07 -0800747 *
dpb08350312016-09-27 10:12:41 -0700748 * <p>If {@code binding} is either not bound in an ancestor component or depends transitively
749 * on bindings in this component, returns this component.
dpb778d5222015-12-22 08:33:07 -0800750 *
dpb2df89f92016-05-24 06:53:48 -0700751 * <p>Otherwise, resolves {@code request} in this component's parent in order to resolve any
gakf53c3f92016-08-17 09:55:56 -0700752 * multibinding contributions in the parent, and returns the parent-resolved {@link
753 * ResolvedBindings#owningComponent(ContributionBinding)}.
dpb5dcbd962015-11-03 09:46:44 -0800754 */
755 private ComponentDescriptor getOwningComponent(
gakf53c3f92016-08-17 09:55:56 -0700756 BindingKey bindingKey, ContributionBinding binding) {
757 if (isResolvedInParent(bindingKey, binding)
dpb08350312016-09-27 10:12:41 -0700758 && !new LocalDependencyChecker().dependsOnLocalBindings(binding)) {
dpb2df89f92016-05-24 06:53:48 -0700759 ResolvedBindings parentResolvedBindings =
gakf53c3f92016-08-17 09:55:56 -0700760 parentResolver.get().resolvedBindings.get(bindingKey);
dpb2df89f92016-05-24 06:53:48 -0700761 return parentResolvedBindings.owningComponent(binding);
762 } else {
763 return componentDescriptor;
764 }
dpb5dcbd962015-11-03 09:46:44 -0800765 }
766
767 /**
gakf53c3f92016-08-17 09:55:56 -0700768 * Returns {@code true} if {@code binding} is owned by an ancestor. If so, {@linkplain
769 * #resolve resolves} the {@link BindingKey} in this component's parent. Don't resolve
770 * directly in the owning component in case it depends on multibindings in any of its
771 * descendants.
dpb76e07472015-08-04 15:43:09 -0700772 */
gakf53c3f92016-08-17 09:55:56 -0700773 private boolean isResolvedInParent(BindingKey bindingKey, ContributionBinding binding) {
dpb6bd55de2015-09-28 07:58:09 -0700774 Optional<Resolver> owningResolver = getOwningResolver(binding);
dpb76e07472015-08-04 15:43:09 -0700775 if (owningResolver.isPresent() && !owningResolver.get().equals(this)) {
gakf53c3f92016-08-17 09:55:56 -0700776 parentResolver.get().resolve(bindingKey);
dpb76e07472015-08-04 15:43:09 -0700777 return true;
778 } else {
779 return false;
780 }
781 }
782
dpb778d5222015-12-22 08:33:07 -0800783 private Optional<Resolver> getOwningResolver(ContributionBinding binding) {
dpb4cd56e82016-03-30 10:12:27 -0700784 if (binding.scope().isPresent() && binding.scope().get().equals(reusableScope(elements))) {
785 for (Resolver requestResolver : getResolverLineage().reverse()) {
786 // If a @Reusable binding was resolved in an ancestor, use that component.
dpba69ead52016-07-11 10:05:20 -0700787 if (requestResolver.resolvedBindings.containsKey(
788 BindingKey.contribution(binding.key()))) {
dpb4cd56e82016-03-30 10:12:27 -0700789 return Optional.of(requestResolver);
790 }
791 }
792 // If a @Reusable binding was not resolved in any ancestor, resolve it here.
dpbffd98f62016-12-20 10:05:16 -0800793 return Optional.empty();
dpb4cd56e82016-03-30 10:12:27 -0700794 }
795
gak3a5e81e2015-08-25 16:22:26 -0700796 for (Resolver requestResolver : getResolverLineage().reverse()) {
ronshapirofbb68402016-08-31 06:44:45 -0700797 if (requestResolver.explicitBindingsSet.contains(binding)
798 || requestResolver.subcomponentDeclarations.containsKey(binding.key())) {
matvore36fc8bf2015-07-16 09:17:49 -0700799 return Optional.of(requestResolver);
gakbce64752015-05-08 12:25:38 -0700800 }
801 }
dpbf0255312015-07-27 15:43:19 -0700802
gakbce64752015-05-08 12:25:38 -0700803 // look for scope separately. we do this for the case where @Singleton can appear twice
804 // in the † compatibility mode
beder3bdf32d2016-02-16 11:37:07 -0800805 Optional<Scope> bindingScope = binding.scope();
dpbf0255312015-07-27 15:43:19 -0700806 if (bindingScope.isPresent()) {
gak3a5e81e2015-08-25 16:22:26 -0700807 for (Resolver requestResolver : getResolverLineage().reverse()) {
beder3bdf32d2016-02-16 11:37:07 -0800808 if (requestResolver.componentDescriptor.scopes().contains(bindingScope.get())) {
dpbf0255312015-07-27 15:43:19 -0700809 return Optional.of(requestResolver);
810 }
gak959f5cd2015-01-29 12:42:09 -0800811 }
812 }
dpbffd98f62016-12-20 10:05:16 -0800813 return Optional.empty();
gak959f5cd2015-01-29 12:42:09 -0800814 }
815
gakbce64752015-05-08 12:25:38 -0700816 /** Returns the resolver lineage from parent to child. */
gak3a5e81e2015-08-25 16:22:26 -0700817 private ImmutableList<Resolver> getResolverLineage() {
818 List<Resolver> resolverList = Lists.newArrayList();
819 for (Optional<Resolver> currentResolver = Optional.of(this);
gak959f5cd2015-01-29 12:42:09 -0800820 currentResolver.isPresent();
821 currentResolver = currentResolver.get().parentResolver) {
822 resolverList.add(currentResolver.get());
823 }
824 return ImmutableList.copyOf(Lists.reverse(resolverList));
825 }
826
dpba2620422015-08-15 10:06:54 -0700827 /**
dpb08350312016-09-27 10:12:41 -0700828 * Returns the explicit {@link ContributionBinding}s that match the {@code key} from this and
829 * all ancestor resolvers.
dpba2620422015-08-15 10:06:54 -0700830 */
dpb08350312016-09-27 10:12:41 -0700831 private ImmutableSet<ContributionBinding> getExplicitBindings(Key key) {
ronshapirod6973272016-07-20 15:41:23 -0700832 ImmutableSet.Builder<ContributionBinding> bindings = ImmutableSet.builder();
gak3a5e81e2015-08-25 16:22:26 -0700833 for (Resolver resolver : getResolverLineage()) {
dpb08350312016-09-27 10:12:41 -0700834 bindings.addAll(resolver.getLocalExplicitBindings(key));
gak959f5cd2015-01-29 12:42:09 -0800835 }
ronshapirod6973272016-07-20 15:41:23 -0700836 return bindings.build();
gak959f5cd2015-01-29 12:42:09 -0800837 }
838
dpb51bf8b42015-12-18 09:59:56 -0800839 /**
dpb08350312016-09-27 10:12:41 -0700840 * Returns the explicit {@link ContributionBinding}s that match the {@code key} from this
841 * resolver.
dpbd8d950a2016-08-30 09:24:37 -0700842 */
dpb08350312016-09-27 10:12:41 -0700843 private ImmutableSet<ContributionBinding> getLocalExplicitBindings(Key key) {
dpbd8d950a2016-08-30 09:24:37 -0700844 return new ImmutableSet.Builder<ContributionBinding>()
dpb08350312016-09-27 10:12:41 -0700845 .addAll(explicitBindings.get(key))
dpbd8d950a2016-08-30 09:24:37 -0700846 .addAll(
847 createDelegateBindings(
dpb08350312016-09-27 10:12:41 -0700848 delegateDeclarations.get(keyFactory.convertToDelegateKey(key))))
dpbd8d950a2016-08-30 09:24:37 -0700849 .build();
850 }
851
852 /**
dpb90263a52016-07-13 07:52:41 -0700853 * Returns the explicit multibinding contributions that contribute to the map or set requested
dpb08350312016-09-27 10:12:41 -0700854 * by {@code key} from this and all ancestor resolvers.
dpbdb240722016-01-25 14:06:41 -0800855 */
dpb08350312016-09-27 10:12:41 -0700856 private ImmutableSet<ContributionBinding> getExplicitMultibindings(Key key) {
ronshapirod6973272016-07-20 15:41:23 -0700857 ImmutableSet.Builder<ContributionBinding> multibindings = ImmutableSet.builder();
dpbdb240722016-01-25 14:06:41 -0800858 for (Resolver resolver : getResolverLineage()) {
dpb08350312016-09-27 10:12:41 -0700859 multibindings.addAll(resolver.getLocalExplicitMultibindings(key));
860 }
861 return multibindings.build();
862 }
863
864 /**
865 * Returns the explicit multibinding contributions that contribute to the map or set requested
866 * by {@code key} from this resolver.
867 */
868 private ImmutableSet<ContributionBinding> getLocalExplicitMultibindings(Key key) {
869 ImmutableSet.Builder<ContributionBinding> multibindings = ImmutableSet.builder();
870 multibindings.addAll(explicitMultibindings.get(key));
871 if (!MapType.isMap(key) || MapType.from(key).valuesAreFrameworkType()) {
872 // There are no @Binds @IntoMap delegate declarations for Map<K, V> requests. All
873 // @IntoMap requests must be for Map<K, Framework<V>>.
874 multibindings.addAll(
875 createDelegateBindings(
876 delegateMultibindingDeclarations.get(keyFactory.convertToDelegateKey(key))));
dpbdb240722016-01-25 14:06:41 -0800877 }
ronshapirod6973272016-07-20 15:41:23 -0700878 return multibindings.build();
dpbdb240722016-01-25 14:06:41 -0800879 }
880
dpbdb240722016-01-25 14:06:41 -0800881 /**
dpb51bf8b42015-12-18 09:59:56 -0800882 * Returns the {@link MultibindingDeclaration}s that match the {@code key} from this and all
883 * ancestor resolvers.
884 */
885 private ImmutableSet<MultibindingDeclaration> getMultibindingDeclarations(Key key) {
886 ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations =
887 ImmutableSet.builder();
888 for (Resolver resolver : getResolverLineage()) {
889 multibindingDeclarations.addAll(resolver.multibindingDeclarations.get(key));
890 }
891 return multibindingDeclarations.build();
892 }
893
dpbd8d950a2016-08-30 09:24:37 -0700894 /**
ronshapirofbb68402016-08-31 06:44:45 -0700895 * Returns the {@link SubcomponentDeclaration}s that match the {@code key} from this and all
896 * ancestor resolvers.
897 */
898 private ImmutableSet<SubcomponentDeclaration> getSubcomponentDeclarations(Key key) {
899 ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations =
900 ImmutableSet.builder();
901 for (Resolver resolver : getResolverLineage()) {
902 subcomponentDeclarations.addAll(resolver.subcomponentDeclarations.get(key));
903 }
904 return subcomponentDeclarations.build();
905 }
906 /**
dpbd8d950a2016-08-30 09:24:37 -0700907 * Returns the {@link OptionalBindingDeclaration}s that match the {@code key} from this and
908 * all ancestor resolvers.
909 */
910 private ImmutableSet<OptionalBindingDeclaration> getOptionalBindingDeclarations(Key key) {
911 Optional<Key> unwrapped = keyFactory.unwrapOptional(key);
912 if (!unwrapped.isPresent()) {
913 return ImmutableSet.of();
914 }
915 ImmutableSet.Builder<OptionalBindingDeclaration> declarations = ImmutableSet.builder();
916 for (Resolver resolver : getResolverLineage()) {
917 declarations.addAll(resolver.optionalBindingDeclarations.get(unwrapped.get()));
918 }
919 return declarations.build();
920 }
921
gak29aeaca2015-02-05 16:48:47 -0800922 private Optional<ResolvedBindings> getPreviouslyResolvedBindings(
923 final BindingKey bindingKey) {
dpbffd98f62016-12-20 10:05:16 -0800924 Optional<ResolvedBindings> result = Optional.ofNullable(resolvedBindings.get(bindingKey));
gak29aeaca2015-02-05 16:48:47 -0800925 if (result.isPresent()) {
926 return result;
927 } else if (parentResolver.isPresent()) {
928 return parentResolver.get().getPreviouslyResolvedBindings(bindingKey);
929 } else {
dpbffd98f62016-12-20 10:05:16 -0800930 return Optional.empty();
gak29aeaca2015-02-05 16:48:47 -0800931 }
932 }
933
gakf53c3f92016-08-17 09:55:56 -0700934 void resolve(BindingKey bindingKey) {
dpbf0255312015-07-27 15:43:19 -0700935 // If we find a cycle, stop resolving. The original request will add it with all of the
936 // other resolved deps.
937 if (cycleStack.contains(bindingKey)) {
bederfaaa9692015-01-09 17:34:53 -0800938 return;
gak16e0cd42014-09-18 09:24:04 -0700939 }
940
dpbf0255312015-07-27 15:43:19 -0700941 // If the binding was previously resolved in this (sub)component, don't resolve it again.
942 if (resolvedBindings.containsKey(bindingKey)) {
943 return;
944 }
945
dpb938b7522016-02-23 07:55:08 -0800946 /* If the binding was previously resolved in a supercomponent, then we may be able to avoid
947 * resolving it here and just depend on the supercomponent resolution.
948 *
dpb08350312016-09-27 10:12:41 -0700949 * 1. If it depends transitively on multibinding contributions or optional bindings with
950 * bindings from this subcomponent, then we have to resolve it in this subcomponent so
951 * that it sees the local bindings.
dpb938b7522016-02-23 07:55:08 -0800952 *
953 * 2. If there are any explicit bindings in this component, they may conflict with those in
954 * the supercomponent, so resolve them here so that conflicts can be caught.
955 */
dpb2df89f92016-05-24 06:53:48 -0700956 if (getPreviouslyResolvedBindings(bindingKey).isPresent()) {
dpb407b7bd2016-02-29 09:05:39 -0800957 /* Resolve in the parent in case there are multibinding contributions or conflicts in some
958 * component between this one and the previously-resolved one. */
gakf53c3f92016-08-17 09:55:56 -0700959 parentResolver.get().resolve(bindingKey);
dpb08350312016-09-27 10:12:41 -0700960 if (!new LocalDependencyChecker().dependsOnLocalBindings(bindingKey)
961 && getLocalExplicitBindings(bindingKey.key()).isEmpty()) {
dpb2df89f92016-05-24 06:53:48 -0700962 /* Cache the inherited parent component's bindings in case resolving at the parent found
963 * bindings in some component between this one and the previously-resolved one. */
964 ResolvedBindings inheritedBindings =
965 getPreviouslyResolvedBindings(bindingKey).get().asInheritedIn(componentDescriptor);
966 resolvedBindings.put(bindingKey, inheritedBindings);
967 return;
968 }
gak16e0cd42014-09-18 09:24:04 -0700969 }
970
beder3e950f32014-12-19 17:48:47 -0800971 cycleStack.push(bindingKey);
gak16e0cd42014-09-18 09:24:04 -0700972 try {
gakf53c3f92016-08-17 09:55:56 -0700973 ResolvedBindings bindings = lookUpBindings(bindingKey);
gakd296d892015-03-10 23:34:03 -0700974 for (Binding binding : bindings.ownedBindings()) {
gak75b9b722016-09-29 15:48:40 -0700975 for (DependencyRequest dependency : binding.dependencies()) {
gakf53c3f92016-08-17 09:55:56 -0700976 resolve(dependency.bindingKey());
gak959f5cd2015-01-29 12:42:09 -0800977 }
bederfaaa9692015-01-09 17:34:53 -0800978 }
gakd296d892015-03-10 23:34:03 -0700979 resolvedBindings.put(bindingKey, bindings);
gak16e0cd42014-09-18 09:24:04 -0700980 } finally {
981 cycleStack.pop();
982 }
983 }
gak78ac3682015-03-30 15:48:00 -0700984
985 ImmutableMap<BindingKey, ResolvedBindings> getResolvedBindings() {
986 ImmutableMap.Builder<BindingKey, ResolvedBindings> resolvedBindingsBuilder =
987 ImmutableMap.builder();
988 resolvedBindingsBuilder.putAll(resolvedBindings);
989 if (parentResolver.isPresent()) {
dpbf0255312015-07-27 15:43:19 -0700990 Collection<ResolvedBindings> bindingsResolvedInParent =
991 Maps.difference(parentResolver.get().getResolvedBindings(), resolvedBindings)
992 .entriesOnlyOnLeft()
993 .values();
994 for (ResolvedBindings resolvedInParent : bindingsResolvedInParent) {
995 resolvedBindingsBuilder.put(
gak924b5f42015-08-25 13:27:02 -0700996 resolvedInParent.bindingKey(),
997 resolvedInParent.asInheritedIn(componentDescriptor));
gak78ac3682015-03-30 15:48:00 -0700998 }
999 }
1000 return resolvedBindingsBuilder.build();
1001 }
gak3a5e81e2015-08-25 16:22:26 -07001002
1003 ImmutableSet<ModuleDescriptor> getInheritedModules() {
1004 return parentResolver.isPresent()
1005 ? Sets.union(
1006 parentResolver.get().getInheritedModules(),
1007 parentResolver.get().componentDescriptor.transitiveModules())
1008 .immutableCopy()
1009 : ImmutableSet.<ModuleDescriptor>of();
1010 }
1011
1012 ImmutableSet<ModuleDescriptor> getOwnedModules() {
1013 return Sets.difference(componentDescriptor.transitiveModules(), getInheritedModules())
1014 .immutableCopy();
1015 }
dpb778d5222015-12-22 08:33:07 -08001016
dpb08350312016-09-27 10:12:41 -07001017 private final class LocalDependencyChecker {
dpb42e4a482016-01-21 12:23:40 -08001018 private final Set<Object> cycleChecker = new HashSet<>();
dpb778d5222015-12-22 08:33:07 -08001019
1020 /**
dpb08350312016-09-27 10:12:41 -07001021 * Returns {@code true} if any of the bindings resolved for {@code bindingKey} are
1022 * multibindings with contributions declared within this component's modules or optional
1023 * bindings with present values declared within this component's modules, or if any of its
1024 * unscoped dependencies depend on such bindings.
dpb778d5222015-12-22 08:33:07 -08001025 *
dpb08350312016-09-27 10:12:41 -07001026 * <p>We don't care about scoped dependencies because they will never depend on bindings
1027 * from subcomponents.
dpb778d5222015-12-22 08:33:07 -08001028 *
1029 * @throws IllegalArgumentException if {@link #getPreviouslyResolvedBindings(BindingKey)} is
dpbffd98f62016-12-20 10:05:16 -08001030 * empty
dpb778d5222015-12-22 08:33:07 -08001031 */
dpb08350312016-09-27 10:12:41 -07001032 boolean dependsOnLocalBindings(BindingKey bindingKey) {
dpb778d5222015-12-22 08:33:07 -08001033 // Don't recur infinitely if there are valid cycles in the dependency graph.
Christian Gruber40260f12016-06-14 08:22:11 -07001034 // http://b/23032377
dpb778d5222015-12-22 08:33:07 -08001035 if (!cycleChecker.add(bindingKey)) {
1036 return false;
1037 }
ronshapiroac6dd2b2017-08-04 12:48:07 -07001038 return reentrantComputeIfAbsent(
1039 bindingKeyDependsOnLocalBindingsCache,
1040 bindingKey,
1041 this::dependsOnLocalBindingsUncached);
dpb9563a022017-06-05 08:39:15 -07001042 }
gak66241102016-09-13 12:23:00 -07001043
dpb9563a022017-06-05 08:39:15 -07001044 private boolean dependsOnLocalBindingsUncached(BindingKey bindingKey) {
1045 checkArgument(
1046 getPreviouslyResolvedBindings(bindingKey).isPresent(),
1047 "no previously resolved bindings in %s for %s",
1048 Resolver.this,
1049 bindingKey);
1050 ResolvedBindings previouslyResolvedBindings =
1051 getPreviouslyResolvedBindings(bindingKey).get();
1052 if (hasLocalMultibindingContributions(previouslyResolvedBindings)
1053 || hasLocallyPresentOptionalBinding(previouslyResolvedBindings)) {
1054 return true;
dpb778d5222015-12-22 08:33:07 -08001055 }
dpb9563a022017-06-05 08:39:15 -07001056
1057 for (Binding binding : previouslyResolvedBindings.bindings()) {
1058 if (dependsOnLocalBindings(binding)) {
1059 return true;
1060 }
1061 }
1062 return false;
dpb778d5222015-12-22 08:33:07 -08001063 }
1064
1065 /**
dpb4cd56e82016-03-30 10:12:27 -07001066 * Returns {@code true} if {@code binding} is unscoped (or has {@link Reusable @Reusable}
1067 * scope) and depends on multibindings with contributions declared within this component's
1068 * modules, or if any of its unscoped or {@link Reusable @Reusable} scoped dependencies
1069 * depend on such local multibindings.
dpb778d5222015-12-22 08:33:07 -08001070 *
dpb4cd56e82016-03-30 10:12:27 -07001071 * <p>We don't care about non-reusable scoped dependencies because they will never depend on
dpb778d5222015-12-22 08:33:07 -08001072 * multibindings with contributions from subcomponents.
1073 */
dpb08350312016-09-27 10:12:41 -07001074 boolean dependsOnLocalBindings(Binding binding) {
dpb42e4a482016-01-21 12:23:40 -08001075 if (!cycleChecker.add(binding)) {
1076 return false;
1077 }
ronshapiroac6dd2b2017-08-04 12:48:07 -07001078 return reentrantComputeIfAbsent(
1079 bindingDependsOnLocalBindingsCache, binding, this::dependsOnLocalBindingsUncached);
dpb9563a022017-06-05 08:39:15 -07001080 }
1081
1082 private boolean dependsOnLocalBindingsUncached(Binding binding) {
1083 if ((!binding.scope().isPresent()
1084 || binding.scope().get().equals(reusableScope(elements)))
1085 // TODO(beder): Figure out what happens with production subcomponents.
1086 && !binding.bindingType().equals(BindingType.PRODUCTION)) {
1087 for (DependencyRequest dependency : binding.dependencies()) {
1088 if (dependsOnLocalBindings(dependency.bindingKey())) {
1089 return true;
1090 }
1091 }
dpb778d5222015-12-22 08:33:07 -08001092 }
dpb9563a022017-06-05 08:39:15 -07001093 return false;
dpb778d5222015-12-22 08:33:07 -08001094 }
1095
dpb08350312016-09-27 10:12:41 -07001096 /**
1097 * Returns {@code true} if {@code resolvedBindings} contains a synthetic multibinding with
1098 * at least one contribution declared within this component's modules.
1099 */
1100 private boolean hasLocalMultibindingContributions(ResolvedBindings resolvedBindings) {
1101 return resolvedBindings
1102 .contributionBindings()
1103 .stream()
1104 .map(ContributionBinding::bindingKind)
1105 .anyMatch(SYNTHETIC_MULTIBOUND_KINDS::contains)
1106 && !getLocalExplicitMultibindings(resolvedBindings.key()).isEmpty();
1107 }
1108
1109 /**
1110 * Returns {@code true} if {@code resolvedBindings} contains a synthetic optional binding
1111 * for which there is an explicit present binding in this component.
1112 */
1113 private boolean hasLocallyPresentOptionalBinding(ResolvedBindings resolvedBindings) {
1114 return resolvedBindings
1115 .contributionBindings()
1116 .stream()
1117 .map(ContributionBinding::bindingKind)
1118 .anyMatch(isEqual(SYNTHETIC_OPTIONAL_BINDING))
1119 && !getLocalExplicitBindings(keyFactory.unwrapOptional(resolvedBindings.key()).get())
1120 .isEmpty();
dpb778d5222015-12-22 08:33:07 -08001121 }
1122 }
gak16e0cd42014-09-18 09:24:04 -07001123 }
ronshapiro846fd942016-06-01 11:50:01 -07001124
1125 /**
dpb90263a52016-07-13 07:52:41 -07001126 * A multimap of those {@code declarations} that are multibinding contribution declarations,
1127 * indexed by the key of the set or map to which they contribute.
ronshapiro846fd942016-06-01 11:50:01 -07001128 */
dpb7edcd4d2016-06-21 07:52:39 -07001129 static <T extends HasKey>
dpb90263a52016-07-13 07:52:41 -07001130 ImmutableSetMultimap<Key, T> multibindingContributionsByMultibindingKey(
1131 Iterable<T> declarations) {
ronshapiro846fd942016-06-01 11:50:01 -07001132 ImmutableSetMultimap.Builder<Key, T> builder = ImmutableSetMultimap.builder();
dpb90263a52016-07-13 07:52:41 -07001133 for (T declaration : declarations) {
1134 if (declaration.key().multibindingContributionIdentifier().isPresent()) {
1135 builder.put(declaration.key().withoutMultibindingContributionIdentifier(), declaration);
ronshapiro846fd942016-06-01 11:50:01 -07001136 }
1137 }
1138 return builder.build();
1139 }
gak16e0cd42014-09-18 09:24:04 -07001140 }
1141}