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 dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom; 21 import static dagger.internal.codegen.xprocessing.XProcessingEnvs.wrapType; 22 23 import androidx.room.compiler.processing.XProcessingEnv; 24 import androidx.room.compiler.processing.XType; 25 import com.squareup.javapoet.ClassName; 26 import dagger.internal.codegen.binding.ContributionBinding; 27 import dagger.internal.codegen.binding.FrameworkType; 28 import dagger.internal.codegen.javapoet.Expression; 29 import dagger.internal.codegen.javapoet.ExpressionType; 30 31 /** A binding expression that uses a {@link FrameworkType} field. */ 32 abstract class FrameworkInstanceRequestRepresentation extends RequestRepresentation { 33 private final ContributionBinding binding; 34 private final FrameworkInstanceSupplier frameworkInstanceSupplier; 35 private final XProcessingEnv processingEnv; 36 FrameworkInstanceRequestRepresentation( ContributionBinding binding, FrameworkInstanceSupplier frameworkInstanceSupplier, XProcessingEnv processingEnv)37 FrameworkInstanceRequestRepresentation( 38 ContributionBinding binding, 39 FrameworkInstanceSupplier frameworkInstanceSupplier, 40 XProcessingEnv processingEnv) { 41 this.binding = checkNotNull(binding); 42 this.frameworkInstanceSupplier = checkNotNull(frameworkInstanceSupplier); 43 this.processingEnv = checkNotNull(processingEnv); 44 } 45 46 /** 47 * The expression for the framework instance for this binding. The field will be initialized and 48 * added to the component the first time this method is invoked. 49 */ 50 @Override getDependencyExpression(ClassName requestingClass)51 Expression getDependencyExpression(ClassName requestingClass) { 52 MemberSelect memberSelect = frameworkInstanceSupplier.memberSelect(); 53 XType expressionType = 54 wrapType(frameworkType().frameworkClassName(), binding.contributedType(), processingEnv); 55 return Expression.create( 56 isTypeAccessibleFrom(binding.contributedType(), requestingClass.packageName()) 57 || isInlinedFactoryCreation(memberSelect) 58 ? ExpressionType.create(expressionType) 59 : ExpressionType.createRawType(expressionType), 60 memberSelect.getExpressionFor(requestingClass)); 61 } 62 63 /** Returns the framework type for the binding. */ frameworkType()64 protected abstract FrameworkType frameworkType(); 65 66 /** 67 * Returns {@code true} if a factory is created inline each time it is requested. For example, in 68 * the initialization {@code this.fooProvider = Foo_Factory.create(Bar_Factory.create());}, {@code 69 * Bar_Factory} is considered to be inline. 70 * 71 * <p>This is used in {@link #getDependencyExpression(ClassName)} when determining the type of a 72 * factory. Normally if the {@link ContributionBinding#contributedType()} is not accessible from 73 * the component, the type of the expression will be a raw {@link javax.inject.Provider}. However, 74 * if the factory is created inline, even if contributed type is not accessible, javac will still 75 * be able to determine the type that is returned from the {@code Foo_Factory.create()} method. 76 */ isInlinedFactoryCreation(MemberSelect memberSelect)77 private static boolean isInlinedFactoryCreation(MemberSelect memberSelect) { 78 return memberSelect.staticMember(); 79 } 80 } 81