• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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