1 /* 2 * Copyright (C) 2017 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 androidx.room.compiler.processing.XElementKt.isMethod; 20 import static androidx.room.compiler.processing.XElementKt.isVariableElement; 21 import static com.google.common.base.Preconditions.checkArgument; 22 import static com.google.common.base.Preconditions.checkNotNull; 23 import static com.google.common.base.Preconditions.checkState; 24 import static com.google.common.collect.Iterables.getOnlyElement; 25 import static dagger.internal.codegen.base.RequestKinds.getRequestKind; 26 import static dagger.internal.codegen.xprocessing.XElements.asMethod; 27 import static dagger.internal.codegen.xprocessing.XElements.asTypeElement; 28 import static dagger.internal.codegen.xprocessing.XElements.asVariable; 29 import static dagger.internal.codegen.xprocessing.XTypes.erasedTypeName; 30 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared; 31 32 import androidx.room.compiler.processing.XConstructorElement; 33 import androidx.room.compiler.processing.XConstructorType; 34 import androidx.room.compiler.processing.XElement; 35 import androidx.room.compiler.processing.XExecutableParameterElement; 36 import androidx.room.compiler.processing.XMethodElement; 37 import androidx.room.compiler.processing.XMethodType; 38 import androidx.room.compiler.processing.XType; 39 import androidx.room.compiler.processing.XTypeElement; 40 import androidx.room.compiler.processing.XVariableElement; 41 import com.google.common.collect.ImmutableCollection; 42 import com.google.common.collect.ImmutableSet; 43 import com.google.common.collect.Iterables; 44 import dagger.Module; 45 import dagger.internal.codegen.base.MapType; 46 import dagger.internal.codegen.base.OptionalType; 47 import dagger.internal.codegen.base.SetType; 48 import dagger.internal.codegen.javapoet.TypeNames; 49 import dagger.internal.codegen.model.BindingKind; 50 import dagger.internal.codegen.model.DependencyRequest; 51 import dagger.internal.codegen.model.Key; 52 import dagger.internal.codegen.model.RequestKind; 53 import dagger.internal.codegen.xprocessing.Nullability; 54 import java.util.Optional; 55 import javax.inject.Inject; 56 57 /** A factory for {@link Binding} objects. */ 58 public final class BindingFactory { 59 private final KeyFactory keyFactory; 60 private final DependencyRequestFactory dependencyRequestFactory; 61 private final InjectionSiteFactory injectionSiteFactory; 62 private final InjectionAnnotations injectionAnnotations; 63 64 @Inject BindingFactory( KeyFactory keyFactory, DependencyRequestFactory dependencyRequestFactory, InjectionSiteFactory injectionSiteFactory, InjectionAnnotations injectionAnnotations)65 BindingFactory( 66 KeyFactory keyFactory, 67 DependencyRequestFactory dependencyRequestFactory, 68 InjectionSiteFactory injectionSiteFactory, 69 InjectionAnnotations injectionAnnotations) { 70 this.keyFactory = keyFactory; 71 this.dependencyRequestFactory = dependencyRequestFactory; 72 this.injectionSiteFactory = injectionSiteFactory; 73 this.injectionAnnotations = injectionAnnotations; 74 } 75 76 /** 77 * Returns an {@link BindingKind#INJECTION} binding. 78 * 79 * @param constructorElement the {@code @Inject}-annotated constructor 80 * @param resolvedEnclosingType the parameterized type if the constructor is for a generic class 81 * and the binding should be for the parameterized type 82 */ 83 // TODO(dpb): See if we can just pass the parameterized type and not also the constructor. injectionBinding( XConstructorElement constructorElement, Optional<XType> resolvedEnclosingType)84 public InjectionBinding injectionBinding( 85 XConstructorElement constructorElement, Optional<XType> resolvedEnclosingType) { 86 checkArgument(InjectionAnnotations.hasInjectAnnotation(constructorElement)); 87 88 XConstructorType constructorType = constructorElement.getExecutableType(); 89 XType enclosingType = constructorElement.getEnclosingElement().getType(); 90 // If the class this is constructing has some type arguments, resolve everything. 91 if (!enclosingType.getTypeArguments().isEmpty() && resolvedEnclosingType.isPresent()) { 92 checkIsSameErasedType(resolvedEnclosingType.get(), enclosingType); 93 enclosingType = resolvedEnclosingType.get(); 94 constructorType = constructorElement.asMemberOf(enclosingType); 95 } 96 97 // Collect all dependency requests within the provision method. 98 ImmutableSet.Builder<DependencyRequest> constructorDependencies = ImmutableSet.builder(); 99 for (int i = 0; i < constructorElement.getParameters().size(); i++) { 100 XExecutableParameterElement parameter = constructorElement.getParameters().get(i); 101 XType parameterType = constructorType.getParameterTypes().get(i); 102 constructorDependencies.add( 103 dependencyRequestFactory.forRequiredResolvedVariable(parameter, parameterType)); 104 } 105 106 return InjectionBinding.builder() 107 .bindingElement(constructorElement) 108 .key(keyFactory.forInjectConstructorWithResolvedType(enclosingType)) 109 .constructorDependencies(constructorDependencies.build()) 110 .injectionSites(injectionSiteFactory.getInjectionSites(enclosingType)) 111 .scope(injectionAnnotations.getScope(constructorElement.getEnclosingElement())) 112 .unresolved( 113 hasNonDefaultTypeParameters(enclosingType) 114 ? Optional.of(injectionBinding(constructorElement, Optional.empty())) 115 : Optional.empty()) 116 .build(); 117 } 118 119 /** 120 * Returns an {@link BindingKind#ASSISTED_INJECTION} binding. 121 * 122 * @param constructorElement the {@code @Inject}-annotated constructor 123 * @param resolvedEnclosingType the parameterized type if the constructor is for a generic class 124 * and the binding should be for the parameterized type 125 */ 126 // TODO(dpb): See if we can just pass the parameterized type and not also the constructor. assistedInjectionBinding( XConstructorElement constructorElement, Optional<XType> resolvedEnclosingType)127 public AssistedInjectionBinding assistedInjectionBinding( 128 XConstructorElement constructorElement, Optional<XType> resolvedEnclosingType) { 129 checkArgument(constructorElement.hasAnnotation(TypeNames.ASSISTED_INJECT)); 130 131 XConstructorType constructorType = constructorElement.getExecutableType(); 132 XType enclosingType = constructorElement.getEnclosingElement().getType(); 133 // If the class this is constructing has some type arguments, resolve everything. 134 if (!enclosingType.getTypeArguments().isEmpty() && resolvedEnclosingType.isPresent()) { 135 checkIsSameErasedType(resolvedEnclosingType.get(), enclosingType); 136 enclosingType = resolvedEnclosingType.get(); 137 constructorType = constructorElement.asMemberOf(enclosingType); 138 } 139 140 // Collect all dependency requests within the provision method. 141 ImmutableSet.Builder<DependencyRequest> constructorDependencies = ImmutableSet.builder(); 142 for (int i = 0; i < constructorElement.getParameters().size(); i++) { 143 XExecutableParameterElement parameter = constructorElement.getParameters().get(i); 144 XType parameterType = constructorType.getParameterTypes().get(i); 145 // Note: we filter out @Assisted parameters since these aren't considered dependency requests. 146 if (!AssistedInjectionAnnotations.isAssistedParameter(parameter)) { 147 constructorDependencies.add( 148 dependencyRequestFactory.forRequiredResolvedVariable(parameter, parameterType)); 149 } 150 } 151 152 return AssistedInjectionBinding.builder() 153 .bindingElement(constructorElement) 154 .key(keyFactory.forInjectConstructorWithResolvedType(enclosingType)) 155 .constructorDependencies(constructorDependencies.build()) 156 .injectionSites(injectionSiteFactory.getInjectionSites(enclosingType)) 157 .scope(injectionAnnotations.getScope(constructorElement.getEnclosingElement())) 158 .unresolved( 159 hasNonDefaultTypeParameters(enclosingType) 160 ? Optional.of(assistedInjectionBinding(constructorElement, Optional.empty())) 161 : Optional.empty()) 162 .build(); 163 } 164 assistedFactoryBinding( XTypeElement factory, Optional<XType> resolvedFactoryType)165 public AssistedFactoryBinding assistedFactoryBinding( 166 XTypeElement factory, Optional<XType> resolvedFactoryType) { 167 168 // If the class this is constructing has some type arguments, resolve everything. 169 XType factoryType = factory.getType(); 170 if (!factoryType.getTypeArguments().isEmpty() && resolvedFactoryType.isPresent()) { 171 checkIsSameErasedType(resolvedFactoryType.get(), factoryType); 172 factoryType = resolvedFactoryType.get(); 173 } 174 175 XMethodElement factoryMethod = AssistedInjectionAnnotations.assistedFactoryMethod(factory); 176 XMethodType factoryMethodType = factoryMethod.asMemberOf(factoryType); 177 return AssistedFactoryBinding.builder() 178 .key(keyFactory.forType(factoryType)) 179 .bindingElement(factory) 180 .assistedInjectKey(keyFactory.forType(factoryMethodType.getReturnType())) 181 .build(); 182 } 183 184 /** 185 * Returns a {@link BindingKind#PROVISION} binding for a {@code @Provides}-annotated method. 186 * 187 * @param module the installed module that declares or inherits the method 188 */ providesMethodBinding(XMethodElement method, XTypeElement module)189 public ProvisionBinding providesMethodBinding(XMethodElement method, XTypeElement module) { 190 XMethodType methodType = method.asMemberOf(module.getType()); 191 return ProvisionBinding.builder() 192 .scope(injectionAnnotations.getScope(method)) 193 .nullability(Nullability.of(method)) 194 .bindingElement(method) 195 .contributingModule(module) 196 .key(keyFactory.forProvidesMethod(method, module)) 197 .dependencies( 198 dependencyRequestFactory.forRequiredResolvedVariables( 199 method.getParameters(), methodType.getParameterTypes())) 200 .unresolved( 201 methodType.isSameType(method.getExecutableType()) 202 ? Optional.empty() 203 : Optional.of( 204 providesMethodBinding(method, asTypeElement(method.getEnclosingElement())))) 205 .build(); 206 } 207 208 /** 209 * Returns a {@link BindingKind#PRODUCTION} binding for a {@code @Produces}-annotated method. 210 * 211 * @param module the installed module that declares or inherits the method 212 */ producesMethodBinding(XMethodElement method, XTypeElement module)213 public ProductionBinding producesMethodBinding(XMethodElement method, XTypeElement module) { 214 // TODO(beder): Add nullability checking with Java 8. 215 XMethodType methodType = method.asMemberOf(module.getType()); 216 return ProductionBinding.builder() 217 .bindingElement(method) 218 .contributingModule(module) 219 .key(keyFactory.forProducesMethod(method, module)) 220 .executorRequest(dependencyRequestFactory.forProductionImplementationExecutor()) 221 .monitorRequest(dependencyRequestFactory.forProductionComponentMonitor()) 222 .explicitDependencies( 223 dependencyRequestFactory.forRequiredResolvedVariables( 224 method.getParameters(), methodType.getParameterTypes())) 225 .scope(injectionAnnotations.getScope(method)) 226 .unresolved( 227 methodType.isSameType(method.getExecutableType()) 228 ? Optional.empty() 229 : Optional.of( 230 producesMethodBinding(method, asTypeElement(method.getEnclosingElement())))) 231 .build(); 232 } 233 234 /** 235 * Returns a {@link BindingKind#MULTIBOUND_MAP} binding given a set of multibinding contributions. 236 * 237 * @param key a key that may be satisfied by a multibinding 238 */ multiboundMap( Key key, Iterable<ContributionBinding> multibindingContributions)239 public MultiboundMapBinding multiboundMap( 240 Key key, Iterable<ContributionBinding> multibindingContributions) { 241 return MultiboundMapBinding.builder() 242 .optionalBindingType(multibindingBindingType(key, multibindingContributions)) 243 .key(key) 244 .dependencies( 245 dependencyRequestFactory.forMultibindingContributions(key, multibindingContributions)) 246 .build(); 247 } 248 249 /** 250 * Returns a {@link BindingKind#MULTIBOUND_SET} binding given a set of multibinding contributions. 251 * 252 * @param key a key that may be satisfied by a multibinding 253 */ multiboundSet( Key key, Iterable<ContributionBinding> multibindingContributions)254 public MultiboundSetBinding multiboundSet( 255 Key key, Iterable<ContributionBinding> multibindingContributions) { 256 return MultiboundSetBinding.builder() 257 .optionalBindingType(multibindingBindingType(key, multibindingContributions)) 258 .key(key) 259 .dependencies( 260 dependencyRequestFactory.forMultibindingContributions(key, multibindingContributions)) 261 .build(); 262 } 263 multibindingBindingType( Key key, Iterable<ContributionBinding> multibindingContributions)264 private Optional<BindingType> multibindingBindingType( 265 Key key, Iterable<ContributionBinding> multibindingContributions) { 266 if (MapType.isMap(key)) { 267 MapType mapType = MapType.from(key); 268 if (mapType.valuesAreTypeOf(TypeNames.PRODUCER) 269 || mapType.valuesAreTypeOf(TypeNames.PRODUCED)) { 270 return Optional.of(BindingType.PRODUCTION); 271 } 272 } else if (SetType.isSet(key) && SetType.from(key).elementsAreTypeOf(TypeNames.PRODUCED)) { 273 return Optional.of(BindingType.PRODUCTION); 274 } 275 if (Iterables.any( 276 multibindingContributions, 277 binding -> binding.optionalBindingType().equals(Optional.of(BindingType.PRODUCTION)))) { 278 return Optional.of(BindingType.PRODUCTION); 279 } 280 return Iterables.any( 281 multibindingContributions, 282 binding -> binding.optionalBindingType().isEmpty()) 283 // If a dependency is missing a BindingType then we can't determine the BindingType of this 284 // binding yet since it may end up depending on a production type. 285 ? Optional.empty() 286 : Optional.of(BindingType.PROVISION); 287 } 288 289 /** 290 * Returns a {@link BindingKind#COMPONENT} binding for the 291 * component. 292 */ componentBinding(XTypeElement componentDefinitionType)293 public ComponentBinding componentBinding(XTypeElement componentDefinitionType) { 294 checkNotNull(componentDefinitionType); 295 return ComponentBinding.builder() 296 .bindingElement(componentDefinitionType) 297 .key(keyFactory.forType(componentDefinitionType.getType())) 298 .build(); 299 } 300 301 /** 302 * Returns a {@link BindingKind#COMPONENT_DEPENDENCY} binding for a 303 * component's dependency. 304 */ componentDependencyBinding(ComponentRequirement dependency)305 public ComponentDependencyBinding componentDependencyBinding(ComponentRequirement dependency) { 306 checkNotNull(dependency); 307 return ComponentDependencyBinding.builder() 308 .bindingElement(dependency.typeElement()) 309 .key(keyFactory.forType(dependency.type())) 310 .build(); 311 } 312 313 /** 314 * Returns a {@link BindingKind#COMPONENT_PROVISION} binding for a 315 * method on a component's dependency. 316 */ componentDependencyProvisionMethodBinding( XMethodElement dependencyMethod)317 public ComponentDependencyProvisionBinding componentDependencyProvisionMethodBinding( 318 XMethodElement dependencyMethod) { 319 checkArgument(dependencyMethod.getParameters().isEmpty()); 320 return ComponentDependencyProvisionBinding.builder() 321 .key(keyFactory.forComponentMethod(dependencyMethod)) 322 .nullability(Nullability.of(dependencyMethod)) 323 .scope(injectionAnnotations.getScope(dependencyMethod)) 324 .bindingElement(dependencyMethod) 325 .build(); 326 } 327 328 /** 329 * Returns a {@link BindingKind#COMPONENT_PRODUCTION} binding for a 330 * method on a component's dependency. 331 */ componentDependencyProductionMethodBinding( XMethodElement dependencyMethod)332 public ComponentDependencyProductionBinding componentDependencyProductionMethodBinding( 333 XMethodElement dependencyMethod) { 334 checkArgument(dependencyMethod.getParameters().isEmpty()); 335 return ComponentDependencyProductionBinding.builder() 336 .key(keyFactory.forProductionComponentMethod(dependencyMethod)) 337 .bindingElement(dependencyMethod) 338 .build(); 339 } 340 341 /** 342 * Returns a {@link BindingKind#BOUND_INSTANCE} binding for a 343 * {@code @BindsInstance}-annotated builder setter method or factory method parameter. 344 */ boundInstanceBinding(ComponentRequirement requirement, XElement element)345 BoundInstanceBinding boundInstanceBinding(ComponentRequirement requirement, XElement element) { 346 checkArgument(isVariableElement(element) || isMethod(element)); 347 XVariableElement parameterElement = 348 isVariableElement(element) 349 ? asVariable(element) 350 : getOnlyElement(asMethod(element).getParameters()); 351 return BoundInstanceBinding.builder() 352 .bindingElement(element) 353 .key(requirement.key().get()) 354 .nullability(Nullability.of(parameterElement)) 355 .build(); 356 } 357 358 /** 359 * Returns a {@link BindingKind#SUBCOMPONENT_CREATOR} binding 360 * declared by a component method that returns a subcomponent builder. Use {{@link 361 * #subcomponentCreatorBinding(ImmutableSet)}} for bindings declared using {@link 362 * Module#subcomponents()}. 363 * 364 * @param component the component that declares or inherits the method 365 */ subcomponentCreatorBinding( XMethodElement subcomponentCreatorMethod, XTypeElement component)366 SubcomponentCreatorBinding subcomponentCreatorBinding( 367 XMethodElement subcomponentCreatorMethod, XTypeElement component) { 368 checkArgument(subcomponentCreatorMethod.getParameters().isEmpty()); 369 Key key = 370 keyFactory.forSubcomponentCreatorMethod(subcomponentCreatorMethod, component.getType()); 371 return SubcomponentCreatorBinding.builder() 372 .bindingElement(subcomponentCreatorMethod) 373 .key(key) 374 .build(); 375 } 376 377 /** 378 * Returns a {@link BindingKind#SUBCOMPONENT_CREATOR} binding 379 * declared using {@link Module#subcomponents()}. 380 */ subcomponentCreatorBinding( ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations)381 SubcomponentCreatorBinding subcomponentCreatorBinding( 382 ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) { 383 SubcomponentDeclaration subcomponentDeclaration = subcomponentDeclarations.iterator().next(); 384 return SubcomponentCreatorBinding.builder().key(subcomponentDeclaration.key()).build(); 385 } 386 387 /** Returns a {@link BindingKind#DELEGATE} binding. */ delegateBinding(DelegateDeclaration delegateDeclaration)388 DelegateBinding delegateBinding(DelegateDeclaration delegateDeclaration) { 389 return delegateBinding(delegateDeclaration, Optional.empty()); 390 } 391 392 /** 393 * Returns a {@link BindingKind#DELEGATE} binding. 394 * 395 * @param delegateDeclaration the {@code @Binds}-annotated declaration 396 * @param actualBinding the binding that satisfies the {@code @Binds} declaration 397 */ delegateBinding( DelegateDeclaration delegateDeclaration, ContributionBinding actualBinding)398 DelegateBinding delegateBinding( 399 DelegateDeclaration delegateDeclaration, ContributionBinding actualBinding) { 400 return delegateBinding(delegateDeclaration, delegateBindingType(Optional.of(actualBinding))); 401 } 402 delegateBinding( DelegateDeclaration delegateDeclaration, Optional<BindingType> optionalBindingType)403 private DelegateBinding delegateBinding( 404 DelegateDeclaration delegateDeclaration, Optional<BindingType> optionalBindingType) { 405 return DelegateBinding.builder() 406 .contributionType(delegateDeclaration.contributionType()) 407 .bindingElement(delegateDeclaration.bindingElement().get()) 408 .contributingModule(delegateDeclaration.contributingModule().get()) 409 .delegateRequest(delegateDeclaration.delegateRequest()) 410 .nullability(Nullability.of(delegateDeclaration.bindingElement().get())) 411 .optionalBindingType(optionalBindingType) 412 .key( 413 optionalBindingType.isEmpty() 414 // This is used by BindingGraphFactory which passes in an empty optionalBindingType. 415 // In this case, multibound map contributions will always return the key type 416 // without framework types, i.e. Map<K,V>. 417 ? delegateDeclaration.key() 418 // This is used by LegacyBindingGraphFactory, which passes in a non-empty 419 // optionalBindingType. Then, KeyFactory decides whether or not multibound map 420 // contributions should include the factory type based on the compiler flag, 421 // -Adagger.useFrameworkTypeInMapMultibindingContributionKey. 422 : optionalBindingType.get() == BindingType.PRODUCTION 423 ? keyFactory.forDelegateBinding(delegateDeclaration, TypeNames.PRODUCER) 424 : keyFactory.forDelegateBinding(delegateDeclaration, TypeNames.PROVIDER)) 425 .scope(injectionAnnotations.getScope(delegateDeclaration.bindingElement().get())) 426 .build(); 427 } 428 429 /** 430 * Returns a {@link BindingKind#DELEGATE} binding used when there is 431 * no binding that satisfies the {@code @Binds} declaration. 432 */ unresolvedDelegateBinding(DelegateDeclaration delegateDeclaration)433 public DelegateBinding unresolvedDelegateBinding(DelegateDeclaration delegateDeclaration) { 434 return delegateBinding(delegateDeclaration, Optional.of(BindingType.PROVISION)); 435 } 436 delegateBindingType(Optional<ContributionBinding> actualBinding)437 private Optional<BindingType> delegateBindingType(Optional<ContributionBinding> actualBinding) { 438 if (actualBinding.isEmpty()) { 439 return Optional.empty(); 440 } 441 checkArgument(actualBinding.get().bindingType() != BindingType.MEMBERS_INJECTION); 442 return Optional.of(actualBinding.get().bindingType()); 443 } 444 445 /** Returns an {@link BindingKind#OPTIONAL} present binding for {@code key}. */ syntheticPresentOptionalDeclaration( Key key, ImmutableCollection<Binding> optionalContributions)446 OptionalBinding syntheticPresentOptionalDeclaration( 447 Key key, ImmutableCollection<Binding> optionalContributions) { 448 checkArgument(!optionalContributions.isEmpty()); 449 return OptionalBinding.builder() 450 .optionalBindingType(presentOptionalBindingType(key, optionalContributions)) 451 .key(key) 452 .delegateRequest(dependencyRequestFactory.forSyntheticPresentOptionalBinding(key)) 453 .build(); 454 } 455 presentOptionalBindingType( Key key, ImmutableCollection<Binding> optionalContributions)456 private Optional<BindingType> presentOptionalBindingType( 457 Key key, ImmutableCollection<Binding> optionalContributions) { 458 RequestKind requestKind = getRequestKind(OptionalType.from(key).valueType()); 459 if (requestKind.equals(RequestKind.PRODUCER) // handles producerFromProvider cases 460 || requestKind.equals(RequestKind.PRODUCED)) { // handles producerFromProvider cases 461 return Optional.of(BindingType.PRODUCTION); 462 } 463 if (optionalContributions.stream() 464 .filter(binding -> binding.optionalBindingType().isPresent()) 465 .anyMatch(binding -> binding.bindingType() == BindingType.PRODUCTION)) { 466 return Optional.of(BindingType.PRODUCTION); 467 } 468 return optionalContributions.stream() 469 .anyMatch(binding -> binding.optionalBindingType().isEmpty()) 470 // If a dependency is missing a BindingType then we can't determine the BindingType of this 471 // binding yet since it may end up depending on a production type. 472 ? Optional.empty() 473 : Optional.of(BindingType.PROVISION); 474 } 475 476 /** Returns an {@link BindingKind#OPTIONAL} absent binding for {@code key}. */ syntheticAbsentOptionalDeclaration(Key key)477 OptionalBinding syntheticAbsentOptionalDeclaration(Key key) { 478 return OptionalBinding.builder() 479 .key(key) 480 .optionalBindingType(Optional.of(BindingType.PROVISION)) 481 .build(); 482 } 483 484 /** Returns a {@link BindingKind#MEMBERS_INJECTOR} binding. */ membersInjectorBinding( Key key, MembersInjectionBinding membersInjectionBinding)485 public MembersInjectorBinding membersInjectorBinding( 486 Key key, MembersInjectionBinding membersInjectionBinding) { 487 return MembersInjectorBinding.builder() 488 .key(key) 489 .bindingElement(membersInjectionBinding.key().type().xprocessing().getTypeElement()) 490 .injectionSites(membersInjectionBinding.injectionSites()) 491 .build(); 492 } 493 494 /** 495 * Returns a {@link BindingKind#MEMBERS_INJECTION} binding. 496 * 497 * @param resolvedType if {@code declaredType} is a generic class and {@code resolvedType} is a 498 * parameterization of that type, the returned binding will be for the resolved type 499 */ 500 // TODO(dpb): See if we can just pass one nongeneric/parameterized type. membersInjectionBinding(XType type, Optional<XType> resolvedType)501 public MembersInjectionBinding membersInjectionBinding(XType type, Optional<XType> resolvedType) { 502 // If the class this is injecting has some type arguments, resolve everything. 503 if (!type.getTypeArguments().isEmpty() && resolvedType.isPresent()) { 504 checkIsSameErasedType(resolvedType.get(), type); 505 type = resolvedType.get(); 506 } 507 return MembersInjectionBinding.builder() 508 .key(keyFactory.forMembersInjectedType(type)) 509 .injectionSites(injectionSiteFactory.getInjectionSites(type)) 510 .unresolved( 511 hasNonDefaultTypeParameters(type) 512 ? Optional.of( 513 membersInjectionBinding(type.getTypeElement().getType(), Optional.empty())) 514 : Optional.empty()) 515 .build(); 516 } 517 checkIsSameErasedType(XType type1, XType type2)518 private void checkIsSameErasedType(XType type1, XType type2) { 519 checkState( 520 erasedTypeName(type1).equals(erasedTypeName(type2)), 521 "erased expected type: %s, erased actual type: %s", 522 erasedTypeName(type1), 523 erasedTypeName(type2)); 524 } 525 hasNonDefaultTypeParameters(XType type)526 private static boolean hasNonDefaultTypeParameters(XType type) { 527 // If the type is not declared, then it can't have type parameters. 528 if (!isDeclared(type)) { 529 return false; 530 } 531 532 // If the element has no type parameters, none can be non-default. 533 XType defaultType = type.getTypeElement().getType(); 534 if (defaultType.getTypeArguments().isEmpty()) { 535 return false; 536 } 537 538 // The actual type parameter size can be different if the user is using a raw type. 539 if (defaultType.getTypeArguments().size() != type.getTypeArguments().size()) { 540 return true; 541 } 542 543 for (int i = 0; i < defaultType.getTypeArguments().size(); i++) { 544 if (!defaultType.getTypeArguments().get(i).isSameType(type.getTypeArguments().get(i))) { 545 return true; 546 } 547 } 548 return false; 549 } 550 } 551