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