1 /* 2 * Copyright (C) 2018 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.squareup.javapoet.MethodSpec.constructorBuilder; 20 import static dagger.internal.codegen.BindingRequest.bindingRequest; 21 import static dagger.model.RequestKind.INSTANCE; 22 import static javax.lang.model.element.Modifier.FINAL; 23 import static javax.lang.model.element.Modifier.PRIVATE; 24 25 import com.squareup.javapoet.ClassName; 26 import com.squareup.javapoet.CodeBlock; 27 import com.squareup.javapoet.TypeName; 28 import com.squareup.javapoet.TypeSpec; 29 import dagger.internal.codegen.javapoet.Expression; 30 import dagger.internal.codegen.langmodel.DaggerTypes; 31 import dagger.model.Key; 32 import javax.inject.Provider; 33 import javax.lang.model.type.TypeMirror; 34 35 /** 36 * Generates {@linkplain BindingExpression binding expressions} for a binding that is represented by 37 * an inner {@code SwitchingProvider} class. 38 */ 39 final class InnerSwitchingProviders extends SwitchingProviders { 40 private final ComponentBindingExpressions componentBindingExpressions; 41 private final DaggerTypes types; 42 InnerSwitchingProviders( ComponentImplementation componentImplementation, ComponentBindingExpressions componentBindingExpressions, DaggerTypes types)43 InnerSwitchingProviders( 44 ComponentImplementation componentImplementation, 45 ComponentBindingExpressions componentBindingExpressions, 46 DaggerTypes types) { 47 super(componentImplementation, types); 48 this.componentBindingExpressions = componentBindingExpressions; 49 this.types = types; 50 } 51 52 /** 53 * Returns the binding expression for a binding that satisfies a {@link Provider} requests with a 54 * inner {@code SwitchingProvider} class. 55 */ newBindingExpression(ContributionBinding binding)56 BindingExpression newBindingExpression(ContributionBinding binding) { 57 return new BindingExpression() { 58 @Override 59 Expression getDependencyExpression(ClassName requestingClass) { 60 return getProviderExpression(new SwitchCase(binding, requestingClass)); 61 } 62 }; 63 } 64 65 @Override 66 protected TypeSpec createSwitchingProviderType(TypeSpec.Builder builder) { 67 return builder 68 .addModifiers(PRIVATE, FINAL) 69 .addField(TypeName.INT, "id", PRIVATE, FINAL) 70 .addMethod( 71 constructorBuilder() 72 .addParameter(TypeName.INT, "id") 73 .addStatement("this.id = id") 74 .build()) 75 .build(); 76 } 77 78 private final class SwitchCase implements SwitchingProviders.SwitchCase { 79 private final ContributionBinding binding; 80 private final ClassName requestingClass; 81 82 SwitchCase(ContributionBinding binding, ClassName requestingClass) { 83 this.binding = binding; 84 this.requestingClass = requestingClass; 85 } 86 87 @Override 88 public Key key() { 89 return binding.key(); 90 } 91 92 @Override 93 public Expression getProviderExpression(ClassName switchingProviderClass, int switchId) { 94 TypeMirror instanceType = types.accessibleType(binding.contributedType(), requestingClass); 95 return Expression.create( 96 types.wrapType(instanceType, Provider.class), 97 CodeBlock.of("new $T<>($L)", switchingProviderClass, switchId)); 98 } 99 100 @Override 101 public Expression getReturnExpression(ClassName switchingProviderClass) { 102 return componentBindingExpressions.getDependencyExpression( 103 bindingRequest(binding.key(), INSTANCE), switchingProviderClass); 104 } 105 } 106 } 107