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 21 import com.squareup.javapoet.ClassName; 22 import com.squareup.javapoet.CodeBlock; 23 import dagger.internal.codegen.binding.BindingRequest; 24 import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor; 25 import dagger.internal.codegen.binding.ContributionBinding; 26 import dagger.internal.codegen.javapoet.Expression; 27 import dagger.internal.codegen.langmodel.DaggerTypes; 28 import javax.lang.model.type.TypeMirror; 29 30 /** 31 * A binding expression that implements and uses a component method. 32 * 33 * <p>Dependents of this binding expression will just call the component method. 34 */ 35 final class ComponentMethodBindingExpression extends MethodBindingExpression { 36 private final ComponentImplementation componentImplementation; 37 private final ComponentMethodDescriptor componentMethod; 38 ComponentMethodBindingExpression( BindingRequest request, ContributionBinding binding, MethodImplementationStrategy methodImplementationStrategy, BindingExpression wrappedBindingExpression, ComponentImplementation componentImplementation, ComponentMethodDescriptor componentMethod, DaggerTypes types)39 ComponentMethodBindingExpression( 40 BindingRequest request, 41 ContributionBinding binding, 42 MethodImplementationStrategy methodImplementationStrategy, 43 BindingExpression wrappedBindingExpression, 44 ComponentImplementation componentImplementation, 45 ComponentMethodDescriptor componentMethod, 46 DaggerTypes types) { 47 super( 48 request, 49 binding, 50 methodImplementationStrategy, 51 wrappedBindingExpression, 52 componentImplementation, 53 types); 54 this.componentImplementation = checkNotNull(componentImplementation); 55 this.componentMethod = checkNotNull(componentMethod); 56 } 57 58 @Override getComponentMethodImplementation( ComponentMethodDescriptor componentMethod, ComponentImplementation component)59 protected CodeBlock getComponentMethodImplementation( 60 ComponentMethodDescriptor componentMethod, ComponentImplementation component) { 61 // There could be several methods on the component for the same request key and kind. 62 // Only one should use the BindingMethodImplementation; the others can delegate that one. So 63 // use methodImplementation.body() only if componentMethod equals the method for this instance. 64 65 // Separately, the method might be defined on a supertype that is also a supertype of some 66 // parent component. In that case, the same ComponentMethodDescriptor will be used to add a CMBE 67 // for the parent and the child. Only the parent's should use the BindingMethodImplementation; 68 // the child's can delegate to the parent. So use methodImplementation.body() only if 69 // componentName equals the component for this instance. 70 return componentMethod.equals(this.componentMethod) && component.equals(componentImplementation) 71 ? methodBodyForComponentMethod(componentMethod) 72 : super.getComponentMethodImplementation(componentMethod, component); 73 } 74 75 @Override getDependencyExpression(ClassName requestingClass)76 Expression getDependencyExpression(ClassName requestingClass) { 77 // If a component method returns a primitive, update the expression's type which might be boxed. 78 Expression expression = super.getDependencyExpression(requestingClass); 79 TypeMirror methodReturnType = componentMethod.methodElement().getReturnType(); 80 return methodReturnType.getKind().isPrimitive() 81 ? Expression.create(methodReturnType, expression.codeBlock()) 82 : expression; 83 } 84 85 @Override addMethod()86 protected void addMethod() {} 87 88 @Override methodName()89 protected String methodName() { 90 return componentMethod.methodElement().getSimpleName().toString(); 91 } 92 } 93