• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
20 import static dagger.internal.codegen.model.BindingKind.MULTIBOUND_MAP;
21 import static dagger.internal.codegen.model.BindingKind.MULTIBOUND_SET;
22 
23 import dagger.assisted.Assisted;
24 import dagger.assisted.AssistedFactory;
25 import dagger.assisted.AssistedInject;
26 import dagger.internal.codegen.binding.BindingRequest;
27 import dagger.internal.codegen.binding.ContributionBinding;
28 import dagger.internal.codegen.binding.FrameworkType;
29 import dagger.internal.codegen.binding.MultiboundMapBinding;
30 import dagger.internal.codegen.binding.MultiboundSetBinding;
31 import dagger.internal.codegen.model.RequestKind;
32 import java.util.HashMap;
33 import java.util.Map;
34 import java.util.Optional;
35 
36 /**
37  * A binding representation that wraps code generation methods that satisfy all kinds of request for
38  * that binding.
39  */
40 final class ProductionBindingRepresentation implements BindingRepresentation {
41   private final ContributionBinding binding;
42   private final DerivedFromFrameworkInstanceRequestRepresentation.Factory
43       derivedFromFrameworkInstanceRequestRepresentationFactory;
44   private final RequestRepresentation producerNodeInstanceRequestRepresentation;
45   private final Map<BindingRequest, RequestRepresentation> requestRepresentations = new HashMap<>();
46 
47   @AssistedInject
ProductionBindingRepresentation( @ssisted ContributionBinding binding, ComponentImplementation componentImplementation, DerivedFromFrameworkInstanceRequestRepresentation.Factory derivedFromFrameworkInstanceRequestRepresentationFactory, ProducerNodeInstanceRequestRepresentation.Factory producerNodeInstanceRequestRepresentationFactory, UnscopedFrameworkInstanceCreationExpressionFactory unscopedFrameworkInstanceCreationExpressionFactory, BindingRepresentations bindingRepresentations)48   ProductionBindingRepresentation(
49       @Assisted ContributionBinding binding,
50       ComponentImplementation componentImplementation,
51       DerivedFromFrameworkInstanceRequestRepresentation.Factory
52           derivedFromFrameworkInstanceRequestRepresentationFactory,
53       ProducerNodeInstanceRequestRepresentation.Factory
54           producerNodeInstanceRequestRepresentationFactory,
55       UnscopedFrameworkInstanceCreationExpressionFactory
56           unscopedFrameworkInstanceCreationExpressionFactory,
57       BindingRepresentations bindingRepresentations) {
58     this.binding = binding;
59     this.derivedFromFrameworkInstanceRequestRepresentationFactory =
60         derivedFromFrameworkInstanceRequestRepresentationFactory;
61     Optional<MemberSelect> staticMethod = staticFactoryCreation();
62     FrameworkInstanceSupplier frameworkInstanceSupplier =
63         staticMethod.isPresent()
64             ? staticMethod::get
65             : new FrameworkFieldInitializer(
66                 componentImplementation,
67                 binding,
68                 binding.scope().isPresent()
69                     ? bindingRepresentations.scope(
70                         binding, unscopedFrameworkInstanceCreationExpressionFactory.create(binding))
71                     : unscopedFrameworkInstanceCreationExpressionFactory.create(binding));
72     this.producerNodeInstanceRequestRepresentation =
73         producerNodeInstanceRequestRepresentationFactory.create(binding, frameworkInstanceSupplier);
74   }
75 
76   @Override
getRequestRepresentation(BindingRequest request)77   public RequestRepresentation getRequestRepresentation(BindingRequest request) {
78     return reentrantComputeIfAbsent(
79         requestRepresentations, request, this::getRequestRepresentationUncached);
80   }
81 
getRequestRepresentationUncached(BindingRequest request)82   private RequestRepresentation getRequestRepresentationUncached(BindingRequest request) {
83     return request.requestKind().equals(RequestKind.PRODUCER)
84         ? producerNodeInstanceRequestRepresentation
85         : derivedFromFrameworkInstanceRequestRepresentationFactory.create(
86             binding,
87             producerNodeInstanceRequestRepresentation,
88             request.requestKind(),
89             FrameworkType.PRODUCER_NODE);
90   }
91   /**
92    * If {@code resolvedBindings} is an unscoped provision binding with no factory arguments, then we
93    * don't need a field to hold its factory. In that case, this method returns the static member
94    * select that returns the factory.
95    */
staticFactoryCreation()96   private Optional<MemberSelect> staticFactoryCreation() {
97     if (binding.dependencies().isEmpty()) {
98       if (binding.kind().equals(MULTIBOUND_MAP)) {
99         return Optional.of(StaticMemberSelects.emptyMapFactory((MultiboundMapBinding) binding));
100       }
101       if (binding.kind().equals(MULTIBOUND_SET)) {
102         return Optional.of(StaticMemberSelects.emptySetFactory((MultiboundSetBinding) binding));
103       }
104     }
105     return Optional.empty();
106   }
107 
108   @AssistedFactory
109   static interface Factory {
create(ContributionBinding binding)110     ProductionBindingRepresentation create(ContributionBinding binding);
111   }
112 }
113