• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import static com.google.auto.common.MoreElements.isAnnotationPresent;
20 import static com.google.auto.common.MoreTypes.asDeclared;
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.Binding.hasNonDefaultTypeParameters;
26 import static dagger.internal.codegen.ComponentDescriptor.isComponentProductionMethod;
27 import static dagger.internal.codegen.ConfigurationAnnotations.getNullableType;
28 import static dagger.internal.codegen.ContributionBinding.bindingKindForMultibindingKey;
29 import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
30 import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
31 import static dagger.internal.codegen.MapKeys.getMapKey;
32 import static dagger.internal.codegen.MoreAnnotationMirrors.wrapOptionalInEquivalence;
33 import static dagger.internal.codegen.Scopes.uniqueScopeOf;
34 import static dagger.model.BindingKind.BOUND_INSTANCE;
35 import static dagger.model.BindingKind.COMPONENT;
36 import static dagger.model.BindingKind.COMPONENT_DEPENDENCY;
37 import static dagger.model.BindingKind.COMPONENT_PRODUCTION;
38 import static dagger.model.BindingKind.COMPONENT_PROVISION;
39 import static dagger.model.BindingKind.DELEGATE;
40 import static dagger.model.BindingKind.INJECTION;
41 import static dagger.model.BindingKind.MEMBERS_INJECTOR;
42 import static dagger.model.BindingKind.OPTIONAL;
43 import static dagger.model.BindingKind.PRODUCTION;
44 import static dagger.model.BindingKind.PROVISION;
45 import static dagger.model.BindingKind.SUBCOMPONENT_CREATOR;
46 import static javax.lang.model.element.ElementKind.CONSTRUCTOR;
47 import static javax.lang.model.element.ElementKind.METHOD;
48 
49 import com.google.auto.common.MoreElements;
50 import com.google.auto.common.MoreTypes;
51 import com.google.common.collect.ImmutableSet;
52 import com.google.common.collect.ImmutableSortedSet;
53 import com.google.common.collect.Iterables;
54 import dagger.Module;
55 import dagger.internal.codegen.MembersInjectionBinding.InjectionSite;
56 import dagger.internal.codegen.ProductionBinding.ProductionKind;
57 import dagger.internal.codegen.langmodel.DaggerElements;
58 import dagger.internal.codegen.langmodel.DaggerTypes;
59 import dagger.model.DependencyRequest;
60 import dagger.model.Key;
61 import dagger.model.RequestKind;
62 import dagger.producers.Produced;
63 import dagger.producers.Producer;
64 import java.util.Optional;
65 import java.util.function.BiFunction;
66 import javax.inject.Inject;
67 import javax.inject.Provider;
68 import javax.lang.model.element.Element;
69 import javax.lang.model.element.ExecutableElement;
70 import javax.lang.model.element.TypeElement;
71 import javax.lang.model.element.VariableElement;
72 import javax.lang.model.type.DeclaredType;
73 import javax.lang.model.type.ExecutableType;
74 import javax.lang.model.type.TypeMirror;
75 
76 /** A factory for {@link Binding} objects. */
77 final class BindingFactory {
78   private final DaggerTypes types;
79   private final KeyFactory keyFactory;
80   private final DependencyRequestFactory dependencyRequestFactory;
81   private final InjectionSiteFactory injectionSiteFactory;
82   private final DaggerElements elements;
83 
84   @Inject
BindingFactory( DaggerTypes types, DaggerElements elements, KeyFactory keyFactory, DependencyRequestFactory dependencyRequestFactory, InjectionSiteFactory injectionSiteFactory)85   BindingFactory(
86       DaggerTypes types,
87       DaggerElements elements,
88       KeyFactory keyFactory,
89       DependencyRequestFactory dependencyRequestFactory,
90       InjectionSiteFactory injectionSiteFactory) {
91     this.types = types;
92     this.elements = elements;
93     this.keyFactory = keyFactory;
94     this.dependencyRequestFactory = dependencyRequestFactory;
95     this.injectionSiteFactory = injectionSiteFactory;
96   }
97 
98   /**
99    * Returns an {@link dagger.model.BindingKind#INJECTION} binding.
100    *
101    * @param constructorElement the {@code @Inject}-annotated constructor
102    * @param resolvedType the parameterized type if the constructor is for a generic class and the
103    *     binding should be for the parameterized type
104    */
105   // TODO(dpb): See if we can just pass the parameterized type and not also the constructor.
injectionBinding( ExecutableElement constructorElement, Optional<TypeMirror> resolvedType)106   ProvisionBinding injectionBinding(
107       ExecutableElement constructorElement, Optional<TypeMirror> resolvedType) {
108     checkArgument(constructorElement.getKind().equals(CONSTRUCTOR));
109     checkArgument(isAnnotationPresent(constructorElement, Inject.class));
110     checkArgument(!getQualifier(constructorElement).isPresent());
111 
112     ExecutableType constructorType = MoreTypes.asExecutable(constructorElement.asType());
113     DeclaredType constructedType =
114         MoreTypes.asDeclared(constructorElement.getEnclosingElement().asType());
115     // If the class this is constructing has some type arguments, resolve everything.
116     if (!constructedType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
117       DeclaredType resolved = MoreTypes.asDeclared(resolvedType.get());
118       // Validate that we're resolving from the correct type.
119       checkState(
120           types.isSameType(types.erasure(resolved), types.erasure(constructedType)),
121           "erased expected type: %s, erased actual type: %s",
122           types.erasure(resolved),
123           types.erasure(constructedType));
124       constructorType = MoreTypes.asExecutable(types.asMemberOf(resolved, constructorElement));
125       constructedType = resolved;
126     }
127 
128     Key key = keyFactory.forInjectConstructorWithResolvedType(constructedType);
129     ImmutableSet<DependencyRequest> provisionDependencies =
130         dependencyRequestFactory.forRequiredResolvedVariables(
131             constructorElement.getParameters(), constructorType.getParameterTypes());
132 
133     ProvisionBinding.Builder builder =
134         ProvisionBinding.builder()
135             .contributionType(ContributionType.UNIQUE)
136             .bindingElement(constructorElement)
137             .key(key)
138             .provisionDependencies(provisionDependencies)
139             .injectionSites(injectionSiteFactory.getInjectionSites(constructedType))
140             .kind(INJECTION)
141             .scope(uniqueScopeOf(constructorElement.getEnclosingElement()));
142 
143     TypeElement bindingTypeElement = MoreElements.asType(constructorElement.getEnclosingElement());
144     if (hasNonDefaultTypeParameters(bindingTypeElement, key.type(), types)) {
145       builder.unresolved(injectionBinding(constructorElement, Optional.empty()));
146     }
147     return builder.build();
148   }
149 
150   /**
151    * Returns a {@link dagger.model.BindingKind#PROVISION} binding for a {@code @Provides}-annotated
152    * method.
153    *
154    * @param contributedBy the installed module that declares or inherits the method
155    */
providesMethodBinding( ExecutableElement providesMethod, TypeElement contributedBy)156   ProvisionBinding providesMethodBinding(
157       ExecutableElement providesMethod, TypeElement contributedBy) {
158     return setMethodBindingProperties(
159             ProvisionBinding.builder(),
160             providesMethod,
161             contributedBy,
162             keyFactory.forProvidesMethod(providesMethod, contributedBy),
163             this::providesMethodBinding)
164         .kind(PROVISION)
165         .scope(uniqueScopeOf(providesMethod))
166         .nullableType(getNullableType(providesMethod))
167         .build();
168   }
169 
170   /**
171    * Returns a {@link dagger.model.BindingKind#PRODUCTION} binding for a {@code @Produces}-annotated
172    * method.
173    *
174    * @param contributedBy the installed module that declares or inherits the method
175    */
producesMethodBinding( ExecutableElement producesMethod, TypeElement contributedBy)176   ProductionBinding producesMethodBinding(
177       ExecutableElement producesMethod, TypeElement contributedBy) {
178     // TODO(beder): Add nullability checking with Java 8.
179     ProductionBinding.Builder builder =
180         setMethodBindingProperties(
181                 ProductionBinding.builder(),
182                 producesMethod,
183                 contributedBy,
184                 keyFactory.forProducesMethod(producesMethod, contributedBy),
185                 this::producesMethodBinding)
186             .kind(PRODUCTION)
187             .productionKind(ProductionKind.fromProducesMethod(producesMethod))
188             .thrownTypes(producesMethod.getThrownTypes())
189             .executorRequest(dependencyRequestFactory.forProductionImplementationExecutor())
190             .monitorRequest(dependencyRequestFactory.forProductionComponentMonitor());
191     return builder.build();
192   }
193 
194   private <C extends ContributionBinding, B extends ContributionBinding.Builder<C, B>>
setMethodBindingProperties( B builder, ExecutableElement method, TypeElement contributedBy, Key key, BiFunction<ExecutableElement, TypeElement, C> create)195       B setMethodBindingProperties(
196           B builder,
197           ExecutableElement method,
198           TypeElement contributedBy,
199           Key key,
200           BiFunction<ExecutableElement, TypeElement, C> create) {
201     checkArgument(method.getKind().equals(METHOD));
202     ExecutableType methodType =
203         MoreTypes.asExecutable(
204             types.asMemberOf(MoreTypes.asDeclared(contributedBy.asType()), method));
205     if (!types.isSameType(methodType, method.asType())) {
206       builder.unresolved(create.apply(method, MoreElements.asType(method.getEnclosingElement())));
207     }
208     return builder
209         .contributionType(ContributionType.fromBindingElement(method))
210         .bindingElement(method)
211         .contributingModule(contributedBy)
212         .key(key)
213         .dependencies(
214             dependencyRequestFactory.forRequiredResolvedVariables(
215                 method.getParameters(), methodType.getParameterTypes()))
216         .wrappedMapKeyAnnotation(wrapOptionalInEquivalence(getMapKey(method)));
217   }
218 
219   /**
220    * Returns a {@link dagger.model.BindingKind#MULTIBOUND_MAP} or {@link
221    * dagger.model.BindingKind#MULTIBOUND_SET} binding given a set of multibinding contribution
222    * bindings.
223    *
224    * @param key a key that may be satisfied by a multibinding
225    */
syntheticMultibinding( Key key, Iterable<ContributionBinding> multibindingContributions)226   ContributionBinding syntheticMultibinding(
227       Key key, Iterable<ContributionBinding> multibindingContributions) {
228     ContributionBinding.Builder<?, ?> builder =
229         multibindingRequiresProduction(key, multibindingContributions)
230             ? ProductionBinding.builder()
231             : ProvisionBinding.builder();
232     return builder
233         .contributionType(ContributionType.UNIQUE)
234         .key(key)
235         .dependencies(
236             dependencyRequestFactory.forMultibindingContributions(key, multibindingContributions))
237         .kind(bindingKindForMultibindingKey(key))
238         .build();
239   }
240 
multibindingRequiresProduction( Key key, Iterable<ContributionBinding> multibindingContributions)241   private boolean multibindingRequiresProduction(
242       Key key, Iterable<ContributionBinding> multibindingContributions) {
243     if (MapType.isMap(key)) {
244       MapType mapType = MapType.from(key);
245       if (mapType.valuesAreTypeOf(Producer.class) || mapType.valuesAreTypeOf(Produced.class)) {
246         return true;
247       }
248     } else if (SetType.isSet(key) && SetType.from(key).elementsAreTypeOf(Produced.class)) {
249       return true;
250     }
251     return Iterables.any(
252         multibindingContributions, binding -> binding.bindingType().equals(BindingType.PRODUCTION));
253   }
254 
255   /** Returns a {@link dagger.model.BindingKind#COMPONENT} binding for the component. */
componentBinding(TypeElement componentDefinitionType)256   ProvisionBinding componentBinding(TypeElement componentDefinitionType) {
257     checkNotNull(componentDefinitionType);
258     return ProvisionBinding.builder()
259         .contributionType(ContributionType.UNIQUE)
260         .bindingElement(componentDefinitionType)
261         .key(keyFactory.forType(componentDefinitionType.asType()))
262         .kind(COMPONENT)
263         .build();
264   }
265 
266   /**
267    * Returns a {@link dagger.model.BindingKind#COMPONENT_DEPENDENCY} binding for a component's
268    * dependency.
269    */
componentDependencyBinding(ComponentRequirement dependency)270   ProvisionBinding componentDependencyBinding(ComponentRequirement dependency) {
271     checkNotNull(dependency);
272     return ProvisionBinding.builder()
273         .contributionType(ContributionType.UNIQUE)
274         .bindingElement(dependency.typeElement())
275         .key(keyFactory.forType(dependency.type()))
276         .kind(COMPONENT_DEPENDENCY)
277         .build();
278   }
279 
280   /**
281    * Returns a {@link dagger.model.BindingKind#COMPONENT_PROVISION} or {@link
282    * dagger.model.BindingKind#COMPONENT_PRODUCTION} binding for a method on a component's
283    * dependency.
284    *
285    * @param componentDescriptor the component with the dependency, not the dependency that has the
286    *     method
287    */
componentDependencyMethodBinding( ComponentDescriptor componentDescriptor, ExecutableElement dependencyMethod)288   ContributionBinding componentDependencyMethodBinding(
289       ComponentDescriptor componentDescriptor, ExecutableElement dependencyMethod) {
290     checkArgument(dependencyMethod.getKind().equals(METHOD));
291     checkArgument(dependencyMethod.getParameters().isEmpty());
292     ContributionBinding.Builder<?, ?> builder;
293     if (componentDescriptor.isProduction()
294         && isComponentProductionMethod(elements, dependencyMethod)) {
295       builder =
296           ProductionBinding.builder()
297               .key(keyFactory.forProductionComponentMethod(dependencyMethod))
298               .kind(COMPONENT_PRODUCTION)
299               .thrownTypes(dependencyMethod.getThrownTypes());
300     } else {
301       builder =
302           ProvisionBinding.builder()
303               .key(keyFactory.forComponentMethod(dependencyMethod))
304               .nullableType(getNullableType(dependencyMethod))
305               .kind(COMPONENT_PROVISION)
306               .scope(uniqueScopeOf(dependencyMethod));
307     }
308     return builder
309         .contributionType(ContributionType.UNIQUE)
310         .bindingElement(dependencyMethod)
311         .build();
312   }
313 
314   /**
315    * Returns a {@link dagger.model.BindingKind#BOUND_INSTANCE} binding for a
316    * {@code @BindsInstance}-annotated builder setter method or factory method parameter.
317    */
boundInstanceBinding(ComponentRequirement requirement, Element element)318   ProvisionBinding boundInstanceBinding(ComponentRequirement requirement, Element element) {
319     checkArgument(element instanceof VariableElement || element instanceof ExecutableElement);
320     VariableElement parameterElement =
321         element instanceof VariableElement
322             ? MoreElements.asVariable(element)
323             : getOnlyElement(MoreElements.asExecutable(element).getParameters());
324     return ProvisionBinding.builder()
325         .contributionType(ContributionType.UNIQUE)
326         .bindingElement(element)
327         .key(requirement.key().get())
328         .nullableType(getNullableType(parameterElement))
329         .kind(BOUND_INSTANCE)
330         .build();
331   }
332 
333   /**
334    * Returns a {@link dagger.model.BindingKind#SUBCOMPONENT_CREATOR} binding declared by a component
335    * method that returns a subcomponent builder. Use {{@link
336    * #subcomponentCreatorBinding(ImmutableSet)}} for bindings declared using {@link
337    * Module#subcomponents()}.
338    *
339    * @param component the component that declares or inherits the method
340    */
subcomponentCreatorBinding( ExecutableElement subcomponentCreatorMethod, TypeElement component)341   ProvisionBinding subcomponentCreatorBinding(
342       ExecutableElement subcomponentCreatorMethod, TypeElement component) {
343     checkArgument(subcomponentCreatorMethod.getKind().equals(METHOD));
344     checkArgument(subcomponentCreatorMethod.getParameters().isEmpty());
345     Key key =
346         keyFactory.forSubcomponentCreatorMethod(
347             subcomponentCreatorMethod, asDeclared(component.asType()));
348     return ProvisionBinding.builder()
349         .contributionType(ContributionType.UNIQUE)
350         .bindingElement(subcomponentCreatorMethod)
351         .key(key)
352         .kind(SUBCOMPONENT_CREATOR)
353         .build();
354   }
355 
356   /**
357    * Returns a {@link dagger.model.BindingKind#SUBCOMPONENT_CREATOR} binding declared using {@link
358    * Module#subcomponents()}.
359    */
subcomponentCreatorBinding( ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations)360   ProvisionBinding subcomponentCreatorBinding(
361       ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) {
362     SubcomponentDeclaration subcomponentDeclaration = subcomponentDeclarations.iterator().next();
363     return ProvisionBinding.builder()
364         .contributionType(ContributionType.UNIQUE)
365         .key(subcomponentDeclaration.key())
366         .kind(SUBCOMPONENT_CREATOR)
367         .build();
368   }
369 
370   /**
371    * Returns a {@link dagger.model.BindingKind#DELEGATE} binding.
372    *
373    * @param delegateDeclaration the {@code @Binds}-annotated declaration
374    * @param actualBinding the binding that satisfies the {@code @Binds} declaration
375    */
delegateBinding( DelegateDeclaration delegateDeclaration, ContributionBinding actualBinding)376   ContributionBinding delegateBinding(
377       DelegateDeclaration delegateDeclaration, ContributionBinding actualBinding) {
378     switch (actualBinding.bindingType()) {
379       case PRODUCTION:
380         return buildDelegateBinding(
381             ProductionBinding.builder().nullableType(actualBinding.nullableType()),
382             delegateDeclaration,
383             Producer.class);
384 
385       case PROVISION:
386         return buildDelegateBinding(
387             ProvisionBinding.builder()
388                 .scope(uniqueScopeOf(delegateDeclaration.bindingElement().get()))
389                 .nullableType(actualBinding.nullableType()),
390             delegateDeclaration,
391             Provider.class);
392 
393       case MEMBERS_INJECTION: // fall-through to throw
394     }
395     throw new AssertionError("bindingType: " + actualBinding);
396   }
397 
398   /**
399    * Returns a {@link dagger.model.BindingKind#DELEGATE} binding used when there is no binding that
400    * satisfies the {@code @Binds} declaration.
401    */
unresolvedDelegateBinding(DelegateDeclaration delegateDeclaration)402   ContributionBinding unresolvedDelegateBinding(DelegateDeclaration delegateDeclaration) {
403     return buildDelegateBinding(
404         ProvisionBinding.builder().scope(uniqueScopeOf(delegateDeclaration.bindingElement().get())),
405         delegateDeclaration,
406         Provider.class);
407   }
408 
buildDelegateBinding( ContributionBinding.Builder<?, ?> builder, DelegateDeclaration delegateDeclaration, Class<?> frameworkType)409   private ContributionBinding buildDelegateBinding(
410       ContributionBinding.Builder<?, ?> builder,
411       DelegateDeclaration delegateDeclaration,
412       Class<?> frameworkType) {
413     return builder
414         .contributionType(delegateDeclaration.contributionType())
415         .bindingElement(delegateDeclaration.bindingElement().get())
416         .contributingModule(delegateDeclaration.contributingModule().get())
417         .key(keyFactory.forDelegateBinding(delegateDeclaration, frameworkType))
418         .dependencies(delegateDeclaration.delegateRequest())
419         .wrappedMapKeyAnnotation(delegateDeclaration.wrappedMapKey())
420         .kind(DELEGATE)
421         .build();
422   }
423 
424   /**
425    * Returns an {@link dagger.model.BindingKind#OPTIONAL} binding for {@code key}.
426    *
427    * @param requestKind the kind of request for the optional binding
428    * @param underlyingKeyBindings the possibly empty set of bindings that exist in the component for
429    *     the underlying (non-optional) key
430    */
syntheticOptionalBinding( Key key, RequestKind requestKind, ResolvedBindings underlyingKeyBindings)431   ContributionBinding syntheticOptionalBinding(
432       Key key, RequestKind requestKind, ResolvedBindings underlyingKeyBindings) {
433     ContributionBinding.Builder<?, ?> builder =
434         syntheticOptionalBindingBuilder(requestKind, underlyingKeyBindings)
435             .contributionType(ContributionType.UNIQUE)
436             .key(key)
437             .kind(OPTIONAL);
438     if (!underlyingKeyBindings.isEmpty()) {
439       builder.dependencies(
440           dependencyRequestFactory.forSyntheticPresentOptionalBinding(key, requestKind));
441     }
442     return builder.build();
443   }
444 
syntheticOptionalBindingBuilder( RequestKind requestKind, ResolvedBindings underlyingKeyBindings)445   private ContributionBinding.Builder<?, ?> syntheticOptionalBindingBuilder(
446       RequestKind requestKind, ResolvedBindings underlyingKeyBindings) {
447     return !underlyingKeyBindings.isEmpty()
448             && (underlyingKeyBindings.bindingTypes().contains(BindingType.PRODUCTION)
449                 || requestKind.equals(RequestKind.PRODUCER) // handles producerFromProvider cases
450                 || requestKind.equals(RequestKind.PRODUCED)) // handles producerFromProvider cases
451         ? ProductionBinding.builder()
452         : ProvisionBinding.builder();
453   }
454 
455   /** Returns a {@link dagger.model.BindingKind#MEMBERS_INJECTOR} binding. */
membersInjectorBinding( Key key, MembersInjectionBinding membersInjectionBinding)456   ProvisionBinding membersInjectorBinding(
457       Key key, MembersInjectionBinding membersInjectionBinding) {
458     return ProvisionBinding.builder()
459         .key(key)
460         .contributionType(ContributionType.UNIQUE)
461         .kind(MEMBERS_INJECTOR)
462         .bindingElement(MoreTypes.asTypeElement(membersInjectionBinding.key().type()))
463         .provisionDependencies(membersInjectionBinding.dependencies())
464         .injectionSites(membersInjectionBinding.injectionSites())
465         .build();
466   }
467 
468   /**
469    * Returns a {@link dagger.model.BindingKind#MEMBERS_INJECTION} binding.
470    *
471    * @param resolvedType if {@code declaredType} is a generic class and {@code resolvedType} is a
472    *     parameterization of that type, the returned binding will be for the resolved type
473    */
474   // TODO(dpb): See if we can just pass one nongeneric/parameterized type.
membersInjectionBinding( DeclaredType declaredType, Optional<TypeMirror> resolvedType)475   MembersInjectionBinding membersInjectionBinding(
476       DeclaredType declaredType, Optional<TypeMirror> resolvedType) {
477     // If the class this is injecting has some type arguments, resolve everything.
478     if (!declaredType.getTypeArguments().isEmpty() && resolvedType.isPresent()) {
479       DeclaredType resolved = asDeclared(resolvedType.get());
480       // Validate that we're resolving from the correct type.
481       checkState(
482           types.isSameType(types.erasure(resolved), types.erasure(declaredType)),
483           "erased expected type: %s, erased actual type: %s",
484           types.erasure(resolved),
485           types.erasure(declaredType));
486       declaredType = resolved;
487     }
488     ImmutableSortedSet<InjectionSite> injectionSites =
489         injectionSiteFactory.getInjectionSites(declaredType);
490     ImmutableSet<DependencyRequest> dependencies =
491         injectionSites
492             .stream()
493             .flatMap(injectionSite -> injectionSite.dependencies().stream())
494             .collect(toImmutableSet());
495 
496     Key key = keyFactory.forMembersInjectedType(declaredType);
497     TypeElement typeElement = MoreElements.asType(declaredType.asElement());
498     return new AutoValue_MembersInjectionBinding(
499         key,
500         dependencies,
501         typeElement,
502         hasNonDefaultTypeParameters(typeElement, key.type(), types)
503             ? Optional.of(
504                 membersInjectionBinding(asDeclared(typeElement.asType()), Optional.empty()))
505             : Optional.empty(),
506         injectionSites);
507   }
508 }
509