Skip to content

Commit 7d87dde

Browse files
authored
Merge pull request square#456 from google/moe_writing_branch_from_fbb684005f94867c54a07e824985836d845ce654
Moe sync 9/6
2 parents a4bb781 + d64c75d commit 7d87dde

File tree

11 files changed

+238
-129
lines changed

11 files changed

+238
-129
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (C) 2016 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 test.multipackage;
18+
19+
import dagger.Component;
20+
import test.multipackage.a.AMultibindsModule;
21+
import test.multipackage.a.UsesInaccessible;
22+
23+
/**
24+
* A component that tests the interaction between multiple packages and {@code @Multibinding}s.
25+
* Specifically, we want:
26+
*
27+
* <ul>
28+
* <li>A {@code @Multibinding} for an empty set of a type not accessible from this package.
29+
* <li>A {@code @Multibinding} for an empty map of a type not accessible from this package.
30+
* <li>A public type that injects the empty set and map of inaccessible objects.
31+
* </ul>
32+
*/
33+
@Component(modules = {AMultibindsModule.class})
34+
interface MultibindsComponent {
35+
UsesInaccessible usesInaccessible();
36+
}

compiler/src/it/functional-tests/src/main/java/test/multipackage/a/AModule.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import dagger.multibindings.StringKey;
2626
import java.util.HashSet;
2727
import java.util.Set;
28-
import javax.inject.Inject;
2928

3029
@Module
3130
public abstract class AModule {
@@ -49,9 +48,4 @@ static Set<Inaccessible> provideSetOfInaccessibles() {
4948
@IntoMap
5049
@StringKey("inaccessible")
5150
abstract Inaccessible provideInaccessibleToMap(Inaccessible inaccessible);
52-
53-
static class Inaccessible {
54-
@Inject Inaccessible() {}
55-
}
56-
5751
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (C) 2015 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 test.multipackage.a;
18+
19+
import dagger.Module;
20+
import dagger.multibindings.Multibinds;
21+
import java.util.Map;
22+
import java.util.Set;
23+
24+
/** A module that {@code @Multibinds} a set and a map of {@link Inaccessible}. */
25+
@Module
26+
public abstract class AMultibindsModule {
27+
@Multibinds
28+
abstract Set<Inaccessible> inaccessibleSet();
29+
30+
@Multibinds
31+
abstract Map<String, Inaccessible> inaccessibleMap();
32+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (C) 2016 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 test.multipackage.a;
18+
19+
import javax.inject.Inject;
20+
21+
final class Inaccessible {
22+
@Inject Inaccessible() {}
23+
}

compiler/src/it/functional-tests/src/main/java/test/multipackage/a/UsesInaccessible.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.Map;
2020
import java.util.Set;
2121
import javax.inject.Inject;
22-
import test.multipackage.a.AModule.Inaccessible;
2322

2423
@SuppressWarnings("unused")
2524
public class UsesInaccessible {

compiler/src/main/java/dagger/internal/codegen/AbstractComponentWriter.java

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static com.google.common.collect.Iterables.getOnlyElement;
2424
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
2525
import static com.squareup.javapoet.MethodSpec.methodBuilder;
26+
import static com.squareup.javapoet.TypeSpec.classBuilder;
2627
import static dagger.internal.codegen.AbstractComponentWriter.InitializationState.DELEGATED;
2728
import static dagger.internal.codegen.AbstractComponentWriter.InitializationState.INITIALIZED;
2829
import 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) {

compiler/src/main/java/dagger/internal/codegen/ComponentWriter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ final class ComponentWriter extends AbstractComponentWriter {
6464
compilerOptions,
6565
name,
6666
graph,
67-
new UniqueSubcomponentNamesGenerator(graph).generate());
67+
new UniqueSubcomponentNamesGenerator(graph).generate(),
68+
new OptionalFactories());
6869
}
6970

7071
/**
@@ -142,10 +143,9 @@ private static ImmutableListMultimap<ComponentDescriptor, String> qualifiedNames
142143
}
143144

144145
@Override
145-
protected TypeSpec.Builder createComponentClass() {
146-
TypeSpec.Builder component = classBuilder(name).addModifiers(PUBLIC, FINAL);
146+
protected void decorateComponent() {
147+
component.addModifiers(PUBLIC, FINAL);
147148
addSupertype(component, componentDefinitionType());
148-
return component;
149149
}
150150

151151
@Override

compiler/src/main/java/dagger/internal/codegen/MemberSelect.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import static dagger.internal.codegen.TypeNames.MAP_PROVIDER_FACTORY;
2727
import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTOR;
2828
import static dagger.internal.codegen.TypeNames.MEMBERS_INJECTORS;
29-
import static dagger.internal.codegen.TypeNames.SET;
3029

3130
import com.google.common.collect.ImmutableList;
3231
import com.squareup.javapoet.ClassName;
@@ -144,10 +143,7 @@ static MemberSelect emptyFrameworkMapFactory(
144143
*/
145144
static MemberSelect emptySetProvider(ClassName setFactoryType, SetType setType) {
146145
return new ParameterizedStaticMethod(
147-
setFactoryType,
148-
ImmutableList.of(setType.elementType()),
149-
CodeBlock.of("empty()"),
150-
SET);
146+
setFactoryType, ImmutableList.of(setType.elementType()), CodeBlock.of("empty()"), FACTORY);
151147
}
152148

153149
private static final class ParameterizedStaticMethod extends MemberSelect {

0 commit comments

Comments
 (0)