2323import static com .google .common .collect .Iterables .getOnlyElement ;
2424import static com .squareup .javapoet .MethodSpec .constructorBuilder ;
2525import static com .squareup .javapoet .MethodSpec .methodBuilder ;
26+ import static com .squareup .javapoet .TypeSpec .classBuilder ;
2627import static dagger .internal .codegen .AbstractComponentWriter .InitializationState .DELEGATED ;
2728import static dagger .internal .codegen .AbstractComponentWriter .InitializationState .INITIALIZED ;
2829import static dagger .internal .codegen .AbstractComponentWriter .InitializationState .UNINITIALIZED ;
@@ -140,13 +141,15 @@ abstract class AbstractComponentWriter {
140141 protected final BindingGraph graph ;
141142 protected final ImmutableMap <ComponentDescriptor , String > subcomponentNames ;
142143 private final Map <BindingKey , InitializationState > initializationStates = new HashMap <>();
143- protected TypeSpec .Builder component ;
144+ protected final TypeSpec .Builder component ;
144145 private final UniqueNameSet componentFieldNames = new UniqueNameSet ();
145146 private final Map <BindingKey , MemberSelect > memberSelects = new HashMap <>();
146147 private final Map <BindingKey , MemberSelect > producerFromProviderMemberSelects = new HashMap <>();
147148 private final Map <BindingKey , RequestFulfillment > requestFulfillments = Maps .newLinkedHashMap ();
148149 protected final MethodSpec .Builder constructor = constructorBuilder ().addModifiers (PRIVATE );
149150 protected Optional <ClassName > builderName = Optional .absent ();
151+ private final OptionalFactories optionalFactories ;
152+ private boolean done ;
150153
151154 /**
152155 * For each component requirement, the builder field. This map is empty for subcomponents that do
@@ -162,28 +165,37 @@ abstract class AbstractComponentWriter {
162165 */
163166 protected final Map <TypeElement , MemberSelect > componentContributionFields = Maps .newHashMap ();
164167
165- /**
166- * The factory classes that implement {@code Provider<Optional<T>>} within the component. If the
167- * key is {@link Optional#absent()}, the class provides absent values.
168- */
169- private final Map <Optional <DependencyRequest .Kind >, TypeSpec > optionalFactoryClasses =
170- new HashMap <>();
171-
172168 AbstractComponentWriter (
173169 Types types ,
174170 Elements elements ,
175171 Key .Factory keyFactory ,
176172 CompilerOptions compilerOptions ,
177173 ClassName name ,
178174 BindingGraph graph ,
179- ImmutableMap <ComponentDescriptor , String > subcomponentNames ) {
175+ ImmutableMap <ComponentDescriptor , String > subcomponentNames ,
176+ OptionalFactories optionalFactories ) {
180177 this .types = types ;
181178 this .elements = elements ;
182179 this .keyFactory = keyFactory ;
183180 this .compilerOptions = compilerOptions ;
181+ this .component = classBuilder (name );
184182 this .name = name ;
185183 this .graph = graph ;
186184 this .subcomponentNames = subcomponentNames ;
185+ this .optionalFactories = optionalFactories ;
186+ }
187+
188+ protected AbstractComponentWriter (
189+ AbstractComponentWriter parent , ClassName name , BindingGraph graph ) {
190+ this (
191+ parent .types ,
192+ parent .elements ,
193+ parent .keyFactory ,
194+ parent .compilerOptions ,
195+ name ,
196+ graph ,
197+ parent .subcomponentNames ,
198+ parent .optionalFactories );
187199 }
188200
189201 protected final TypeElement componentDefinitionType () {
@@ -267,22 +279,27 @@ private void setInitializationState(BindingKey bindingKey, InitializationState s
267279 * component must be regenerated, use a new instance.
268280 */
269281 final TypeSpec .Builder write () {
270- checkState (component == null , "ComponentWriter has already been generated." );
271- component = createComponentClass ();
282+ checkState (! done , "ComponentWriter has already been generated." );
283+ decorateComponent ();
272284 addBuilder ();
273285 addFactoryMethods ();
274286 addFrameworkFields ();
275287 initializeFrameworkTypes ();
276288 implementInterfaceMethods ();
277289 addSubcomponents ();
278290 component .addMethod (constructor .build ());
291+ if (graph .componentDescriptor ().kind ().isTopLevel ()) {
292+ optionalFactories .addMembers (component );
293+ }
294+ done = true ;
279295 return component ;
280296 }
281297
282298 /**
283- * Creates the component implementation class.
299+ * Adds Javadoc, modifiers, supertypes, and annotations to the component implementation class
300+ * declaration.
284301 */
285- protected abstract TypeSpec . Builder createComponentClass ();
302+ protected abstract void decorateComponent ();
286303
287304 /**
288305 * Adds a builder type.
@@ -737,7 +754,7 @@ private void implementInterfaceMethods() {
737754 }
738755 }
739756
740- public MethodSpec .Builder methodSpecForComponentMethod (
757+ private MethodSpec .Builder methodSpecForComponentMethod (
741758 ExecutableElement method , ExecutableType methodType ) {
742759 String methodName = method .getSimpleName ().toString ();
743760 MethodSpec .Builder methodBuilder = MethodSpec .methodBuilder (methodName );
@@ -1279,41 +1296,16 @@ private CodeBlock initializeFactoryForSyntheticOptionalBinding(ContributionBindi
12791296 }
12801297
12811298 if (binding .dependencies ().isEmpty ()) {
1282- return CodeBlock .of (
1283- "$N.instance()" , optionalFactoryClass (Optional .<DependencyRequest .Kind >absent ()));
1299+ return optionalFactories .absentOptionalProvider ();
12841300 } else {
12851301 TypeMirror valueType = OptionalType .from (binding .key ()).valueType ();
1286- DependencyRequest .Kind optionalValueKind =
1287- DependencyRequest .extractKindAndType (valueType ).kind ();
1302+ DependencyRequest .Kind valueKind = DependencyRequest .extractKindAndType (valueType ).kind ();
12881303 FrameworkDependency frameworkDependency =
12891304 getOnlyElement (frameworkDependenciesForBinding (binding ));
12901305 CodeBlock dependencyArgument =
12911306 getDependencyArgument (frameworkDependency ).getExpressionFor (name );
1292- return CodeBlock .of (
1293- "$N.of($L)" , optionalFactoryClass (Optional .of (optionalValueKind )), dependencyArgument );
1294- }
1295- }
1296-
1297- /**
1298- * Returns the nested class that implements {@code Provider<Optional<T>>} for optional bindings.
1299- * Adds it to the root component if it hasn't already been added.
1300- *
1301- * <p>If {@code optionalValueKind} is absent, returns a {@link Provider} class that returns {@link
1302- * Optional#absent()}.
1303- *
1304- * <p>If {@code optionalValueKind} is present, returns a {@link Provider} class where {@code T}
1305- * represents dependency requests of that kind.
1306- */
1307- protected TypeSpec optionalFactoryClass (Optional <DependencyRequest .Kind > optionalValueKind ) {
1308- if (!optionalFactoryClasses .containsKey (optionalValueKind )) {
1309- TypeSpec factory =
1310- optionalValueKind .isPresent ()
1311- ? OptionalFactoryClasses .presentFactoryClass (optionalValueKind .get ())
1312- : OptionalFactoryClasses .ABSENT_FACTORY_CLASS ;
1313- component .addType (factory );
1314- optionalFactoryClasses .put (optionalValueKind , factory );
1307+ return optionalFactories .presentOptionalProvider (valueKind , dependencyArgument );
13151308 }
1316- return optionalFactoryClasses .get (optionalValueKind );
13171309 }
13181310
13191311 private static String simpleVariableName (TypeElement typeElement ) {
0 commit comments