23
23
import static com .google .common .collect .Iterables .getOnlyElement ;
24
24
import static com .squareup .javapoet .MethodSpec .constructorBuilder ;
25
25
import static com .squareup .javapoet .MethodSpec .methodBuilder ;
26
+ import static com .squareup .javapoet .TypeSpec .classBuilder ;
26
27
import static dagger .internal .codegen .AbstractComponentWriter .InitializationState .DELEGATED ;
27
28
import static dagger .internal .codegen .AbstractComponentWriter .InitializationState .INITIALIZED ;
28
29
import static dagger .internal .codegen .AbstractComponentWriter .InitializationState .UNINITIALIZED ;
@@ -140,13 +141,15 @@ abstract class AbstractComponentWriter {
140
141
protected final BindingGraph graph ;
141
142
protected final ImmutableMap <ComponentDescriptor , String > subcomponentNames ;
142
143
private final Map <BindingKey , InitializationState > initializationStates = new HashMap <>();
143
- protected TypeSpec .Builder component ;
144
+ protected final TypeSpec .Builder component ;
144
145
private final UniqueNameSet componentFieldNames = new UniqueNameSet ();
145
146
private final Map <BindingKey , MemberSelect > memberSelects = new HashMap <>();
146
147
private final Map <BindingKey , MemberSelect > producerFromProviderMemberSelects = new HashMap <>();
147
148
private final Map <BindingKey , RequestFulfillment > requestFulfillments = Maps .newLinkedHashMap ();
148
149
protected final MethodSpec .Builder constructor = constructorBuilder ().addModifiers (PRIVATE );
149
150
protected Optional <ClassName > builderName = Optional .absent ();
151
+ private final OptionalFactories optionalFactories ;
152
+ private boolean done ;
150
153
151
154
/**
152
155
* For each component requirement, the builder field. This map is empty for subcomponents that do
@@ -162,28 +165,37 @@ abstract class AbstractComponentWriter {
162
165
*/
163
166
protected final Map <TypeElement , MemberSelect > componentContributionFields = Maps .newHashMap ();
164
167
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
-
172
168
AbstractComponentWriter (
173
169
Types types ,
174
170
Elements elements ,
175
171
Key .Factory keyFactory ,
176
172
CompilerOptions compilerOptions ,
177
173
ClassName name ,
178
174
BindingGraph graph ,
179
- ImmutableMap <ComponentDescriptor , String > subcomponentNames ) {
175
+ ImmutableMap <ComponentDescriptor , String > subcomponentNames ,
176
+ OptionalFactories optionalFactories ) {
180
177
this .types = types ;
181
178
this .elements = elements ;
182
179
this .keyFactory = keyFactory ;
183
180
this .compilerOptions = compilerOptions ;
181
+ this .component = classBuilder (name );
184
182
this .name = name ;
185
183
this .graph = graph ;
186
184
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 );
187
199
}
188
200
189
201
protected final TypeElement componentDefinitionType () {
@@ -267,22 +279,27 @@ private void setInitializationState(BindingKey bindingKey, InitializationState s
267
279
* component must be regenerated, use a new instance.
268
280
*/
269
281
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 ();
272
284
addBuilder ();
273
285
addFactoryMethods ();
274
286
addFrameworkFields ();
275
287
initializeFrameworkTypes ();
276
288
implementInterfaceMethods ();
277
289
addSubcomponents ();
278
290
component .addMethod (constructor .build ());
291
+ if (graph .componentDescriptor ().kind ().isTopLevel ()) {
292
+ optionalFactories .addMembers (component );
293
+ }
294
+ done = true ;
279
295
return component ;
280
296
}
281
297
282
298
/**
283
- * Creates the component implementation class.
299
+ * Adds Javadoc, modifiers, supertypes, and annotations to the component implementation class
300
+ * declaration.
284
301
*/
285
- protected abstract TypeSpec . Builder createComponentClass ();
302
+ protected abstract void decorateComponent ();
286
303
287
304
/**
288
305
* Adds a builder type.
@@ -737,7 +754,7 @@ private void implementInterfaceMethods() {
737
754
}
738
755
}
739
756
740
- public MethodSpec .Builder methodSpecForComponentMethod (
757
+ private MethodSpec .Builder methodSpecForComponentMethod (
741
758
ExecutableElement method , ExecutableType methodType ) {
742
759
String methodName = method .getSimpleName ().toString ();
743
760
MethodSpec .Builder methodBuilder = MethodSpec .methodBuilder (methodName );
@@ -1279,41 +1296,16 @@ private CodeBlock initializeFactoryForSyntheticOptionalBinding(ContributionBindi
1279
1296
}
1280
1297
1281
1298
if (binding .dependencies ().isEmpty ()) {
1282
- return CodeBlock .of (
1283
- "$N.instance()" , optionalFactoryClass (Optional .<DependencyRequest .Kind >absent ()));
1299
+ return optionalFactories .absentOptionalProvider ();
1284
1300
} else {
1285
1301
TypeMirror valueType = OptionalType .from (binding .key ()).valueType ();
1286
- DependencyRequest .Kind optionalValueKind =
1287
- DependencyRequest .extractKindAndType (valueType ).kind ();
1302
+ DependencyRequest .Kind valueKind = DependencyRequest .extractKindAndType (valueType ).kind ();
1288
1303
FrameworkDependency frameworkDependency =
1289
1304
getOnlyElement (frameworkDependenciesForBinding (binding ));
1290
1305
CodeBlock dependencyArgument =
1291
1306
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 );
1315
1308
}
1316
- return optionalFactoryClasses .get (optionalValueKind );
1317
1309
}
1318
1310
1319
1311
private static String simpleVariableName (TypeElement typeElement ) {
0 commit comments