19
19
import static com .google .common .base .CaseFormat .LOWER_CAMEL ;
20
20
import static com .google .common .base .CaseFormat .UPPER_CAMEL ;
21
21
import static com .google .common .base .Preconditions .checkState ;
22
+ import static com .google .common .base .Verify .verify ;
22
23
import static com .google .common .collect .Iterables .getOnlyElement ;
23
24
import static com .squareup .javapoet .MethodSpec .constructorBuilder ;
24
25
import static com .squareup .javapoet .MethodSpec .methodBuilder ;
38
39
import static dagger .internal .codegen .MemberSelect .staticMethod ;
39
40
import static dagger .internal .codegen .MembersInjectionBinding .Strategy .NO_OP ;
40
41
import static dagger .internal .codegen .Scope .reusableScope ;
41
- import static dagger .internal .codegen .SourceFiles .frameworkTypeUsageStatement ;
42
42
import static dagger .internal .codegen .SourceFiles .generatedClassNameForBinding ;
43
43
import static dagger .internal .codegen .SourceFiles .membersInjectorNameForType ;
44
44
import static dagger .internal .codegen .TypeNames .DELEGATE_FACTORY ;
87
87
import com .squareup .javapoet .CodeBlock ;
88
88
import com .squareup .javapoet .FieldSpec ;
89
89
import com .squareup .javapoet .MethodSpec ;
90
+ import com .squareup .javapoet .ParameterSpec ;
90
91
import com .squareup .javapoet .TypeName ;
91
92
import com .squareup .javapoet .TypeSpec ;
92
93
import com .squareup .javapoet .TypeVariableName ;
103
104
import dagger .producers .internal .MapProducer ;
104
105
import dagger .producers .internal .SetOfProducedProducer ;
105
106
import dagger .producers .internal .SetProducer ;
107
+ import java .util .EnumSet ;
106
108
import java .util .HashMap ;
107
109
import java .util .List ;
108
110
import java .util .Map ;
109
111
import java .util .Set ;
110
112
import javax .inject .Provider ;
111
113
import javax .lang .model .element .ExecutableElement ;
114
+ import javax .lang .model .element .Modifier ;
112
115
import javax .lang .model .element .Name ;
113
116
import javax .lang .model .element .TypeElement ;
114
117
import javax .lang .model .element .VariableElement ;
@@ -141,6 +144,7 @@ abstract class AbstractComponentWriter {
141
144
private final UniqueNameSet componentFieldNames = new UniqueNameSet ();
142
145
private final Map <BindingKey , MemberSelect > memberSelects = new HashMap <>();
143
146
private final Map <BindingKey , MemberSelect > producerFromProviderMemberSelects = new HashMap <>();
147
+ private final Map <BindingKey , RequestFulfillment > requestFulfillments = Maps .newLinkedHashMap ();
144
148
protected final MethodSpec .Builder constructor = constructorBuilder ().addModifiers (PRIVATE );
145
149
protected Optional <ClassName > builderName = Optional .absent ();
146
150
@@ -654,11 +658,39 @@ private static ClassName frameworkMapFactoryClassName(BindingType bindingType) {
654
658
? MAP_OF_PRODUCER_PRODUCER : MAP_PROVIDER_FACTORY ;
655
659
}
656
660
661
+ // TODO(gak): extract this into a proper factory class
662
+ private RequestFulfillment getOrCreateRequestFulfillment (BindingKey bindingKey ) {
663
+ RequestFulfillment requestFulfillment = requestFulfillments .get (bindingKey );
664
+ if (requestFulfillment == null ) {
665
+ /* TODO(gak): it is super convoluted that we create the member selects separately and then
666
+ * look them up again this way. Now that we have RequestFulfillment, the next step is to
667
+ * create it and the MemberSelect and the field on demand rather than in a first pass. */
668
+ MemberSelect memberSelect = getMemberSelect (bindingKey );
669
+ ResolvedBindings resolvedBindings = graph .resolvedBindings ().get (bindingKey );
670
+ switch (resolvedBindings .bindingType ()) {
671
+ case MEMBERS_INJECTION :
672
+ requestFulfillment = new MembersInjectorRequestFulfillment (bindingKey , memberSelect );
673
+ break ;
674
+ case PRODUCTION :
675
+ requestFulfillment = new ProducerFieldRequestFulfillment (bindingKey , memberSelect );
676
+ break ;
677
+ case PROVISION :
678
+ requestFulfillment = new ProviderFieldRequestFulfillment (bindingKey , memberSelect );
679
+ break ;
680
+ default :
681
+ throw new AssertionError ();
682
+ }
683
+ requestFulfillments .put (bindingKey , requestFulfillment );
684
+ }
685
+ return requestFulfillment ;
686
+ }
687
+
657
688
private void implementInterfaceMethods () {
658
689
Set <MethodSignature > interfaceMethods = Sets .newHashSet ();
659
690
for (ComponentMethodDescriptor componentMethod :
660
691
graph .componentDescriptor ().componentMethods ()) {
661
692
if (componentMethod .dependencyRequest ().isPresent ()) {
693
+ DependencyRequest interfaceRequest = componentMethod .dependencyRequest ().get ();
662
694
ExecutableElement methodElement =
663
695
MoreElements .asExecutable (componentMethod .methodElement ());
664
696
ExecutableType requestType =
@@ -671,52 +703,67 @@ private void implementInterfaceMethods() {
671
703
if (!interfaceMethods .contains (signature )) {
672
704
interfaceMethods .add (signature );
673
705
MethodSpec .Builder interfaceMethod =
674
- methodBuilder (methodElement .getSimpleName ().toString ())
675
- .addAnnotation (Override .class )
676
- .addModifiers (PUBLIC )
677
- .returns (TypeName .get (requestType .getReturnType ()));
678
- DependencyRequest interfaceRequest = componentMethod .dependencyRequest ().get ();
679
- BindingKey bindingKey = interfaceRequest .bindingKey ();
680
- MemberSelect memberSelect = getMemberSelect (bindingKey );
681
- CodeBlock memberSelectCodeBlock = memberSelect .getExpressionFor (name );
706
+ methodSpecForComponentMethod (methodElement , requestType );
707
+ RequestFulfillment fulfillment =
708
+ getOrCreateRequestFulfillment (interfaceRequest .bindingKey ());
709
+ CodeBlock codeBlock = fulfillment .getSnippetForDependencyRequest (interfaceRequest , name );
682
710
switch (interfaceRequest .kind ()) {
683
711
case MEMBERS_INJECTOR :
684
712
List <? extends VariableElement > parameters = methodElement .getParameters ();
685
713
if (parameters .isEmpty ()) {
686
714
// we're returning the framework type
687
- interfaceMethod .addStatement ("return $L" , memberSelectCodeBlock );
715
+ interfaceMethod .addStatement ("return $L" , codeBlock );
688
716
} else {
689
- Name parameterName = Iterables .getOnlyElement (parameters ).getSimpleName ();
690
- interfaceMethod .addParameter (
691
- TypeName .get (Iterables .getOnlyElement (requestType .getParameterTypes ())),
692
- parameterName .toString ());
693
- interfaceMethod .addStatement (
694
- "$L.injectMembers($L)" , memberSelectCodeBlock , parameterName );
717
+ Name parameterName =
718
+ Iterables .getOnlyElement (methodElement .getParameters ()).getSimpleName ();
719
+ interfaceMethod .addStatement ("$L.injectMembers($L)" , codeBlock , parameterName );
695
720
if (!requestType .getReturnType ().getKind ().equals (VOID )) {
696
721
interfaceMethod .addStatement ("return $L" , parameterName );
697
722
}
698
723
}
699
724
break ;
700
- case INSTANCE :
701
- case LAZY :
702
- case PRODUCED :
703
- case PRODUCER :
704
- case PROVIDER :
705
- case PROVIDER_OF_LAZY :
706
- case FUTURE :
707
- interfaceMethod .addStatement (
708
- "return $L" ,
709
- frameworkTypeUsageStatement (memberSelectCodeBlock , interfaceRequest .kind ()));
710
- break ;
711
725
default :
712
- throw new AssertionError ();
726
+ interfaceMethod .addStatement ("return $L" , codeBlock );
727
+ break ;
713
728
}
714
729
component .addMethod (interfaceMethod .build ());
715
730
}
716
731
}
717
732
}
718
733
}
719
734
735
+ public MethodSpec .Builder methodSpecForComponentMethod (
736
+ ExecutableElement method , ExecutableType methodType ) {
737
+ String methodName = method .getSimpleName ().toString ();
738
+ MethodSpec .Builder methodBuilder = MethodSpec .methodBuilder (methodName );
739
+
740
+ methodBuilder .addAnnotation (Override .class );
741
+
742
+ Set <Modifier > modifiers = EnumSet .copyOf (method .getModifiers ());
743
+ modifiers .remove (Modifier .ABSTRACT );
744
+ methodBuilder .addModifiers (modifiers );
745
+
746
+ methodBuilder .returns (TypeName .get (methodType .getReturnType ()));
747
+
748
+ List <? extends VariableElement > parameters = method .getParameters ();
749
+ List <? extends TypeMirror > resolvedParameterTypes = methodType .getParameterTypes ();
750
+ verify (parameters .size () == resolvedParameterTypes .size ());
751
+ for (int i = 0 ; i < parameters .size (); i ++) {
752
+ VariableElement parameter = parameters .get (i );
753
+ TypeName type = TypeName .get (resolvedParameterTypes .get (i ));
754
+ String name = parameter .getSimpleName ().toString ();
755
+ Set <Modifier > parameterModifiers = parameter .getModifiers ();
756
+ ParameterSpec .Builder parameterBuilder =
757
+ ParameterSpec .builder (type , name )
758
+ .addModifiers (parameterModifiers .toArray (new Modifier [0 ]));
759
+ methodBuilder .addParameter (parameterBuilder .build ());
760
+ }
761
+ for (TypeMirror thrownType : method .getThrownTypes ()) {
762
+ methodBuilder .addException (TypeName .get (thrownType ));
763
+ }
764
+ return methodBuilder ;
765
+ }
766
+
720
767
private void addSubcomponents () {
721
768
for (Map .Entry <ExecutableElement , BindingGraph > subgraphEntry : graph .subgraphs ().entrySet ()) {
722
769
SubcomponentWriter subcomponent =
0 commit comments