blob: 81eb8d9e6116c0470c3e8f15515cea650d4eb973 [file] [log] [blame]
beder72466bc2014-12-08 10:51:05 -08001/*
ronshapiro5dde42d2016-06-17 09:03:35 -07002 * Copyright (C) 2014 The Dagger Authors.
beder72466bc2014-12-08 10:51:05 -08003 *
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 */
dpb1b65b6a2016-07-11 12:11:24 -070016
beder72466bc2014-12-08 10:51:05 -080017package dagger.internal.codegen;
18
gake55f0742016-07-12 15:36:42 -070019import static com.google.common.collect.Sets.immutableEnumSet;
20import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.CLASS_CONSTRUCTOR;
21import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.DELEGATE;
gak4d860192016-10-13 23:41:00 -070022import static dagger.internal.codegen.ContributionBinding.FactoryCreationStrategy.SINGLETON_INSTANCE;
gake55f0742016-07-12 15:36:42 -070023import static dagger.internal.codegen.MapKeys.unwrapValue;
24import static dagger.internal.codegen.MoreAnnotationMirrors.unwrapOptionalEquivalence;
ronshapirodc1a84c2016-08-24 10:47:50 -070025import static javax.lang.model.element.Modifier.ABSTRACT;
26import static javax.lang.model.element.Modifier.STATIC;
gake55f0742016-07-12 15:36:42 -070027
dpbfb7a9d42015-09-15 14:04:03 -070028import com.google.auto.common.MoreTypes;
29import com.google.common.base.Equivalence;
30import com.google.common.base.Equivalence.Wrapper;
gak66241102016-09-13 12:23:00 -070031import com.google.common.collect.ImmutableSet;
dpb482cbd42015-08-07 08:17:31 -070032import com.google.common.collect.ImmutableSetMultimap;
dpbfb7a9d42015-09-15 14:04:03 -070033import com.google.common.collect.Multimaps;
dpb6bd55de2015-09-28 07:58:09 -070034import com.google.common.util.concurrent.ListenableFuture;
dpb6313ae32016-06-21 15:15:26 -070035import com.google.errorprone.annotations.CanIgnoreReturnValue;
dpb6bd55de2015-09-28 07:58:09 -070036import dagger.Component;
dpb482cbd42015-08-07 08:17:31 -070037import dagger.MapKey;
dpb6bd55de2015-09-28 07:58:09 -070038import dagger.Provides;
dpba2620422015-08-15 10:06:54 -070039import dagger.internal.codegen.ContributionType.HasContributionType;
dpb6bd55de2015-09-28 07:58:09 -070040import dagger.producers.Produces;
dpbffd98f62016-12-20 10:05:16 -080041import java.util.Optional;
beder72466bc2014-12-08 10:51:05 -080042import java.util.Set;
dpb6bd55de2015-09-28 07:58:09 -070043import javax.inject.Inject;
dpb482cbd42015-08-07 08:17:31 -070044import javax.lang.model.element.AnnotationMirror;
45import javax.lang.model.element.AnnotationValue;
dpb6313ae32016-06-21 15:15:26 -070046import javax.lang.model.element.Element;
ronshapirodc1a84c2016-08-24 10:47:50 -070047import javax.lang.model.element.Modifier;
dpb6313ae32016-06-21 15:15:26 -070048import javax.lang.model.element.TypeElement;
sameb725e7832015-01-30 05:30:55 -080049import javax.lang.model.type.DeclaredType;
ronshapiroe56af6a2016-05-13 08:25:40 -070050import javax.lang.model.type.TypeMirror;
beder72466bc2014-12-08 10:51:05 -080051
beder72466bc2014-12-08 10:51:05 -080052/**
53 * An abstract class for a value object representing the mechanism by which a {@link Key} can be
54 * contributed to a dependency graph.
55 *
56 * @author Jesse Beder
57 * @since 2.0
58 */
dpba2620422015-08-15 10:06:54 -070059abstract class ContributionBinding extends Binding implements HasContributionType {
dpbbf29ab32015-12-09 07:37:21 -080060
sameb725e7832015-01-30 05:30:55 -080061 /** Returns the type that specifies this' nullability, absent if not nullable. */
62 abstract Optional<DeclaredType> nullableType();
beder72466bc2014-12-08 10:51:05 -080063
ronshapirod42ce7c2016-05-16 08:04:51 -070064 abstract Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKey();
65
66 final Optional<AnnotationMirror> mapKey() {
67 return unwrapOptionalEquivalence(wrappedMapKey());
68 }
69
beder01fed472015-02-26 06:29:53 -080070 /**
dpb6bd55de2015-09-28 07:58:09 -070071 * The kind of contribution this binding represents. Defines which elements can specify this kind
72 * of contribution.
beder01fed472015-02-26 06:29:53 -080073 */
dpb6bd55de2015-09-28 07:58:09 -070074 enum Kind {
75 /**
dpbbf29ab32015-12-09 07:37:21 -080076 * The synthetic binding for {@code Map<K, V>} that depends on either
77 * {@code Map<K, Provider<V>>} or {@code Map<K, Producer<V>>}.
dpb6bd55de2015-09-28 07:58:09 -070078 */
dpbbf29ab32015-12-09 07:37:21 -080079 SYNTHETIC_MAP,
dpb6bd55de2015-09-28 07:58:09 -070080
dpbdb240722016-01-25 14:06:41 -080081 /**
82 * A synthetic binding for a multibound set that depends on the individual multibinding
83 * {@link Provides @Provides} or {@link Produces @Produces} methods.
84 */
85 SYNTHETIC_MULTIBOUND_SET,
86
87 /**
88 * A synthetic binding for a multibound map that depends on the individual multibinding
89 * {@link Provides @Provides} or {@link Produces @Produces} methods.
90 */
91 SYNTHETIC_MULTIBOUND_MAP,
92
gake1b68a22016-04-07 11:54:06 -070093 /**
94 * A binding (provision or production) that delegates from requests for one key to another.
ronshapiro01f9e6e2016-05-12 13:18:14 -070095 * These are the bindings that satisfy {@code @Binds} declarations.
gake1b68a22016-04-07 11:54:06 -070096 */
97 SYNTHETIC_DELEGATE_BINDING,
98
dpbd8d950a2016-08-30 09:24:37 -070099 /**
ronshapirod804a302016-11-08 10:21:56 -0800100 * A binding for a {@link dagger.releasablereferences.ReleasableReferenceManager} or {@link
101 * dagger.releasablereferences.TypedReleasableReferenceManager} object for a scope.
102 */
103 SYNTHETIC_RELEASABLE_REFERENCE_MANAGER,
104
105 /**
106 * A binding for a set of {@link dagger.releasablereferences.ReleasableReferenceManager} or
107 * {@link dagger.releasablereferences.TypedReleasableReferenceManager} objects.
108 */
109 SYNTHETIC_RELEASABLE_REFERENCE_MANAGERS,
110
111 /**
dpbd8d950a2016-08-30 09:24:37 -0700112 * A synthetic binding for {@code Optional} of a type or a {@link javax.inject.Provider}, {@link
113 * dagger.Lazy}, or {@code Provider} of {@code Lazy} of a type. Generated by a {@link
114 * dagger.BindsOptionalOf} declaration.
115 */
116 SYNTHETIC_OPTIONAL_BINDING,
117
dpb6bd55de2015-09-28 07:58:09 -0700118 // Provision kinds
119
120 /** An {@link Inject}-annotated constructor. */
121 INJECTION,
122
123 /** A {@link Provides}-annotated method. */
124 PROVISION,
125
126 /** An implicit binding to a {@link Component @Component}-annotated type. */
127 COMPONENT,
128
129 /** A provision method on a component's {@linkplain Component#dependencies() dependency}. */
130 COMPONENT_PROVISION,
131
dpb99d64082015-11-12 11:27:12 -0800132 /**
133 * A subcomponent builder method on a component or subcomponent.
134 */
135 SUBCOMPONENT_BUILDER,
136
bederb50b8ae2016-12-07 08:36:26 -0800137 /** A builder binding method. */
138 BUILDER_BINDING,
139
dpb6bd55de2015-09-28 07:58:09 -0700140 // Production kinds
141
Ron Shapiro5f21a802016-09-21 10:23:55 -0400142 /** A {@link Produces}-annotated method. */
143 PRODUCTION,
dpb6bd55de2015-09-28 07:58:09 -0700144
145 /**
gakf53c3f92016-08-17 09:55:56 -0700146 * A production method on a production component's {@linkplain
147 * dagger.producers.ProductionComponent#dependencies()} dependency} that returns a
dpb6bd55de2015-09-28 07:58:09 -0700148 * {@link ListenableFuture}. Methods on production component dependencies that don't return a
149 * {@link ListenableFuture} are considered {@linkplain #PROVISION provision bindings}.
150 */
151 COMPONENT_PRODUCTION,
dpbdb240722016-01-25 14:06:41 -0800152 ;
153
gak66241102016-09-13 12:23:00 -0700154 static final ImmutableSet<Kind> SYNTHETIC_MULTIBOUND_KINDS =
155 immutableEnumSet(SYNTHETIC_MULTIBOUND_SET, SYNTHETIC_MULTIBOUND_MAP);
dpbdb240722016-01-25 14:06:41 -0800156
157 /**
gakf53c3f92016-08-17 09:55:56 -0700158 * {@link #SYNTHETIC_MULTIBOUND_SET} or {@link #SYNTHETIC_MULTIBOUND_MAP}, depending on the key.
dpbdb240722016-01-25 14:06:41 -0800159 */
gakf53c3f92016-08-17 09:55:56 -0700160 static Kind forMultibindingKey(Key key) {
ronshapiro698653f2016-06-03 09:14:13 -0700161 if (SetType.isSet(key)) {
dpbdb240722016-01-25 14:06:41 -0800162 return SYNTHETIC_MULTIBOUND_SET;
ronshapiro698653f2016-06-03 09:14:13 -0700163 } else if (MapType.isMap(key)) {
dpbdb240722016-01-25 14:06:41 -0800164 return SYNTHETIC_MULTIBOUND_MAP;
165 } else {
gakf53c3f92016-08-17 09:55:56 -0700166 throw new IllegalArgumentException(String.format("key is not for a set or map: %s", key));
dpbdb240722016-01-25 14:06:41 -0800167 }
168 }
dpb6bd55de2015-09-28 07:58:09 -0700169 }
beder01fed472015-02-26 06:29:53 -0800170
171 /**
dpb6bd55de2015-09-28 07:58:09 -0700172 * The kind of this contribution binding.
beder72466bc2014-12-08 10:51:05 -0800173 */
dpb6bd55de2015-09-28 07:58:09 -0700174 protected abstract Kind bindingKind();
gake1b68a22016-04-07 11:54:06 -0700175
dpb99d64082015-11-12 11:27:12 -0800176 /**
ronshapirodc1a84c2016-08-24 10:47:50 -0700177 * {@code true} if {@link #contributingModule()} is present and this is a nonabstract instance
178 * method.
179 */
180 boolean requiresModuleInstance() {
181 if (!bindingElement().isPresent() || !contributingModule().isPresent()) {
182 return false;
183 }
184 Set<Modifier> modifiers = bindingElement().get().getModifiers();
185 return !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC);
186 }
187
188 /**
dpb6bd55de2015-09-28 07:58:09 -0700189 * The strategy for getting an instance of a factory for a {@link ContributionBinding}.
190 */
191 enum FactoryCreationStrategy {
gak4d860192016-10-13 23:41:00 -0700192 /** The factory class is a single instance. */
193 SINGLETON_INSTANCE,
dpb6bd55de2015-09-28 07:58:09 -0700194 /** The factory must be created by calling the constructor. */
195 CLASS_CONSTRUCTOR,
gake1b68a22016-04-07 11:54:06 -0700196 /** The factory is simply delegated to another. */
197 DELEGATE,
dpb6bd55de2015-09-28 07:58:09 -0700198 }
199
200 /**
dpb7edcd4d2016-06-21 07:52:39 -0700201 * Returns the {@link FactoryCreationStrategy} appropriate for a binding.
202 *
dpba69ead52016-07-11 10:05:20 -0700203 * <p>Delegate bindings use the {@link FactoryCreationStrategy#DELEGATE} strategy.
dpb7edcd4d2016-06-21 07:52:39 -0700204 *
dpba69ead52016-07-11 10:05:20 -0700205 * <p>Bindings without dependencies that don't require a module instance use the {@link
gak4d860192016-10-13 23:41:00 -0700206 * FactoryCreationStrategy#SINGLETON_INSTANCE} strategy.
dpb7edcd4d2016-06-21 07:52:39 -0700207 *
208 * <p>All other bindings use the {@link FactoryCreationStrategy#CLASS_CONSTRUCTOR} strategy.
dpb6bd55de2015-09-28 07:58:09 -0700209 */
210 FactoryCreationStrategy factoryCreationStrategy() {
211 switch (bindingKind()) {
gake1b68a22016-04-07 11:54:06 -0700212 case SYNTHETIC_DELEGATE_BINDING:
dpb7edcd4d2016-06-21 07:52:39 -0700213 return DELEGATE;
dpb6bd55de2015-09-28 07:58:09 -0700214 case PROVISION:
gak75b9b722016-09-29 15:48:40 -0700215 return dependencies().isEmpty() && !requiresModuleInstance()
gak4d860192016-10-13 23:41:00 -0700216 ? SINGLETON_INSTANCE
dpb7edcd4d2016-06-21 07:52:39 -0700217 : CLASS_CONSTRUCTOR;
dpb6bd55de2015-09-28 07:58:09 -0700218 case INJECTION:
dpbdb240722016-01-25 14:06:41 -0800219 case SYNTHETIC_MULTIBOUND_SET:
220 case SYNTHETIC_MULTIBOUND_MAP:
gak4d860192016-10-13 23:41:00 -0700221 return dependencies().isEmpty() ? SINGLETON_INSTANCE : CLASS_CONSTRUCTOR;
dpb6bd55de2015-09-28 07:58:09 -0700222 default:
dpb7edcd4d2016-06-21 07:52:39 -0700223 return CLASS_CONSTRUCTOR;
dpb6bd55de2015-09-28 07:58:09 -0700224 }
225 }
226
227 /**
ronshapiroe56af6a2016-05-13 08:25:40 -0700228 * The {@link TypeMirror type} for the {@code Factory<T>} or {@code Producer<T>} which is created
dpbdf43ccb2017-04-25 10:19:10 -0700229 * for this binding. Uses the binding's key, V in the case of {@code Map<K, FrameworkClass<V>>>},
ronshapiroe56af6a2016-05-13 08:25:40 -0700230 * and E {@code Set<E>} for {@link dagger.multibindings.IntoSet @IntoSet} methods.
231 */
gak4d860192016-10-13 23:41:00 -0700232 final TypeMirror contributedType() {
ronshapiroe56af6a2016-05-13 08:25:40 -0700233 switch (contributionType()) {
234 case MAP:
gak8449ca32016-08-18 19:59:29 -0700235 return MapType.from(key()).unwrappedValueType(bindingType().frameworkClass());
ronshapiroe56af6a2016-05-13 08:25:40 -0700236 case SET:
ronshapiro698653f2016-06-03 09:14:13 -0700237 return SetType.from(key()).elementType();
ronshapiroe56af6a2016-05-13 08:25:40 -0700238 case SET_VALUES:
239 case UNIQUE:
240 return key().type();
241 default:
242 throw new AssertionError();
243 }
244 }
245
246 /**
dpb482cbd42015-08-07 08:17:31 -0700247 * Indexes map-multibindings by map key (the result of calling
248 * {@link AnnotationValue#getValue()} on a single member or the whole {@link AnnotationMirror}
249 * itself, depending on {@link MapKey#unwrapValue()}).
250 */
dpb7c3ff292015-10-06 12:50:32 -0700251 static ImmutableSetMultimap<Object, ContributionBinding> indexMapBindingsByMapKey(
252 Set<ContributionBinding> mapBindings) {
dpbfb7a9d42015-09-15 14:04:03 -0700253 return ImmutableSetMultimap.copyOf(
254 Multimaps.index(
255 mapBindings,
gak66241102016-09-13 12:23:00 -0700256 mapBinding -> {
257 AnnotationMirror mapKey = mapBinding.mapKey().get();
dpbffd98f62016-12-20 10:05:16 -0800258 return unwrapValue(mapKey).map(AnnotationValue::getValue).orElse(mapKey);
dpbfb7a9d42015-09-15 14:04:03 -0700259 }));
260 }
261
262 /**
263 * Indexes map-multibindings by map key annotation type.
264 */
dpb7c3ff292015-10-06 12:50:32 -0700265 static ImmutableSetMultimap<Wrapper<DeclaredType>, ContributionBinding>
266 indexMapBindingsByAnnotationType(Set<ContributionBinding> mapBindings) {
dpbfb7a9d42015-09-15 14:04:03 -0700267 return ImmutableSetMultimap.copyOf(
268 Multimaps.index(
269 mapBindings,
gak66241102016-09-13 12:23:00 -0700270 mapBinding ->
271 MoreTypes.equivalence().wrap(mapBinding.mapKey().get().getAnnotationType())));
dpb482cbd42015-08-07 08:17:31 -0700272 }
dpb6313ae32016-06-21 15:15:26 -0700273
274 /**
275 * Base builder for {@link com.google.auto.value.AutoValue @AutoValue} subclasses of
276 * {@link ContributionBinding}.
277 */
278 @CanIgnoreReturnValue
279 abstract static class Builder<B extends Builder<B>> {
280 abstract B contributionType(ContributionType contributionType);
281
282 abstract B bindingElement(Element bindingElement);
283
284 abstract B contributingModule(TypeElement contributingModule);
285
286 abstract B key(Key key);
287
dpb6313ae32016-06-21 15:15:26 -0700288 abstract B nullableType(Optional<DeclaredType> nullableType);
289
dpb6313ae32016-06-21 15:15:26 -0700290 abstract B wrappedMapKey(Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedMapKey);
291
292 abstract B bindingKind(ContributionBinding.Kind kind);
293 }
beder72466bc2014-12-08 10:51:05 -0800294}