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