Skip to content

Commit 798b5f2

Browse files
authored
Merge pull request square#439 from google/moe_sync_0811
Moe sync 8/11
2 parents 5cba295 + b8dea08 commit 798b5f2

File tree

12 files changed

+348
-56
lines changed

12 files changed

+348
-56
lines changed

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

Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
2020
import static com.google.common.base.CaseFormat.UPPER_CAMEL;
2121
import static com.google.common.base.Preconditions.checkState;
22+
import static com.google.common.base.Verify.verify;
2223
import static com.google.common.collect.Iterables.getOnlyElement;
2324
import static com.squareup.javapoet.MethodSpec.constructorBuilder;
2425
import static com.squareup.javapoet.MethodSpec.methodBuilder;
@@ -38,7 +39,6 @@
3839
import static dagger.internal.codegen.MemberSelect.staticMethod;
3940
import static dagger.internal.codegen.MembersInjectionBinding.Strategy.NO_OP;
4041
import static dagger.internal.codegen.Scope.reusableScope;
41-
import static dagger.internal.codegen.SourceFiles.frameworkTypeUsageStatement;
4242
import static dagger.internal.codegen.SourceFiles.generatedClassNameForBinding;
4343
import static dagger.internal.codegen.SourceFiles.membersInjectorNameForType;
4444
import static dagger.internal.codegen.TypeNames.DELEGATE_FACTORY;
@@ -87,6 +87,7 @@
8787
import com.squareup.javapoet.CodeBlock;
8888
import com.squareup.javapoet.FieldSpec;
8989
import com.squareup.javapoet.MethodSpec;
90+
import com.squareup.javapoet.ParameterSpec;
9091
import com.squareup.javapoet.TypeName;
9192
import com.squareup.javapoet.TypeSpec;
9293
import com.squareup.javapoet.TypeVariableName;
@@ -103,12 +104,14 @@
103104
import dagger.producers.internal.MapProducer;
104105
import dagger.producers.internal.SetOfProducedProducer;
105106
import dagger.producers.internal.SetProducer;
107+
import java.util.EnumSet;
106108
import java.util.HashMap;
107109
import java.util.List;
108110
import java.util.Map;
109111
import java.util.Set;
110112
import javax.inject.Provider;
111113
import javax.lang.model.element.ExecutableElement;
114+
import javax.lang.model.element.Modifier;
112115
import javax.lang.model.element.Name;
113116
import javax.lang.model.element.TypeElement;
114117
import javax.lang.model.element.VariableElement;
@@ -141,6 +144,7 @@ abstract class AbstractComponentWriter {
141144
private final UniqueNameSet componentFieldNames = new UniqueNameSet();
142145
private final Map<BindingKey, MemberSelect> memberSelects = new HashMap<>();
143146
private final Map<BindingKey, MemberSelect> producerFromProviderMemberSelects = new HashMap<>();
147+
private final Map<BindingKey, RequestFulfillment> requestFulfillments = Maps.newLinkedHashMap();
144148
protected final MethodSpec.Builder constructor = constructorBuilder().addModifiers(PRIVATE);
145149
protected Optional<ClassName> builderName = Optional.absent();
146150

@@ -654,11 +658,39 @@ private static ClassName frameworkMapFactoryClassName(BindingType bindingType) {
654658
? MAP_OF_PRODUCER_PRODUCER : MAP_PROVIDER_FACTORY;
655659
}
656660

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+
657688
private void implementInterfaceMethods() {
658689
Set<MethodSignature> interfaceMethods = Sets.newHashSet();
659690
for (ComponentMethodDescriptor componentMethod :
660691
graph.componentDescriptor().componentMethods()) {
661692
if (componentMethod.dependencyRequest().isPresent()) {
693+
DependencyRequest interfaceRequest = componentMethod.dependencyRequest().get();
662694
ExecutableElement methodElement =
663695
MoreElements.asExecutable(componentMethod.methodElement());
664696
ExecutableType requestType =
@@ -671,52 +703,67 @@ private void implementInterfaceMethods() {
671703
if (!interfaceMethods.contains(signature)) {
672704
interfaceMethods.add(signature);
673705
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);
682710
switch (interfaceRequest.kind()) {
683711
case MEMBERS_INJECTOR:
684712
List<? extends VariableElement> parameters = methodElement.getParameters();
685713
if (parameters.isEmpty()) {
686714
// we're returning the framework type
687-
interfaceMethod.addStatement("return $L", memberSelectCodeBlock);
715+
interfaceMethod.addStatement("return $L", codeBlock);
688716
} 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);
695720
if (!requestType.getReturnType().getKind().equals(VOID)) {
696721
interfaceMethod.addStatement("return $L", parameterName);
697722
}
698723
}
699724
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;
711725
default:
712-
throw new AssertionError();
726+
interfaceMethod.addStatement("return $L", codeBlock);
727+
break;
713728
}
714729
component.addMethod(interfaceMethod.build());
715730
}
716731
}
717732
}
718733
}
719734

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+
720767
private void addSubcomponents() {
721768
for (Map.Entry<ExecutableElement, BindingGraph> subgraphEntry : graph.subgraphs().entrySet()) {
722769
SubcomponentWriter subcomponent =

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

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,20 @@ static CodeBlock concat(Iterable<CodeBlock> codeBlocks) {
4040
return join(codeBlocks, "\n");
4141
}
4242

43-
static CodeBlock join(Iterable<CodeBlock> codeBlocks, String delimiter) {
44-
CodeBlock.Builder builder = CodeBlock.builder();
43+
static CodeBlock.Builder join(
44+
CodeBlock.Builder builder, Iterable<CodeBlock> codeBlocks, String delimiter) {
4545
Iterator<CodeBlock> iterator = codeBlocks.iterator();
4646
while (iterator.hasNext()) {
4747
builder.add(iterator.next());
4848
if (iterator.hasNext()) {
4949
builder.add(delimiter);
5050
}
5151
}
52-
return builder.build();
52+
return builder;
53+
}
54+
55+
static CodeBlock join(Iterable<CodeBlock> codeBlocks, String delimiter) {
56+
return join(CodeBlock.builder(), codeBlocks, delimiter).build();
5357
}
5458

5559
static FluentIterable<CodeBlock> toCodeBlocks(Iterable<? extends TypeMirror> typeMirrors) {
@@ -68,12 +72,12 @@ public CodeBlock apply(TypeMirror typeMirror) {
6872
}
6973
};
7074

71-
static Function<ParameterSpec, CodeBlock> PARAMETER_NAME =
75+
static final Function<ParameterSpec, CodeBlock> PARAMETER_NAME =
7276
new Function<ParameterSpec, CodeBlock>() {
73-
@Override
74-
public CodeBlock apply(ParameterSpec input) {
75-
return CodeBlock.of("$N", input);
76-
}
77+
@Override
78+
public CodeBlock apply(ParameterSpec input) {
79+
return CodeBlock.of("$N", input);
80+
}
7781
};
7882

7983
private CodeBlocks() {}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ protected Iterable<? extends ProcessingStep> initSteps() {
115115
new ProductionExecutorModuleGenerator(filer, elements);
116116

117117
DependencyRequest.Factory dependencyRequestFactory =
118-
new DependencyRequest.Factory(elements, keyFactory);
118+
new DependencyRequest.Factory(keyFactory);
119119
ProvisionBinding.Factory provisionBindingFactory =
120120
new ProvisionBinding.Factory(elements, types, keyFactory, dependencyRequestFactory);
121121
ProductionBinding.Factory productionBindingFactory =

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

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import static com.google.common.base.Preconditions.checkNotNull;
2424
import static com.google.common.base.Preconditions.checkState;
2525
import static com.google.common.collect.Iterables.getOnlyElement;
26-
import static javax.lang.model.util.ElementFilter.constructorsIn;
2726

2827
import com.google.auto.common.MoreTypes;
2928
import com.google.auto.value.AutoValue;
@@ -40,22 +39,19 @@
4039
import dagger.internal.codegen.DependencyRequest.Factory.KindAndType;
4140
import dagger.producers.Produced;
4241
import dagger.producers.Producer;
43-
import dagger.producers.internal.AbstractProducer;
4442
import java.util.List;
4543
import javax.annotation.CheckReturnValue;
4644
import javax.inject.Inject;
4745
import javax.inject.Provider;
4846
import javax.lang.model.element.AnnotationMirror;
4947
import javax.lang.model.element.Element;
5048
import javax.lang.model.element.ExecutableElement;
51-
import javax.lang.model.element.TypeElement;
5249
import javax.lang.model.element.VariableElement;
5350
import javax.lang.model.type.DeclaredType;
5451
import javax.lang.model.type.ErrorType;
5552
import javax.lang.model.type.ExecutableType;
5653
import javax.lang.model.type.TypeKind;
5754
import javax.lang.model.type.TypeMirror;
58-
import javax.lang.model.util.Elements;
5955
import javax.lang.model.util.SimpleTypeVisitor7;
6056

6157
/**
@@ -201,11 +197,9 @@ abstract static class Builder {
201197
* which may mean that the type will be generated in a later round of processing.
202198
*/
203199
static final class Factory {
204-
private final Elements elements;
205200
private final Key.Factory keyFactory;
206201

207-
Factory(Elements elements, Key.Factory keyFactory) {
208-
this.elements = elements;
202+
Factory(Key.Factory keyFactory) {
209203
this.keyFactory = keyFactory;
210204
}
211205

@@ -371,15 +365,14 @@ DependencyRequest forProductionImplementationExecutor() {
371365
.build();
372366
}
373367

374-
DependencyRequest forProductionComponentMonitorProvider() {
375-
TypeElement element = elements.getTypeElement(AbstractProducer.class.getCanonicalName());
376-
for (ExecutableElement constructor : constructorsIn(element.getEnclosedElements())) {
377-
if (constructor.getParameters().size() == 2) {
378-
// the 2-arg constructor has the appropriate dependency as its first arg
379-
return forRequiredVariable(constructor.getParameters().get(0), Optional.of("monitor"));
380-
}
381-
}
382-
throw new AssertionError("expected 2-arg constructor in AbstractProducer");
368+
DependencyRequest forProductionComponentMonitor() {
369+
Key key = keyFactory.forProductionComponentMonitor();
370+
return DependencyRequest.builder()
371+
.kind(Kind.PROVIDER)
372+
.key(key)
373+
.requestElement(MoreTypes.asElement(key.type()))
374+
.overriddenVariableName(Optional.of("monitor"))
375+
.build();
383376
}
384377

385378
private DependencyRequest newDependencyRequest(

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import dagger.producers.Producer;
5050
import dagger.producers.Production;
5151
import dagger.producers.internal.ProductionImplementation;
52+
import dagger.producers.monitoring.ProductionComponentMonitor;
5253
import java.util.Map;
5354
import java.util.Set;
5455
import java.util.concurrent.Executor;
@@ -508,6 +509,12 @@ Key forProductionImplementationExecutor() {
508509
getClassElement(Executor.class).asType());
509510
}
510511

512+
Key forProductionComponentMonitor() {
513+
return forQualifiedType(
514+
Optional.<AnnotationMirror>absent(),
515+
getClassElement(ProductionComponentMonitor.class).asType());
516+
}
517+
511518
/**
512519
* If {@code requestKey} is for a {@code Map<K, V>} or {@code Map<K, Produced<V>>}, returns keys
513520
* for {@code Map<K, Provider<V>>} and {@code Map<K, Producer<V>>} (if Dagger-Producers is on
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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 dagger.internal.codegen;
18+
19+
import static com.google.common.base.Preconditions.checkArgument;
20+
import static dagger.internal.codegen.BindingKey.Kind.MEMBERS_INJECTION;
21+
22+
import com.squareup.javapoet.ClassName;
23+
import com.squareup.javapoet.CodeBlock;
24+
import dagger.internal.codegen.DependencyRequest.Kind;
25+
26+
/** Fulfills requests for {@link MembersInjectionBinding} instances. */
27+
final class MembersInjectorRequestFulfillment extends RequestFulfillment {
28+
private final MemberSelect membersInjectorFieldSelect;
29+
30+
MembersInjectorRequestFulfillment(
31+
BindingKey bindingKey, MemberSelect membersInjectorFieldSelect) {
32+
super(bindingKey);
33+
checkArgument(bindingKey.kind().equals(MEMBERS_INJECTION));
34+
this.membersInjectorFieldSelect = membersInjectorFieldSelect;
35+
}
36+
37+
@Override
38+
public CodeBlock getSnippetForDependencyRequest(
39+
DependencyRequest request, ClassName requestingClass) {
40+
checkArgument(request.kind().equals(Kind.MEMBERS_INJECTOR));
41+
return membersInjectorFieldSelect.getExpressionFor(requestingClass);
42+
}
43+
}

0 commit comments

Comments
 (0)