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.Preconditions;
24 import dagger.internal.codegen.binding.BindingGraph;
25 import dagger.internal.codegen.binding.ComponentRequirement;
26 import dagger.internal.codegen.binding.ProvisionBinding;
27 import dagger.internal.codegen.compileroption.CompilerOptions;
28 import dagger.internal.codegen.javapoet.Expression;
29 
30 /** A binding expression for component provision methods. */
31 final class ComponentProvisionBindingExpression extends SimpleInvocationBindingExpression {
32   private final ProvisionBinding binding;
33   private final BindingGraph bindingGraph;
34   private final ComponentRequirementExpressions componentRequirementExpressions;
35   private final CompilerOptions compilerOptions;
36 
ComponentProvisionBindingExpression( ProvisionBinding binding, BindingGraph bindingGraph, ComponentRequirementExpressions componentRequirementExpressions, CompilerOptions compilerOptions)37   ComponentProvisionBindingExpression(
38       ProvisionBinding binding,
39       BindingGraph bindingGraph,
40       ComponentRequirementExpressions componentRequirementExpressions,
41       CompilerOptions compilerOptions) {
42     super(binding);
43     this.binding = binding;
44     this.bindingGraph = checkNotNull(bindingGraph);
45     this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
46     this.compilerOptions = checkNotNull(compilerOptions);
47   }
48 
49   @Override
getDependencyExpression(ClassName requestingClass)50   Expression getDependencyExpression(ClassName requestingClass) {
51     CodeBlock invocation =
52         CodeBlock.of(
53             "$L.$L()",
54             componentRequirementExpressions.getExpression(componentRequirement(), requestingClass),
55             binding.bindingElement().get().getSimpleName());
56     return Expression.create(
57         binding.contributedPrimitiveType().orElse(binding.key().type()),
58         maybeCheckForNull(binding, compilerOptions, invocation));
59   }
60 
componentRequirement()61   private ComponentRequirement componentRequirement() {
62     return bindingGraph
63         .componentDescriptor()
64         .getDependencyThatDefinesMethod(binding.bindingElement().get());
65   }
66 
maybeCheckForNull( ProvisionBinding binding, CompilerOptions compilerOptions, CodeBlock invocation)67   static CodeBlock maybeCheckForNull(
68       ProvisionBinding binding, CompilerOptions compilerOptions, CodeBlock invocation) {
69     return binding.shouldCheckForNull(compilerOptions)
70         ? CodeBlock.of("$T.checkNotNullFromComponent($L)", Preconditions.class, invocation)
71         : invocation;
72   }
73 }
74