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