• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.writing;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.squareup.javapoet.MethodSpec.methodBuilder;
21 import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
22 import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
23 import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.PRIVATE_METHOD;
24 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
25 import static javax.lang.model.element.Modifier.PRIVATE;
26 
27 import androidx.room.compiler.processing.XProcessingEnv;
28 import androidx.room.compiler.processing.XType;
29 import com.squareup.javapoet.CodeBlock;
30 import com.squareup.javapoet.TypeName;
31 import dagger.assisted.Assisted;
32 import dagger.assisted.AssistedFactory;
33 import dagger.assisted.AssistedInject;
34 import dagger.internal.codegen.binding.BindingRequest;
35 import dagger.internal.codegen.binding.ContributionBinding;
36 import dagger.internal.codegen.compileroption.CompilerOptions;
37 import dagger.internal.codegen.javapoet.ExpressionType;
38 import dagger.internal.codegen.model.RequestKind;
39 import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
40 
41 /**
42  * A binding expression that wraps the dependency expressions in a private, no-arg method.
43  *
44  * <p>Dependents of this binding expression will just call the no-arg private method.
45  */
46 final class PrivateMethodRequestRepresentation extends MethodRequestRepresentation {
47   private final ShardImplementation shardImplementation;
48   private final ContributionBinding binding;
49   private final BindingRequest request;
50   private final RequestRepresentation wrappedRequestRepresentation;
51   private final CompilerOptions compilerOptions;
52   private final XProcessingEnv processingEnv;
53   private String methodName;
54 
55   @AssistedInject
PrivateMethodRequestRepresentation( @ssisted BindingRequest request, @Assisted ContributionBinding binding, @Assisted RequestRepresentation wrappedRequestRepresentation, ComponentImplementation componentImplementation, XProcessingEnv processingEnv, CompilerOptions compilerOptions)56   PrivateMethodRequestRepresentation(
57       @Assisted BindingRequest request,
58       @Assisted ContributionBinding binding,
59       @Assisted RequestRepresentation wrappedRequestRepresentation,
60       ComponentImplementation componentImplementation,
61       XProcessingEnv processingEnv,
62       CompilerOptions compilerOptions) {
63     super(componentImplementation.shardImplementation(binding), processingEnv);
64     this.binding = checkNotNull(binding);
65     this.request = checkNotNull(request);
66     this.wrappedRequestRepresentation = checkNotNull(wrappedRequestRepresentation);
67     this.shardImplementation = componentImplementation.shardImplementation(binding);
68     this.compilerOptions = compilerOptions;
69     this.processingEnv = processingEnv;
70   }
71 
72   @Override
methodCall()73   protected CodeBlock methodCall() {
74     return CodeBlock.of("$N()", methodName());
75   }
76 
77   @Override
returnType()78   protected ExpressionType returnType() {
79     XType type = request.isRequestKind(RequestKind.INSTANCE)
80                 && binding.contributedPrimitiveType().isPresent()
81         ? binding.contributedPrimitiveType().get()
82         : request.requestedType(binding.contributedType(), processingEnv);
83     String requestingPackage = shardImplementation.name().packageName();
84     if (isTypeAccessibleFrom(type, requestingPackage)) {
85       return ExpressionType.create(type);
86     } else if (isDeclared(type) && isRawTypeAccessible(type, requestingPackage)) {
87       return ExpressionType.createRawType(type);
88     } else {
89       return ExpressionType.create(processingEnv.requireType(TypeName.OBJECT));
90     }
91   }
92 
methodName()93   private String methodName() {
94     if (methodName == null) {
95       // Have to set methodName field before implementing the method in order to handle recursion.
96       methodName = shardImplementation.getUniqueMethodName(request);
97 
98       // TODO(bcorso): Fix the order that these generated methods are written to the component.
99       shardImplementation.addMethod(
100           PRIVATE_METHOD,
101           methodBuilder(methodName)
102               .addModifiers(PRIVATE)
103               .returns(returnType().getTypeName())
104               .addStatement(
105                   "return $L",
106                   wrappedRequestRepresentation
107                       .getDependencyExpression(shardImplementation.name())
108                       .codeBlock())
109               .build());
110     }
111     return methodName;
112   }
113 
114   @AssistedFactory
115   static interface Factory {
create( BindingRequest request, ContributionBinding binding, RequestRepresentation wrappedRequestRepresentation)116     PrivateMethodRequestRepresentation create(
117         BindingRequest request,
118         ContributionBinding binding,
119         RequestRepresentation wrappedRequestRepresentation);
120   }
121 }
122