• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Dagger Authors.
3  *
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  */
16 
17 package dagger.internal.codegen;
18 
19 import static com.google.auto.common.MoreTypes.isType;
20 import static com.google.auto.common.MoreTypes.isTypeOf;
21 import static com.google.common.base.Preconditions.checkArgument;
22 import static com.google.common.base.Preconditions.checkNotNull;
23 import static com.google.common.collect.Iterables.isEmpty;
24 import static dagger.internal.codegen.ComponentDescriptor.isComponentContributionMethod;
25 import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
26 import static dagger.internal.codegen.RequestKinds.getRequestKind;
27 import static dagger.internal.codegen.SourceFiles.generatedMonitoringModuleName;
28 import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
29 import static dagger.model.BindingKind.DELEGATE;
30 import static dagger.model.BindingKind.INJECTION;
31 import static dagger.model.BindingKind.OPTIONAL;
32 import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
33 import static dagger.model.RequestKind.MEMBERS_INJECTION;
34 import static java.util.function.Predicate.isEqual;
35 import static javax.lang.model.util.ElementFilter.methodsIn;
36 
37 import com.google.auto.common.MoreTypes;
38 import com.google.common.collect.ImmutableList;
39 import com.google.common.collect.ImmutableMap;
40 import com.google.common.collect.ImmutableSet;
41 import com.google.common.collect.ImmutableSetMultimap;
42 import com.google.common.collect.Iterables;
43 import com.google.common.collect.Multimaps;
44 import com.google.common.collect.Sets;
45 import dagger.MembersInjector;
46 import dagger.Reusable;
47 import dagger.internal.codegen.langmodel.DaggerElements;
48 import dagger.model.DependencyRequest;
49 import dagger.model.Key;
50 import dagger.model.Scope;
51 import dagger.producers.Produced;
52 import dagger.producers.Producer;
53 import dagger.producers.internal.ProductionExecutorModule;
54 import java.util.ArrayDeque;
55 import java.util.Collection;
56 import java.util.Deque;
57 import java.util.HashMap;
58 import java.util.HashSet;
59 import java.util.LinkedHashMap;
60 import java.util.LinkedHashSet;
61 import java.util.List;
62 import java.util.Map;
63 import java.util.Optional;
64 import java.util.Queue;
65 import java.util.Set;
66 import java.util.function.Function;
67 import javax.inject.Inject;
68 import javax.inject.Provider;
69 import javax.inject.Singleton;
70 import javax.lang.model.element.ExecutableElement;
71 import javax.lang.model.element.TypeElement;
72 
73 /** A factory for {@link BindingGraph} objects. */
74 @Singleton
75 final class BindingGraphFactory implements ClearableCache {
76   private final DaggerElements elements;
77   private final InjectBindingRegistry injectBindingRegistry;
78   private final KeyFactory keyFactory;
79   private final BindingFactory bindingFactory;
80   private final ModuleDescriptor.Factory moduleDescriptorFactory;
81   private final Map<Key, ImmutableSet<Key>> keysMatchingRequestCache = new HashMap<>();
82 
83   @Inject
BindingGraphFactory( DaggerElements elements, InjectBindingRegistry injectBindingRegistry, KeyFactory keyFactory, BindingFactory bindingFactory, ModuleDescriptor.Factory moduleDescriptorFactory)84   BindingGraphFactory(
85       DaggerElements elements,
86       InjectBindingRegistry injectBindingRegistry,
87       KeyFactory keyFactory,
88       BindingFactory bindingFactory,
89       ModuleDescriptor.Factory moduleDescriptorFactory) {
90     this.elements = elements;
91     this.injectBindingRegistry = injectBindingRegistry;
92     this.keyFactory = keyFactory;
93     this.bindingFactory = bindingFactory;
94     this.moduleDescriptorFactory = moduleDescriptorFactory;
95   }
96 
97   /**
98    * Creates a binding graph for a component.
99    *
100    * @param createFullBindingGraph if {@code true}, the binding graph will include all bindings;
101    *     otherwise it will include only bindings reachable from at least one entry point
102    */
create(ComponentDescriptor componentDescriptor, boolean createFullBindingGraph)103   BindingGraph create(ComponentDescriptor componentDescriptor, boolean createFullBindingGraph) {
104     return create(Optional.empty(), componentDescriptor, createFullBindingGraph);
105   }
106 
create( Optional<Resolver> parentResolver, ComponentDescriptor componentDescriptor, boolean createFullBindingGraph)107   private BindingGraph create(
108       Optional<Resolver> parentResolver,
109       ComponentDescriptor componentDescriptor,
110       boolean createFullBindingGraph) {
111     ImmutableSet.Builder<ContributionBinding> explicitBindingsBuilder = ImmutableSet.builder();
112     ImmutableSet.Builder<DelegateDeclaration> delegatesBuilder = ImmutableSet.builder();
113     ImmutableSet.Builder<OptionalBindingDeclaration> optionalsBuilder = ImmutableSet.builder();
114 
115     if (componentDescriptor.isRealComponent()) {
116       // binding for the component itself
117       explicitBindingsBuilder.add(
118           bindingFactory.componentBinding(componentDescriptor.typeElement()));
119     }
120 
121     // Collect Component dependencies.
122     for (ComponentRequirement dependency : componentDescriptor.dependencies()) {
123       explicitBindingsBuilder.add(bindingFactory.componentDependencyBinding(dependency));
124       List<ExecutableElement> dependencyMethods =
125           methodsIn(elements.getAllMembers(dependency.typeElement()));
126       for (ExecutableElement method : dependencyMethods) {
127         // MembersInjection methods aren't "provided" explicitly, so ignore them.
128         if (isComponentContributionMethod(elements, method)) {
129           explicitBindingsBuilder.add(
130               bindingFactory.componentDependencyMethodBinding(componentDescriptor, method));
131         }
132       }
133     }
134 
135     // Collect bindings on the creator.
136     componentDescriptor
137         .creatorDescriptor()
138         .ifPresent(
139             creatorDescriptor ->
140                 creatorDescriptor.boundInstanceRequirements().stream()
141                     .map(
142                         requirement ->
143                             bindingFactory.boundInstanceBinding(
144                                 requirement, creatorDescriptor.elementForRequirement(requirement)))
145                     .forEach(explicitBindingsBuilder::add));
146 
147     componentDescriptor
148         .childComponentsDeclaredByBuilderEntryPoints()
149         .forEach(
150             (builderEntryPoint, childComponent) -> {
151               if (!componentDescriptor
152                   .childComponentsDeclaredByModules()
153                   .contains(childComponent)) {
154                 explicitBindingsBuilder.add(
155                     bindingFactory.subcomponentCreatorBinding(
156                         builderEntryPoint.methodElement(), componentDescriptor.typeElement()));
157               }
158             });
159 
160     ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations = ImmutableSet.builder();
161     ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations = ImmutableSet.builder();
162 
163     // Collect transitive module bindings and multibinding declarations.
164     for (ModuleDescriptor moduleDescriptor : modules(componentDescriptor, parentResolver)) {
165       explicitBindingsBuilder.addAll(moduleDescriptor.bindings());
166       multibindingDeclarations.addAll(moduleDescriptor.multibindingDeclarations());
167       subcomponentDeclarations.addAll(moduleDescriptor.subcomponentDeclarations());
168       delegatesBuilder.addAll(moduleDescriptor.delegateDeclarations());
169       optionalsBuilder.addAll(moduleDescriptor.optionalDeclarations());
170     }
171 
172     final Resolver requestResolver =
173         new Resolver(
174             parentResolver,
175             componentDescriptor,
176             indexBindingDeclarationsByKey(explicitBindingsBuilder.build()),
177             indexBindingDeclarationsByKey(multibindingDeclarations.build()),
178             indexBindingDeclarationsByKey(subcomponentDeclarations.build()),
179             indexBindingDeclarationsByKey(delegatesBuilder.build()),
180             indexBindingDeclarationsByKey(optionalsBuilder.build()));
181 
182     componentDescriptor.entryPointMethods().stream()
183         .map(method -> method.dependencyRequest().get())
184         .forEach(
185             entryPoint -> {
186               if (entryPoint.kind().equals(MEMBERS_INJECTION)) {
187                 requestResolver.resolveMembersInjection(entryPoint.key());
188               } else {
189                 requestResolver.resolve(entryPoint.key());
190               }
191             });
192 
193     if (createFullBindingGraph) {
194       // Resolve the keys for all bindings in all modules, stripping any multibinding contribution
195       // identifier so that the multibinding itself is resolved.
196       modules(componentDescriptor, parentResolver).stream()
197           .flatMap(module -> module.allBindingKeys().stream())
198           .map(key -> key.toBuilder().multibindingContributionIdentifier(Optional.empty()).build())
199           .forEach(requestResolver::resolve);
200     }
201 
202     // Resolve all bindings for subcomponents, creating subgraphs for all subcomponents that have
203     // been detected during binding resolution. If a binding for a subcomponent is never resolved,
204     // no BindingGraph will be created for it and no implementation will be generated. This is
205     // done in a queue since resolving one subcomponent might resolve a key for a subcomponent
206     // from a parent graph. This is done until no more new subcomponents are resolved.
207     Set<ComponentDescriptor> resolvedSubcomponents = new HashSet<>();
208     ImmutableList.Builder<BindingGraph> subgraphs = ImmutableList.builder();
209     for (ComponentDescriptor subcomponent :
210         Iterables.consumingIterable(requestResolver.subcomponentsToResolve)) {
211       if (resolvedSubcomponents.add(subcomponent)) {
212         subgraphs.add(create(Optional.of(requestResolver), subcomponent, createFullBindingGraph));
213       }
214     }
215 
216     return BindingGraph.create(
217         componentDescriptor,
218         requestResolver.getResolvedContributionBindings(),
219         requestResolver.getResolvedMembersInjectionBindings(),
220         subgraphs.build(),
221         requestResolver.getOwnedModules(),
222         requestResolver.getFactoryMethod(),
223         createFullBindingGraph);
224   }
225 
226   /**
227    * Returns all the modules that should be installed in the component. For production components
228    * and production subcomponents that have a parent that is not a production component or
229    * subcomponent, also includes the production monitoring module for the component and the
230    * production executor module.
231    */
modules( ComponentDescriptor componentDescriptor, Optional<Resolver> parentResolver)232   private ImmutableSet<ModuleDescriptor> modules(
233       ComponentDescriptor componentDescriptor, Optional<Resolver> parentResolver) {
234     return shouldIncludeImplicitProductionModules(componentDescriptor, parentResolver)
235         ? new ImmutableSet.Builder<ModuleDescriptor>()
236             .addAll(componentDescriptor.modules())
237             .add(descriptorForMonitoringModule(componentDescriptor.typeElement()))
238             .add(descriptorForProductionExecutorModule())
239             .build()
240         : componentDescriptor.modules();
241   }
242 
shouldIncludeImplicitProductionModules( ComponentDescriptor component, Optional<Resolver> parentResolver)243   private boolean shouldIncludeImplicitProductionModules(
244       ComponentDescriptor component, Optional<Resolver> parentResolver) {
245     return component.isProduction()
246         && ((!component.isSubcomponent() && component.isRealComponent())
247             || (parentResolver.isPresent()
248                 && !parentResolver.get().componentDescriptor.isProduction()));
249   }
250 
251   /**
252    * Returns a descriptor for a generated module that handles monitoring for production components.
253    * This module is generated in the {@link MonitoringModuleProcessingStep}.
254    *
255    * @throws TypeNotPresentException if the module has not been generated yet. This will cause the
256    *     processor to retry in a later processing round.
257    */
descriptorForMonitoringModule(TypeElement componentDefinitionType)258   private ModuleDescriptor descriptorForMonitoringModule(TypeElement componentDefinitionType) {
259     return moduleDescriptorFactory.create(
260         elements.checkTypePresent(
261             generatedMonitoringModuleName(componentDefinitionType).toString()));
262   }
263 
264   /** Returns a descriptor {@link ProductionExecutorModule}. */
descriptorForProductionExecutorModule()265   private ModuleDescriptor descriptorForProductionExecutorModule() {
266     return moduleDescriptorFactory.create(elements.getTypeElement(ProductionExecutorModule.class));
267   }
268 
269   /** Indexes {@code bindingDeclarations} by {@link BindingDeclaration#key()}. */
270   private static <T extends BindingDeclaration>
indexBindingDeclarationsByKey(Iterable<T> declarations)271       ImmutableSetMultimap<Key, T> indexBindingDeclarationsByKey(Iterable<T> declarations) {
272     return ImmutableSetMultimap.copyOf(Multimaps.index(declarations, BindingDeclaration::key));
273   }
274 
275   @Override
clearCache()276   public void clearCache() {
277     keysMatchingRequestCache.clear();
278   }
279 
280   private final class Resolver {
281     final Optional<Resolver> parentResolver;
282     final ComponentDescriptor componentDescriptor;
283     final ImmutableSetMultimap<Key, ContributionBinding> explicitBindings;
284     final ImmutableSet<ContributionBinding> explicitBindingsSet;
285     final ImmutableSetMultimap<Key, ContributionBinding> explicitMultibindings;
286     final ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations;
287     final ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations;
288     final ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations;
289     final ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations;
290     final ImmutableSetMultimap<Key, DelegateDeclaration> delegateMultibindingDeclarations;
291     final Map<Key, ResolvedBindings> resolvedContributionBindings = new LinkedHashMap<>();
292     final Map<Key, ResolvedBindings> resolvedMembersInjectionBindings = new LinkedHashMap<>();
293     final Deque<Key> cycleStack = new ArrayDeque<>();
294     final Map<Key, Boolean> keyDependsOnLocalBindingsCache = new HashMap<>();
295     final Map<Binding, Boolean> bindingDependsOnLocalBindingsCache = new HashMap<>();
296     final Queue<ComponentDescriptor> subcomponentsToResolve = new ArrayDeque<>();
297 
Resolver( Optional<Resolver> parentResolver, ComponentDescriptor componentDescriptor, ImmutableSetMultimap<Key, ContributionBinding> explicitBindings, ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations, ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations, ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations, ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations)298     Resolver(
299         Optional<Resolver> parentResolver,
300         ComponentDescriptor componentDescriptor,
301         ImmutableSetMultimap<Key, ContributionBinding> explicitBindings,
302         ImmutableSetMultimap<Key, MultibindingDeclaration> multibindingDeclarations,
303         ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations,
304         ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations,
305         ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations) {
306       this.parentResolver = parentResolver;
307       this.componentDescriptor = checkNotNull(componentDescriptor);
308       this.explicitBindings = checkNotNull(explicitBindings);
309       this.explicitBindingsSet = ImmutableSet.copyOf(explicitBindings.values());
310       this.multibindingDeclarations = checkNotNull(multibindingDeclarations);
311       this.subcomponentDeclarations = checkNotNull(subcomponentDeclarations);
312       this.delegateDeclarations = checkNotNull(delegateDeclarations);
313       this.optionalBindingDeclarations = checkNotNull(optionalBindingDeclarations);
314       this.explicitMultibindings = multibindingContributionsByMultibindingKey(explicitBindingsSet);
315       this.delegateMultibindingDeclarations =
316           multibindingContributionsByMultibindingKey(delegateDeclarations.values());
317       subcomponentsToResolve.addAll(
318           componentDescriptor.childComponentsDeclaredByFactoryMethods().values());
319       subcomponentsToResolve.addAll(
320           componentDescriptor.childComponentsDeclaredByBuilderEntryPoints().values());
321     }
322 
323     /** Returns the optional factory method for this component. */
getFactoryMethod()324     Optional<ExecutableElement> getFactoryMethod() {
325       return parentResolver
326           .flatMap(
327               parent ->
328                   parent.componentDescriptor.getFactoryMethodForChildComponent(componentDescriptor))
329           .map(method -> method.methodElement());
330     }
331 
332     /**
333      * Returns the resolved contribution bindings for the given {@link Key}:
334      *
335      * <ul>
336      *   <li>All explicit bindings for:
337      *       <ul>
338      *         <li>the requested key
339      *         <li>{@code Set<T>} if the requested key's type is {@code Set<Produced<T>>}
340      *         <li>{@code Map<K, Provider<V>>} if the requested key's type is {@code Map<K,
341      *             Producer<V>>}.
342      *       </ul>
343      *   <li>A synthetic binding that depends on {@code Map<K, Producer<V>>} if the requested key's
344      *       type is {@code Map<K, V>} and there are some explicit bindings for {@code Map<K,
345      *       Producer<V>>}.
346      *   <li>A synthetic binding that depends on {@code Map<K, Provider<V>>} if the requested key's
347      *       type is {@code Map<K, V>} and there are some explicit bindings for {@code Map<K,
348      *       Provider<V>>} but no explicit bindings for {@code Map<K, Producer<V>>}.
349      *   <li>An implicit {@link Inject @Inject}-annotated constructor binding if there is one and
350      *       there are no explicit bindings or synthetic bindings.
351      * </ul>
352      */
lookUpBindings(Key requestKey)353     ResolvedBindings lookUpBindings(Key requestKey) {
354       Set<ContributionBinding> bindings = new LinkedHashSet<>();
355       bindings.addAll(getExplicitBindings(requestKey));
356 
357       ImmutableSet<ContributionBinding> multibindingContributions =
358           getAllMatchingBindingDeclarations(requestKey, this::getExplicitMultibindings);
359       ImmutableSet<MultibindingDeclaration> multibindingDeclarations =
360           getAllMatchingBindingDeclarations(requestKey, this::getMultibindingDeclarations);
361 
362       syntheticMultibinding(requestKey, multibindingContributions, multibindingDeclarations)
363           .ifPresent(bindings::add);
364 
365       ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations =
366           getAllMatchingBindingDeclarations(requestKey, this::getOptionalBindingDeclarations);
367       syntheticOptionalBinding(requestKey, optionalBindingDeclarations).ifPresent(bindings::add);
368 
369       ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations =
370           getSubcomponentDeclarations(requestKey);
371       syntheticSubcomponentBuilderBinding(subcomponentDeclarations)
372           .ifPresent(
373               binding -> {
374                 bindings.add(binding);
375                 addSubcomponentToOwningResolver(binding);
376               });
377 
378       if (isType(requestKey.type()) && isTypeOf(MembersInjector.class, requestKey.type())) {
379         injectBindingRegistry
380             .getOrFindMembersInjectorProvisionBinding(requestKey)
381             .ifPresent(bindings::add);
382       }
383 
384       // If there are no bindings, add the implicit @Inject-constructed binding if there is one.
385       if (bindings.isEmpty()) {
386         injectBindingRegistry.getOrFindProvisionBinding(requestKey)
387             .filter(binding -> !isIncorrectlyScopedInPartialGraph(binding))
388             .ifPresent(bindings::add);
389       }
390 
391       return ResolvedBindings.forContributionBindings(
392           requestKey,
393           indexBindingsByOwningComponent(requestKey, ImmutableSet.copyOf(bindings)),
394           multibindingDeclarations,
395           subcomponentDeclarations,
396           optionalBindingDeclarations);
397     }
398 
399     /**
400      * Returns true if this binding graph resolution is for a partial graph and the {@code @Inject}
401      * binding's scope doesn't match any of the components in the current component ancestry. If so,
402      * the binding is not owned by any of the currently known components, and will be owned by a
403      * future ancestor (or, if never owned, will result in an incompatibly scoped binding error at
404      * the root component).
405      */
isIncorrectlyScopedInPartialGraph(ProvisionBinding binding)406     private boolean isIncorrectlyScopedInPartialGraph(ProvisionBinding binding) {
407       checkArgument(binding.kind().equals(INJECTION));
408       Resolver owningResolver = getOwningResolver(binding).orElse(this);
409       ComponentDescriptor owningComponent = owningResolver.componentDescriptor;
410       return rootComponent().isSubcomponent()
411           && binding.scope().isPresent()
412           && !binding.scope().get().isReusable()
413           && !owningComponent.scopes().contains(binding.scope().get());
414     }
415 
rootComponent()416     private ComponentDescriptor rootComponent() {
417       return parentResolver.map(Resolver::rootComponent).orElse(componentDescriptor);
418     }
419 
420     /** Returns the resolved members injection bindings for the given {@link Key}. */
lookUpMembersInjectionBinding(Key requestKey)421     ResolvedBindings lookUpMembersInjectionBinding(Key requestKey) {
422       // no explicit deps for members injection, so just look it up
423       Optional<MembersInjectionBinding> binding =
424           injectBindingRegistry.getOrFindMembersInjectionBinding(requestKey);
425       return binding.isPresent()
426           ? ResolvedBindings.forMembersInjectionBinding(
427               requestKey, componentDescriptor, binding.get())
428           : ResolvedBindings.noBindings(requestKey);
429     }
430 
431     /**
432      * When a binding is resolved for a {@link SubcomponentDeclaration}, adds corresponding {@link
433      * ComponentDescriptor subcomponent} to a queue in the owning component's resolver. The queue
434      * will be used to detect which subcomponents need to be resolved.
435      */
addSubcomponentToOwningResolver(ProvisionBinding subcomponentCreatorBinding)436     private void addSubcomponentToOwningResolver(ProvisionBinding subcomponentCreatorBinding) {
437       checkArgument(subcomponentCreatorBinding.kind().equals(SUBCOMPONENT_CREATOR));
438       Resolver owningResolver = getOwningResolver(subcomponentCreatorBinding).get();
439 
440       TypeElement builderType = MoreTypes.asTypeElement(subcomponentCreatorBinding.key().type());
441       owningResolver.subcomponentsToResolve.add(
442           owningResolver.componentDescriptor.getChildComponentWithBuilderType(builderType));
443     }
444 
445     /**
446      * Profiling has determined that computing the keys matching {@code requestKey} has measurable
447      * performance impact. It is called repeatedly (at least 3 times per key resolved per {@link
448      * BindingGraph}. {@code javac}'s name-checking performance seems suboptimal (converting byte
449      * strings to Strings repeatedly), and the matching keys creations relies on that. This also
450      * ensures that the resulting keys have their hash codes cached on successive calls to this
451      * method.
452      *
453      * <p>This caching may become obsolete if:
454      *
455      * <ul>
456      *   <li>We decide to intern all {@link Key} instances
457      *   <li>We fix javac's name-checking peformance (though we may want to keep this for older
458      *       javac users)
459      * </ul>
460      */
keysMatchingRequest(Key requestKey)461     private ImmutableSet<Key> keysMatchingRequest(Key requestKey) {
462       return keysMatchingRequestCache.computeIfAbsent(
463           requestKey, this::keysMatchingRequestUncached);
464     }
465 
keysMatchingRequestUncached(Key requestKey)466     private ImmutableSet<Key> keysMatchingRequestUncached(Key requestKey) {
467       ImmutableSet.Builder<Key> keys = ImmutableSet.builder();
468       keys.add(requestKey);
469       keyFactory.unwrapSetKey(requestKey, Produced.class).ifPresent(keys::add);
470       keyFactory.rewrapMapKey(requestKey, Producer.class, Provider.class).ifPresent(keys::add);
471       keyFactory.rewrapMapKey(requestKey, Provider.class, Producer.class).ifPresent(keys::add);
472       keys.addAll(keyFactory.implicitFrameworkMapKeys(requestKey));
473       return keys.build();
474     }
475 
476     /**
477      * Returns a synthetic binding that depends on individual multibinding contributions.
478      *
479      * <p>If there are no {@code multibindingContributions} or {@code multibindingDeclarations},
480      * returns {@link Optional#empty()}.
481      *
482      * <p>If there are production {@code multibindingContributions} or the request is for any of the
483      * following types, returns a {@link ProductionBinding}.
484      *
485      * <ul>
486      *   <li>{@code Set<Produced<T>>}
487      *   <li>{@code Map<K, Producer<V>>}
488      *   <li>{@code Map<K, Produced<V>>}
489      * </ul>
490      *
491      * Otherwise, returns a {@link ProvisionBinding}.
492      */
syntheticMultibinding( Key key, Iterable<ContributionBinding> multibindingContributions, Iterable<MultibindingDeclaration> multibindingDeclarations)493     private Optional<ContributionBinding> syntheticMultibinding(
494         Key key,
495         Iterable<ContributionBinding> multibindingContributions,
496         Iterable<MultibindingDeclaration> multibindingDeclarations) {
497       return isEmpty(multibindingContributions) && isEmpty(multibindingDeclarations)
498           ? Optional.empty()
499           : Optional.of(bindingFactory.syntheticMultibinding(key, multibindingContributions));
500     }
501 
syntheticSubcomponentBuilderBinding( ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations)502     private Optional<ProvisionBinding> syntheticSubcomponentBuilderBinding(
503         ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
504       return subcomponentDeclarations.isEmpty()
505           ? Optional.empty()
506           : Optional.of(bindingFactory.subcomponentCreatorBinding(subcomponentDeclarations));
507     }
508 
509     /**
510      * Returns a synthetic binding for {@code @Qualifier Optional<Type>} if there are any {@code
511      * optionalBindingDeclarations}.
512      *
513      * <p>If there are no bindings for the underlying key (the key for dependency requests for
514      * {@code Type}), returns a provision binding that always returns {@link Optional#empty()}.
515      *
516      * <p>If there are any production bindings for the underlying key, returns a production binding.
517      * Otherwise returns a provision binding.
518      */
syntheticOptionalBinding( Key key, ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations)519     private Optional<ContributionBinding> syntheticOptionalBinding(
520         Key key, ImmutableSet<OptionalBindingDeclaration> optionalBindingDeclarations) {
521       return optionalBindingDeclarations.isEmpty()
522           ? Optional.empty()
523           : Optional.of(
524               bindingFactory.syntheticOptionalBinding(
525                   key,
526                   getRequestKind(OptionalType.from(key).valueType()),
527                   lookUpBindings(keyFactory.unwrapOptional(key).get())));
528     }
529 
createDelegateBindings( ImmutableSet<DelegateDeclaration> delegateDeclarations)530     private ImmutableSet<ContributionBinding> createDelegateBindings(
531         ImmutableSet<DelegateDeclaration> delegateDeclarations) {
532       ImmutableSet.Builder<ContributionBinding> builder = ImmutableSet.builder();
533       for (DelegateDeclaration delegateDeclaration : delegateDeclarations) {
534         builder.add(createDelegateBinding(delegateDeclaration));
535       }
536       return builder.build();
537     }
538 
539     /**
540      * Creates one (and only one) delegate binding for a delegate declaration, based on the resolved
541      * bindings of the right-hand-side of a {@link dagger.Binds} method. If there are duplicate
542      * bindings for the dependency key, there should still be only one binding for the delegate key.
543      */
createDelegateBinding(DelegateDeclaration delegateDeclaration)544     private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDeclaration) {
545       Key delegateKey = delegateDeclaration.delegateRequest().key();
546       if (cycleStack.contains(delegateKey)) {
547         return bindingFactory.unresolvedDelegateBinding(delegateDeclaration);
548       }
549 
550       ResolvedBindings resolvedDelegate;
551       try {
552         cycleStack.push(delegateKey);
553         resolvedDelegate = lookUpBindings(delegateKey);
554       } finally {
555         cycleStack.pop();
556       }
557       if (resolvedDelegate.contributionBindings().isEmpty()) {
558         // This is guaranteed to result in a missing binding error, so it doesn't matter if the
559         // binding is a Provision or Production, except if it is a @IntoMap method, in which
560         // case the key will be of type Map<K, Provider<V>>, which will be "upgraded" into a
561         // Map<K, Producer<V>> if it's requested in a ProductionComponent. This may result in a
562         // strange error, that the RHS needs to be provided with an @Inject or @Provides
563         // annotated method, but a user should be able to figure out if a @Produces annotation
564         // is needed.
565         // TODO(gak): revisit how we model missing delegates if/when we clean up how we model
566         // binding declarations
567         return bindingFactory.unresolvedDelegateBinding(delegateDeclaration);
568       }
569       // It doesn't matter which of these is selected, since they will later on produce a
570       // duplicate binding error.
571       ContributionBinding explicitDelegate =
572           resolvedDelegate.contributionBindings().iterator().next();
573       return bindingFactory.delegateBinding(delegateDeclaration, explicitDelegate);
574     }
575 
576     // TODO(dpb,ronshapiro): requestKey appears to be interchangeable with each binding's .key(),
577     // but should it? We're currently conflating the two all over the place and it would be good
578     // to unify, or if it's necessary, clarify why with docs+tests. Specifically, should we also
579     // be checking these for keysMatchingRequest?
indexBindingsByOwningComponent( Key requestKey, Iterable<? extends ContributionBinding> bindings)580     private ImmutableSetMultimap<TypeElement, ContributionBinding> indexBindingsByOwningComponent(
581         Key requestKey, Iterable<? extends ContributionBinding> bindings) {
582       ImmutableSetMultimap.Builder<TypeElement, ContributionBinding> index =
583           ImmutableSetMultimap.builder();
584       for (ContributionBinding binding : bindings) {
585         index.put(getOwningComponent(requestKey, binding), binding);
586       }
587       return index.build();
588     }
589 
590     /**
591      * Returns the component that should contain the framework field for {@code binding}.
592      *
593      * <p>If {@code binding} is either not bound in an ancestor component or depends transitively on
594      * bindings in this component, returns this component.
595      *
596      * <p>Otherwise, resolves {@code request} in this component's parent in order to resolve any
597      * multibinding contributions in the parent, and returns the parent-resolved {@link
598      * ResolvedBindings#owningComponent(ContributionBinding)}.
599      */
getOwningComponent(Key requestKey, ContributionBinding binding)600     private TypeElement getOwningComponent(Key requestKey, ContributionBinding binding) {
601       if (isResolvedInParent(requestKey, binding)
602           && !new LocalDependencyChecker().dependsOnLocalBindings(binding)) {
603         ResolvedBindings parentResolvedBindings =
604             parentResolver.get().resolvedContributionBindings.get(requestKey);
605         return parentResolvedBindings.owningComponent(binding);
606       } else {
607         return componentDescriptor.typeElement();
608       }
609     }
610 
611     /**
612      * Returns {@code true} if {@code binding} is owned by an ancestor. If so, {@linkplain #resolve
613      * resolves} the {@link Key} in this component's parent. Don't resolve directly in the owning
614      * component in case it depends on multibindings in any of its descendants.
615      */
isResolvedInParent(Key requestKey, ContributionBinding binding)616     private boolean isResolvedInParent(Key requestKey, ContributionBinding binding) {
617       Optional<Resolver> owningResolver = getOwningResolver(binding);
618       if (owningResolver.isPresent() && !owningResolver.get().equals(this)) {
619         parentResolver.get().resolve(requestKey);
620         return true;
621       } else {
622         return false;
623       }
624     }
625 
getOwningResolver(ContributionBinding binding)626     private Optional<Resolver> getOwningResolver(ContributionBinding binding) {
627       // TODO(ronshapiro): extract the different pieces of this method into their own methods
628       if ((binding.scope().isPresent() && binding.scope().get().isProductionScope())
629           || binding.bindingType().equals(BindingType.PRODUCTION)) {
630         for (Resolver requestResolver : getResolverLineage()) {
631           // Resolve @Inject @ProductionScope bindings at the highest production component.
632           if (binding.kind().equals(INJECTION)
633               && requestResolver.componentDescriptor.isProduction()) {
634             return Optional.of(requestResolver);
635           }
636 
637           // Resolve explicit @Produces and @ProductionScope bindings at the highest component that
638           // installs the binding.
639           if (requestResolver.containsExplicitBinding(binding)) {
640             return Optional.of(requestResolver);
641           }
642         }
643       }
644 
645       if (binding.scope().isPresent() && binding.scope().get().isReusable()) {
646         for (Resolver requestResolver : getResolverLineage().reverse()) {
647           // If a @Reusable binding was resolved in an ancestor, use that component.
648           ResolvedBindings resolvedBindings =
649               requestResolver.resolvedContributionBindings.get(binding.key());
650           if (resolvedBindings != null
651               && resolvedBindings.contributionBindings().contains(binding)) {
652             return Optional.of(requestResolver);
653           }
654         }
655         // If a @Reusable binding was not resolved in any ancestor, resolve it here.
656         return Optional.empty();
657       }
658 
659       for (Resolver requestResolver : getResolverLineage().reverse()) {
660         if (requestResolver.containsExplicitBinding(binding)) {
661           return Optional.of(requestResolver);
662         }
663       }
664 
665       // look for scope separately.  we do this for the case where @Singleton can appear twice
666       // in the † compatibility mode
667       Optional<Scope> bindingScope = binding.scope();
668       if (bindingScope.isPresent()) {
669         for (Resolver requestResolver : getResolverLineage().reverse()) {
670           if (requestResolver.componentDescriptor.scopes().contains(bindingScope.get())) {
671             return Optional.of(requestResolver);
672           }
673         }
674       }
675       return Optional.empty();
676     }
677 
containsExplicitBinding(ContributionBinding binding)678     private boolean containsExplicitBinding(ContributionBinding binding) {
679       return explicitBindingsSet.contains(binding)
680           || resolverContainsDelegateDeclarationForBinding(binding)
681           || subcomponentDeclarations.containsKey(binding.key());
682     }
683 
684     /** Returns true if {@code binding} was installed in a module in this resolver's component. */
resolverContainsDelegateDeclarationForBinding(ContributionBinding binding)685     private boolean resolverContainsDelegateDeclarationForBinding(ContributionBinding binding) {
686       return binding.kind().equals(DELEGATE)
687           && delegateDeclarations.get(binding.key()).stream()
688               .anyMatch(
689                   declaration ->
690                       declaration.contributingModule().equals(binding.contributingModule())
691                           && declaration.bindingElement().equals(binding.bindingElement()));
692     }
693 
694     /** Returns the resolver lineage from parent to child. */
getResolverLineage()695     private ImmutableList<Resolver> getResolverLineage() {
696       ImmutableList.Builder<Resolver> resolverList = ImmutableList.builder();
697       for (Optional<Resolver> currentResolver = Optional.of(this);
698           currentResolver.isPresent();
699           currentResolver = currentResolver.get().parentResolver) {
700         resolverList.add(currentResolver.get());
701       }
702       return resolverList.build().reverse();
703     }
704 
705     /**
706      * For all {@linkplain #keysMatchingRequest(Key) keys matching {@code requestKey}}, applies
707      * {@code getDeclarationsPerKey} and collects the values into an {@link ImmutableSet}.
708      */
getAllMatchingBindingDeclarations( Key requestKey, Function<Key, Collection<T>> getDeclarationsPerKey)709     private <T extends BindingDeclaration> ImmutableSet<T> getAllMatchingBindingDeclarations(
710         Key requestKey, Function<Key, Collection<T>> getDeclarationsPerKey) {
711       return keysMatchingRequest(requestKey)
712           .stream()
713           .flatMap(key -> getDeclarationsPerKey.apply(key).stream())
714           .collect(toImmutableSet());
715     }
716 
717     /**
718      * Returns the explicit {@link ContributionBinding}s that match the {@code key} from this and
719      * all ancestor resolvers.
720      */
getExplicitBindings(Key key)721     private ImmutableSet<ContributionBinding> getExplicitBindings(Key key) {
722       ImmutableSet.Builder<ContributionBinding> bindings = ImmutableSet.builder();
723       for (Resolver resolver : getResolverLineage()) {
724         bindings.addAll(resolver.getLocalExplicitBindings(key));
725       }
726       return bindings.build();
727     }
728 
729     /**
730      * Returns the explicit {@link ContributionBinding}s that match the {@code key} from this
731      * resolver.
732      */
getLocalExplicitBindings(Key key)733     private ImmutableSet<ContributionBinding> getLocalExplicitBindings(Key key) {
734       return new ImmutableSet.Builder<ContributionBinding>()
735           .addAll(explicitBindings.get(key))
736           // @Binds @IntoMap declarations have key Map<K, V>, unlike @Provides @IntoMap or @Produces
737           // @IntoMap, which have Map<K, Provider/Producer<V>> keys. So unwrap the key's type's
738           // value type if it's a Map<K, Provider/Producer<V>> before looking in
739           // delegateDeclarations. createDelegateBindings() will create bindings with the properly
740           // wrapped key type.
741           .addAll(
742               createDelegateBindings(delegateDeclarations.get(keyFactory.unwrapMapValueType(key))))
743           .build();
744     }
745 
746     /**
747      * Returns the explicit multibinding contributions that contribute to the map or set requested
748      * by {@code key} from this and all ancestor resolvers.
749      */
getExplicitMultibindings(Key key)750     private ImmutableSet<ContributionBinding> getExplicitMultibindings(Key key) {
751       ImmutableSet.Builder<ContributionBinding> multibindings = ImmutableSet.builder();
752       for (Resolver resolver : getResolverLineage()) {
753         multibindings.addAll(resolver.getLocalExplicitMultibindings(key));
754       }
755       return multibindings.build();
756     }
757 
758     /**
759      * Returns the explicit multibinding contributions that contribute to the map or set requested
760      * by {@code key} from this resolver.
761      */
getLocalExplicitMultibindings(Key key)762     private ImmutableSet<ContributionBinding> getLocalExplicitMultibindings(Key key) {
763       ImmutableSet.Builder<ContributionBinding> multibindings = ImmutableSet.builder();
764       multibindings.addAll(explicitMultibindings.get(key));
765       if (!MapType.isMap(key)
766           || MapType.from(key).isRawType()
767           || MapType.from(key).valuesAreFrameworkType()) {
768         // @Binds @IntoMap declarations have key Map<K, V>, unlike @Provides @IntoMap or @Produces
769         // @IntoMap, which have Map<K, Provider/Producer<V>> keys. So unwrap the key's type's
770         // value type if it's a Map<K, Provider/Producer<V>> before looking in
771         // delegateMultibindingDeclarations. createDelegateBindings() will create bindings with the
772         // properly wrapped key type.
773         multibindings.addAll(
774             createDelegateBindings(
775                 delegateMultibindingDeclarations.get(keyFactory.unwrapMapValueType(key))));
776       }
777       return multibindings.build();
778     }
779 
780     /**
781      * Returns the {@link MultibindingDeclaration}s that match the {@code key} from this and all
782      * ancestor resolvers.
783      */
getMultibindingDeclarations(Key key)784     private ImmutableSet<MultibindingDeclaration> getMultibindingDeclarations(Key key) {
785       ImmutableSet.Builder<MultibindingDeclaration> multibindingDeclarations =
786           ImmutableSet.builder();
787       for (Resolver resolver : getResolverLineage()) {
788         multibindingDeclarations.addAll(resolver.multibindingDeclarations.get(key));
789       }
790       return multibindingDeclarations.build();
791     }
792 
793     /**
794      * Returns the {@link SubcomponentDeclaration}s that match the {@code key} from this and all
795      * ancestor resolvers.
796      */
getSubcomponentDeclarations(Key key)797     private ImmutableSet<SubcomponentDeclaration> getSubcomponentDeclarations(Key key) {
798       ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations =
799           ImmutableSet.builder();
800       for (Resolver resolver : getResolverLineage()) {
801         subcomponentDeclarations.addAll(resolver.subcomponentDeclarations.get(key));
802       }
803       return subcomponentDeclarations.build();
804     }
805     /**
806      * Returns the {@link OptionalBindingDeclaration}s that match the {@code key} from this and all
807      * ancestor resolvers.
808      */
getOptionalBindingDeclarations(Key key)809     private ImmutableSet<OptionalBindingDeclaration> getOptionalBindingDeclarations(Key key) {
810       Optional<Key> unwrapped = keyFactory.unwrapOptional(key);
811       if (!unwrapped.isPresent()) {
812         return ImmutableSet.of();
813       }
814       ImmutableSet.Builder<OptionalBindingDeclaration> declarations = ImmutableSet.builder();
815       for (Resolver resolver : getResolverLineage()) {
816         declarations.addAll(resolver.optionalBindingDeclarations.get(unwrapped.get()));
817       }
818       return declarations.build();
819     }
820 
821     /**
822      * Returns the {@link ResolvedBindings} for {@code key} that was resolved in this resolver or an
823      * ancestor resolver. Only checks for {@link ContributionBinding}s as {@link
824      * MembersInjectionBinding}s are not inherited.
825      */
getPreviouslyResolvedBindings(Key key)826     private Optional<ResolvedBindings> getPreviouslyResolvedBindings(Key key) {
827       Optional<ResolvedBindings> result =
828           Optional.ofNullable(resolvedContributionBindings.get(key));
829       if (result.isPresent()) {
830         return result;
831       } else if (parentResolver.isPresent()) {
832         return parentResolver.get().getPreviouslyResolvedBindings(key);
833       } else {
834         return Optional.empty();
835       }
836     }
837 
resolveMembersInjection(Key key)838     private void resolveMembersInjection(Key key) {
839       ResolvedBindings bindings = lookUpMembersInjectionBinding(key);
840       resolveDependencies(bindings);
841       resolvedMembersInjectionBindings.put(key, bindings);
842     }
843 
resolve(Key key)844     void resolve(Key key) {
845       // If we find a cycle, stop resolving. The original request will add it with all of the
846       // other resolved deps.
847       if (cycleStack.contains(key)) {
848         return;
849       }
850 
851       // If the binding was previously resolved in this (sub)component, don't resolve it again.
852       if (resolvedContributionBindings.containsKey(key)) {
853         return;
854       }
855 
856       /*
857        * If the binding was previously resolved in an ancestor component, then we may be able to
858        * avoid resolving it here and just depend on the ancestor component resolution.
859        *
860        * 1. If it depends transitively on multibinding contributions or optional bindings with
861        *    bindings from this subcomponent, then we have to resolve it in this subcomponent so
862        *    that it sees the local bindings.
863        *
864        * 2. If there are any explicit bindings in this component, they may conflict with those in
865        *    the ancestor component, so resolve them here so that conflicts can be caught.
866        */
867       if (getPreviouslyResolvedBindings(key).isPresent()) {
868         /* Resolve in the parent in case there are multibinding contributions or conflicts in some
869          * component between this one and the previously-resolved one. */
870         parentResolver.get().resolve(key);
871         if (!new LocalDependencyChecker().dependsOnLocalBindings(key)
872             && getLocalExplicitBindings(key).isEmpty()) {
873           /* Cache the inherited parent component's bindings in case resolving at the parent found
874            * bindings in some component between this one and the previously-resolved one. */
875           resolvedContributionBindings.put(key, getPreviouslyResolvedBindings(key).get());
876           return;
877         }
878       }
879 
880       cycleStack.push(key);
881       try {
882         ResolvedBindings bindings = lookUpBindings(key);
883         resolvedContributionBindings.put(key, bindings);
884         resolveDependencies(bindings);
885       } finally {
886         cycleStack.pop();
887       }
888     }
889 
890     /**
891      * {@link #resolve(Key) Resolves} each of the dependencies of the bindings owned by this
892      * component.
893      */
resolveDependencies(ResolvedBindings resolvedBindings)894     private void resolveDependencies(ResolvedBindings resolvedBindings) {
895       for (Binding binding : resolvedBindings.bindingsOwnedBy(componentDescriptor)) {
896         for (DependencyRequest dependency : binding.dependencies()) {
897           resolve(dependency.key());
898         }
899       }
900     }
901 
902     /**
903      * Returns all of the {@link ResolvedBindings} for {@link ContributionBinding}s from this and
904      * all ancestor resolvers, indexed by {@link ResolvedBindings#key()}.
905      */
getResolvedContributionBindings()906     Map<Key, ResolvedBindings> getResolvedContributionBindings() {
907       Map<Key, ResolvedBindings> bindings = new LinkedHashMap<>();
908       parentResolver.ifPresent(parent -> bindings.putAll(parent.getResolvedContributionBindings()));
909       bindings.putAll(resolvedContributionBindings);
910       return bindings;
911     }
912 
913     /**
914      * Returns all of the {@link ResolvedBindings} for {@link MembersInjectionBinding} from this
915      * resolvers, indexed by {@link ResolvedBindings#key()}.
916      */
getResolvedMembersInjectionBindings()917     ImmutableMap<Key, ResolvedBindings> getResolvedMembersInjectionBindings() {
918       return ImmutableMap.copyOf(resolvedMembersInjectionBindings);
919     }
920 
getInheritedModules()921     ImmutableSet<ModuleDescriptor> getInheritedModules() {
922       return parentResolver.isPresent()
923           ? Sets.union(
924                   parentResolver.get().getInheritedModules(),
925                   parentResolver.get().componentDescriptor.modules())
926               .immutableCopy()
927           : ImmutableSet.<ModuleDescriptor>of();
928     }
929 
getOwnedModules()930     ImmutableSet<ModuleDescriptor> getOwnedModules() {
931       return Sets.difference(componentDescriptor.modules(), getInheritedModules()).immutableCopy();
932     }
933 
934     private final class LocalDependencyChecker {
935       private final Set<Object> cycleChecker = new HashSet<>();
936 
937       /**
938        * Returns {@code true} if any of the bindings resolved for {@code key} are multibindings with
939        * contributions declared within this component's modules or optional bindings with present
940        * values declared within this component's modules, or if any of its unscoped dependencies
941        * depend on such bindings.
942        *
943        * <p>We don't care about scoped dependencies because they will never depend on bindings from
944        * subcomponents.
945        *
946        * @throws IllegalArgumentException if {@link #getPreviouslyResolvedBindings(Key)} is empty
947        */
dependsOnLocalBindings(Key key)948       boolean dependsOnLocalBindings(Key key) {
949         // Don't recur infinitely if there are valid cycles in the dependency graph.
950         // http://b/23032377
951         if (!cycleChecker.add(key)) {
952           return false;
953         }
954         return reentrantComputeIfAbsent(
955             keyDependsOnLocalBindingsCache, key, this::dependsOnLocalBindingsUncached);
956       }
957 
dependsOnLocalBindingsUncached(Key key)958       private boolean dependsOnLocalBindingsUncached(Key key) {
959         checkArgument(
960             getPreviouslyResolvedBindings(key).isPresent(),
961             "no previously resolved bindings in %s for %s",
962             Resolver.this,
963             key);
964         ResolvedBindings previouslyResolvedBindings = getPreviouslyResolvedBindings(key).get();
965         if (hasLocalMultibindingContributions(key)
966             || hasLocalOptionalBindingContribution(previouslyResolvedBindings)) {
967           return true;
968         }
969 
970         for (Binding binding : previouslyResolvedBindings.bindings()) {
971           if (dependsOnLocalBindings(binding)) {
972             return true;
973           }
974         }
975         return false;
976       }
977 
978       /**
979        * Returns {@code true} if {@code binding} is unscoped (or has {@link Reusable @Reusable}
980        * scope) and depends on multibindings with contributions declared within this component's
981        * modules, or if any of its unscoped or {@link Reusable @Reusable} scoped dependencies depend
982        * on such local multibindings.
983        *
984        * <p>We don't care about non-reusable scoped dependencies because they will never depend on
985        * multibindings with contributions from subcomponents.
986        */
dependsOnLocalBindings(Binding binding)987       boolean dependsOnLocalBindings(Binding binding) {
988         if (!cycleChecker.add(binding)) {
989           return false;
990         }
991         return reentrantComputeIfAbsent(
992             bindingDependsOnLocalBindingsCache, binding, this::dependsOnLocalBindingsUncached);
993       }
994 
dependsOnLocalBindingsUncached(Binding binding)995       private boolean dependsOnLocalBindingsUncached(Binding binding) {
996         if ((!binding.scope().isPresent() || binding.scope().get().isReusable())
997             // TODO(beder): Figure out what happens with production subcomponents.
998             && !binding.bindingType().equals(BindingType.PRODUCTION)) {
999           for (DependencyRequest dependency : binding.dependencies()) {
1000             if (dependsOnLocalBindings(dependency.key())) {
1001               return true;
1002             }
1003           }
1004         }
1005         return false;
1006       }
1007 
1008       /**
1009        * Returns {@code true} if there is at least one multibinding contribution declared within
1010        * this component's modules that matches the key.
1011        */
hasLocalMultibindingContributions(Key requestKey)1012       private boolean hasLocalMultibindingContributions(Key requestKey) {
1013         return keysMatchingRequest(requestKey)
1014             .stream()
1015             .anyMatch(key -> !getLocalExplicitMultibindings(key).isEmpty());
1016       }
1017 
1018       /**
1019        * Returns {@code true} if there is a contribution in this component for an {@code
1020        * Optional<Foo>} key that has not been contributed in a parent.
1021        */
hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings)1022       private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
1023         if (resolvedBindings
1024             .contributionBindings()
1025             .stream()
1026             .map(ContributionBinding::kind)
1027             .anyMatch(isEqual(OPTIONAL))) {
1028           return !getLocalExplicitBindings(keyFactory.unwrapOptional(resolvedBindings.key()).get())
1029               .isEmpty();
1030         } else {
1031           // If a parent contributes a @Provides Optional<Foo> binding and a child has a
1032           // @BindsOptionalOf Foo method, the two should conflict, even if there is no binding for
1033           // Foo on its own
1034           return !getOptionalBindingDeclarations(resolvedBindings.key()).isEmpty();
1035         }
1036       }
1037     }
1038   }
1039 
1040   /**
1041    * A multimap of those {@code declarations} that are multibinding contribution declarations,
1042    * indexed by the key of the set or map to which they contribute.
1043    */
1044   static <T extends BindingDeclaration>
multibindingContributionsByMultibindingKey( Iterable<T> declarations)1045       ImmutableSetMultimap<Key, T> multibindingContributionsByMultibindingKey(
1046           Iterable<T> declarations) {
1047     ImmutableSetMultimap.Builder<Key, T> builder = ImmutableSetMultimap.builder();
1048     for (T declaration : declarations) {
1049       if (declaration.key().multibindingContributionIdentifier().isPresent()) {
1050         builder.put(
1051             declaration
1052                 .key()
1053                 .toBuilder()
1054                 .multibindingContributionIdentifier(Optional.empty())
1055                 .build(),
1056             declaration);
1057       }
1058     }
1059     return builder.build();
1060   }
1061 }
1062