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 com.squareup.javapoet.ClassName; 20 import com.squareup.javapoet.CodeBlock; 21 import dagger.internal.MissingBindingFactory; 22 import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod; 23 import dagger.internal.codegen.javapoet.Expression; 24 import dagger.internal.codegen.langmodel.DaggerTypes; 25 import dagger.producers.internal.MissingBindingProducer; 26 import java.util.Optional; 27 28 /** 29 * A {@link BindingExpression} that implements a method that encapsulates a binding that is not part 30 * of the binding graph when generating a final concrete implementation of a subcomponent. The 31 * implementation throws an exception. It is assumed that a binding may remain missing in a valid 32 * binding graph, because it's possible for there to be dependencies that are passively pruned when 33 * a non-leaf binding is re-defined (such as when {@code @Provides} bindings override 34 * {@code @Inject} bindings). 35 * 36 * <p>This method should never be invoked. If it is the exception indicates an issue within Dagger 37 * itself. 38 */ 39 final class PrunedConcreteMethodBindingExpression extends BindingExpression { 40 private static final CodeBlock METHOD_IMPLEMENTATION = 41 CodeBlock.of( 42 "throw new $T($S);", 43 UnsupportedOperationException.class, 44 "This binding is not part of the final binding graph. The key was requested by a binding " 45 + "that was believed to possibly be part of the graph, but is no longer requested. " 46 + "If this exception is thrown, it is the result of a Dagger bug."); 47 PrunedConcreteMethodBindingExpression()48 PrunedConcreteMethodBindingExpression() {} 49 50 @Override getModifiableBindingMethodImplementation( ModifiableBindingMethod modifiableBindingMethod, ComponentImplementation component, DaggerTypes types)51 CodeBlock getModifiableBindingMethodImplementation( 52 ModifiableBindingMethod modifiableBindingMethod, 53 ComponentImplementation component, 54 DaggerTypes types) { 55 Optional<FrameworkType> frameworkType = modifiableBindingMethod.request().frameworkType(); 56 if (frameworkType.isPresent()) { 57 // If we make initializations replaceable, we can do away with these classes and this logic 58 // since the pruned framework instances will no longer be initialized 59 switch (frameworkType.get()) { 60 case PROVIDER: 61 return missingFrameworkInstance(MissingBindingFactory.class); 62 case PRODUCER_NODE: 63 return missingFrameworkInstance(MissingBindingProducer.class); 64 } 65 throw new AssertionError(frameworkType); 66 } 67 return METHOD_IMPLEMENTATION; 68 } 69 missingFrameworkInstance(Class<?> factoryClass)70 private static CodeBlock missingFrameworkInstance(Class<?> factoryClass) { 71 return CodeBlock.builder().addStatement("return $T.create()", factoryClass).build(); 72 } 73 74 @Override getDependencyExpression(ClassName requestingClass)75 final Expression getDependencyExpression(ClassName requestingClass) { 76 throw new UnsupportedOperationException( 77 "Requesting a dependency expression for a pruned binding."); 78 } 79 } 80