• 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.google.common.collect.ImmutableSet;
20 import com.google.common.collect.Sets;
21 import com.squareup.javapoet.ClassName;
22 import com.squareup.javapoet.CodeBlock;
23 import dagger.internal.codegen.ModifiableBindingMethods.ModifiableBindingMethod;
24 import dagger.internal.codegen.javapoet.Expression;
25 import dagger.model.DependencyRequest;
26 import dagger.model.Key;
27 import dagger.model.RequestKind;
28 import java.util.Optional;
29 import java.util.Set;
30 
31 /** An abstract base class for multibinding {@link BindingExpression}s. */
32 abstract class MultibindingExpression extends SimpleInvocationBindingExpression {
33   private final ProvisionBinding binding;
34   private final ComponentImplementation componentImplementation;
35 
MultibindingExpression( ResolvedBindings resolvedBindings, ComponentImplementation componentImplementation)36   MultibindingExpression(
37       ResolvedBindings resolvedBindings, ComponentImplementation componentImplementation) {
38     super(resolvedBindings);
39     this.componentImplementation = componentImplementation;
40     this.binding = (ProvisionBinding) resolvedBindings.contributionBinding();
41   }
42 
43   @Override
getDependencyExpression(ClassName requestingClass)44   Expression getDependencyExpression(ClassName requestingClass) {
45     Expression expression = buildDependencyExpression(requestingClass);
46     componentImplementation.registerImplementedMultibinding(binding, bindingRequest());
47     return expression;
48   }
49 
50   /**
51    * Returns an expression that evaluates to the value of a multibinding request for the given
52    * requesting class.
53    */
buildDependencyExpression(ClassName requestingClass)54   protected abstract Expression buildDependencyExpression(ClassName requestingClass);
55 
56   /**
57    * Returns the subset of {@code dependencies} that represent multibinding contributions that were
58    * not included in a superclass implementation of this multibinding method. This is relevant only
59    * for ahead-of-time subcomponents. When not generating ahead-of-time subcomponents there is only
60    * one implementation of a multibinding expression and all {@link DependencyRequest}s from the
61    * argment are returned.
62    */
getNewContributions( ImmutableSet<DependencyRequest> dependencies)63   protected Set<DependencyRequest> getNewContributions(
64       ImmutableSet<DependencyRequest> dependencies) {
65     ImmutableSet<Key> superclassContributions = superclassContributions();
66     return Sets.filter(
67         dependencies, dependency -> !superclassContributions.contains(dependency.key()));
68   }
69 
70   /**
71    * Returns the {@link CodeBlock} representing a call to a superclass implementation of the
72    * modifiable binding method that encapsulates this binding, if it exists. This is only possible
73    * when generating ahead-of-time subcomponents.
74    */
superMethodCall()75   protected Optional<CodeBlock> superMethodCall() {
76     if (componentImplementation.superclassImplementation().isPresent()) {
77       Optional<ModifiableBindingMethod> method =
78           componentImplementation.getModifiableBindingMethod(bindingRequest());
79       if (method.isPresent()) {
80         if (!superclassContributions().isEmpty()) {
81           return Optional.of(CodeBlock.of("super.$L()", method.get().methodSpec().name));
82         }
83       }
84     }
85     return Optional.empty();
86   }
87 
bindingRequest()88   private BindingRequest bindingRequest() {
89     return BindingRequest.bindingRequest(binding.key(), RequestKind.INSTANCE);
90   }
91 
superclassContributions()92   private ImmutableSet<Key> superclassContributions() {
93     return componentImplementation.superclassContributionsMade(bindingRequest());
94   }
95 }
96