blob: 3c4cecc069473b79a0fa92a503702e41a8c783bb [file] [log] [blame]
Christian Edward Gruberc8e11072014-03-17 08:38:59 -07001/*
ronshapiro5dde42d2016-06-17 09:03:35 -07002 * Copyright (C) 2014 The Dagger Authors.
Christian Edward Gruberc8e11072014-03-17 08:38:59 -07003 *
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 */
dpba69ead52016-07-11 10:05:20 -070016
Christian Edward Gruberc8e11072014-03-17 08:38:59 -070017package dagger.internal.codegen;
18
gake55f0742016-07-12 15:36:42 -070019import static com.google.auto.common.MoreElements.isAnnotationPresent;
20import static com.google.auto.common.MoreTypes.asExecutable;
dpbec434ad2016-09-08 13:24:00 -070021import static com.google.auto.common.MoreTypes.isType;
22import static com.google.auto.common.MoreTypes.isTypeOf;
gake55f0742016-07-12 15:36:42 -070023import static com.google.common.base.Preconditions.checkArgument;
24import static com.google.common.base.Preconditions.checkNotNull;
dpbec434ad2016-09-08 13:24:00 -070025import static com.google.common.collect.Iterables.getOnlyElement;
gake55f0742016-07-12 15:36:42 -070026import static dagger.internal.codegen.InjectionAnnotations.getQualifier;
27import static dagger.internal.codegen.MapKeys.getMapKey;
28import static dagger.internal.codegen.MapKeys.getUnwrappedMapKeyType;
29import static dagger.internal.codegen.MoreAnnotationMirrors.unwrapOptionalEquivalence;
30import static dagger.internal.codegen.MoreAnnotationMirrors.wrapOptionalInEquivalence;
dpbffd98f62016-12-20 10:05:16 -080031import static dagger.internal.codegen.Optionals.firstPresent;
32import static dagger.internal.codegen.Util.toImmutableSet;
gake55f0742016-07-12 15:36:42 -070033import static javax.lang.model.element.ElementKind.METHOD;
34
cgruber4fd5a462015-01-08 17:26:12 -080035import com.google.auto.common.AnnotationMirrors;
sameb2ea676a2015-01-15 10:20:24 -080036import com.google.auto.common.MoreElements;
Christian Edward Gruber02a32292014-07-18 18:19:02 -070037import com.google.auto.common.MoreTypes;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070038import com.google.auto.value.AutoValue;
David P. Baker1e718b82016-11-03 15:51:22 -040039import com.google.auto.value.extension.memoized.Memoized;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070040import com.google.common.base.Equivalence;
dpb90263a52016-07-13 07:52:41 -070041import com.google.common.base.Joiner;
ronshapirod804a302016-11-08 10:21:56 -080042import com.google.common.collect.ImmutableMap;
dpbffd98f62016-12-20 10:05:16 -080043import com.google.common.collect.ImmutableSet;
dpba2620422015-08-15 10:06:54 -070044import com.google.common.collect.ImmutableSetMultimap;
dpba2620422015-08-15 10:06:54 -070045import com.google.common.collect.Multimaps;
beder8fdbb9e2014-12-08 10:14:17 -080046import com.google.common.util.concurrent.ListenableFuture;
gak24b02282016-04-11 15:51:14 -070047import dagger.Binds;
dpbd8d950a2016-08-30 09:24:37 -070048import dagger.BindsOptionalOf;
dpb228475f2016-05-24 14:46:53 -070049import dagger.multibindings.Multibinds;
beder65834202015-09-30 08:49:44 -070050import dagger.producers.Produced;
bederca9c82b2015-01-23 18:30:22 -080051import dagger.producers.Producer;
gake1b68a22016-04-07 11:54:06 -070052import dagger.producers.Production;
beder893f7702016-02-17 05:22:50 -080053import dagger.producers.internal.ProductionImplementation;
gakb8dea082016-08-11 12:17:56 -070054import dagger.producers.monitoring.ProductionComponentMonitor;
ronshapirod804a302016-11-08 10:21:56 -080055import dagger.releasablereferences.ForReleasableReferences;
56import dagger.releasablereferences.ReleasableReferenceManager;
57import dagger.releasablereferences.TypedReleasableReferenceManager;
houcy3fc075f2014-07-29 16:51:27 -070058import java.util.Map;
dpbffd98f62016-12-20 10:05:16 -080059import java.util.Optional;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070060import java.util.Set;
beder893f7702016-02-17 05:22:50 -080061import java.util.concurrent.Executor;
dpbffd98f62016-12-20 10:05:16 -080062import java.util.stream.Stream;
houcy3fc075f2014-07-29 16:51:27 -070063import javax.inject.Provider;
dpbd8d950a2016-08-30 09:24:37 -070064import javax.inject.Qualifier;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070065import javax.lang.model.element.AnnotationMirror;
sameb2ea676a2015-01-15 10:20:24 -080066import javax.lang.model.element.ElementKind;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070067import javax.lang.model.element.ExecutableElement;
sameb2ea676a2015-01-15 10:20:24 -080068import javax.lang.model.element.Modifier;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070069import javax.lang.model.element.TypeElement;
70import javax.lang.model.type.DeclaredType;
sameb0d49be82015-01-22 17:29:48 -080071import javax.lang.model.type.ExecutableType;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070072import javax.lang.model.type.PrimitiveType;
73import javax.lang.model.type.TypeKind;
74import javax.lang.model.type.TypeMirror;
75import javax.lang.model.util.Elements;
gak3978af32014-08-19 14:38:40 -070076import javax.lang.model.util.SimpleTypeVisitor6;
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070077import javax.lang.model.util.Types;
gak3978af32014-08-19 14:38:40 -070078
Christian Edward Gruberc8e11072014-03-17 08:38:59 -070079/**
80 * Represents a unique combination of {@linkplain TypeMirror type} and
81 * {@linkplain Qualifier qualifier} to which binding can occur.
82 *
83 * @author Gregory Kick
84 */
85@AutoValue
86abstract class Key {
beder893f7702016-02-17 05:22:50 -080087
dpba2620422015-08-15 10:06:54 -070088 /** An object that is associated with a {@link Key}. */
89 interface HasKey {
90 /** The key associated with this object. */
91 Key key();
92 }
93
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -070094 /**
95 * A {@link javax.inject.Qualifier} annotation that provides a unique namespace prefix
96 * for the type of this key.
Christian Edward Gruber122f2122014-06-16 16:06:00 -070097 *
98 * Despite documentation in {@link AnnotationMirror}, equals and hashCode aren't implemented
cgruber815ccd12014-09-02 13:06:30 -070099 * to represent logical equality, so {@link AnnotationMirrors#equivalence()}
Christian Edward Gruber122f2122014-06-16 16:06:00 -0700100 * provides this facility.
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -0700101 */
Christian Edward Gruber122f2122014-06-16 16:06:00 -0700102 abstract Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedQualifier();
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700103
104 /**
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -0700105 * The type represented by this key.
106 *
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700107 * As documented in {@link TypeMirror}, equals and hashCode aren't implemented to represent
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -0700108 * logical equality, so {@link MoreTypes#equivalence()} wraps this type.
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700109 */
110 abstract Equivalence.Wrapper<TypeMirror> wrappedType();
beder893f7702016-02-17 05:22:50 -0800111
dpbdb240722016-01-25 14:06:41 -0800112 /**
dpb90263a52016-07-13 07:52:41 -0700113 * Distinguishes keys for multibinding contributions that share a {@link #type()} and {@link
114 * #qualifier()}.
dpb7edcd4d2016-06-21 07:52:39 -0700115 *
dpb90263a52016-07-13 07:52:41 -0700116 * <p>Each multibound map and set has a {@linkplain
dpb54203462016-10-19 13:46:43 -0700117 * ProvisionBinding.Factory#syntheticMultibinding(Key, Iterable) synthetic multibinding} that
118 * depends on the specific contributions to that map or set using keys that identify those
119 * multibinding contributions.
dpb90263a52016-07-13 07:52:41 -0700120 *
121 * <p>Absent except for multibinding contributions.
dpbdb240722016-01-25 14:06:41 -0800122 */
dpb90263a52016-07-13 07:52:41 -0700123 abstract Optional<MultibindingContributionIdentifier> multibindingContributionIdentifier();
ronshapirod804a302016-11-08 10:21:56 -0800124
dpbec434ad2016-09-08 13:24:00 -0700125 abstract Builder toBuilder();
126
David P. Baker1e718b82016-11-03 15:51:22 -0400127 @Memoized
128 @Override
129 public abstract int hashCode();
130
dpbec434ad2016-09-08 13:24:00 -0700131 static Builder builder(TypeMirror type) {
132 return new AutoValue_Key.Builder().type(type);
133 }
134
135 @AutoValue.Builder
136 abstract static class Builder {
137 abstract Builder wrappedType(Equivalence.Wrapper<TypeMirror> wrappedType);
138
139 Builder type(TypeMirror type) {
140 return wrappedType(MoreTypes.equivalence().wrap(checkNotNull(type)));
141 }
142
143 abstract Builder wrappedQualifier(
144 Optional<Equivalence.Wrapper<AnnotationMirror>> wrappedQualifier);
145
146 abstract Builder wrappedQualifier(Equivalence.Wrapper<AnnotationMirror> wrappedQualifier);
147
148 Builder qualifier(AnnotationMirror qualifier) {
149 return wrappedQualifier(AnnotationMirrors.equivalence().wrap(checkNotNull(qualifier)));
150 }
151
152 Builder qualifier(Optional<AnnotationMirror> qualifier) {
153 return wrappedQualifier(wrapOptionalInEquivalence(checkNotNull(qualifier)));
154 }
155
156 Builder qualifier(TypeElement annotationType) {
157 return qualifier(SimpleAnnotationMirror.of(annotationType));
158 }
159
160 abstract Builder multibindingContributionIdentifier(
161 Optional<MultibindingContributionIdentifier> identifier);
162
163 abstract Builder multibindingContributionIdentifier(
164 MultibindingContributionIdentifier identifier);
165
166 abstract Key build();
167 }
ronshapirod804a302016-11-08 10:21:56 -0800168
dpb90263a52016-07-13 07:52:41 -0700169 /**
170 * An object that identifies a multibinding contribution method and the module class that
171 * contributes it to the graph.
172 *
173 * @see Key#multibindingContributionIdentifier()
174 */
175 static final class MultibindingContributionIdentifier {
176 private final String identifierString;
dpb4955ef92016-04-29 12:31:14 -0700177
dpb90263a52016-07-13 07:52:41 -0700178 MultibindingContributionIdentifier(
179 ExecutableElement bindingMethod, TypeElement contributingModule) {
180 this.identifierString =
181 String.format(
182 "%s#%s", contributingModule.getQualifiedName(), bindingMethod.getSimpleName());
dpb7edcd4d2016-06-21 07:52:39 -0700183 }
dpb4955ef92016-04-29 12:31:14 -0700184
dpb90263a52016-07-13 07:52:41 -0700185 /**
186 * {@inheritDoc}
187 *
188 * <p>The returned string is human-readable and distinguishes the keys in the same way as the
189 * whole object.
190 */
191 @Override
192 public String toString() {
193 return identifierString;
194 }
195
196 @Override
197 public boolean equals(Object obj) {
198 return obj instanceof MultibindingContributionIdentifier
199 && ((MultibindingContributionIdentifier) obj)
200 .identifierString.equals(this.identifierString);
201 }
202
203 @Override
204 public int hashCode() {
205 return identifierString.hashCode();
dpb4955ef92016-04-29 12:31:14 -0700206 }
207 }
dpb7edcd4d2016-06-21 07:52:39 -0700208
dpbdb240722016-01-25 14:06:41 -0800209 /**
210 * A {@link javax.inject.Qualifier} annotation that provides a unique namespace prefix
211 * for the type of this key.
212 */
Christian Edward Gruber122f2122014-06-16 16:06:00 -0700213 Optional<AnnotationMirror> qualifier() {
cgruber4136f4d2014-10-28 10:59:26 -0700214 return unwrapOptionalEquivalence(wrappedQualifier());
Christian Edward Gruber122f2122014-06-16 16:06:00 -0700215 }
216
dpbdb240722016-01-25 14:06:41 -0800217 /**
218 * The type represented by this key.
219 */
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700220 TypeMirror type() {
221 return wrappedType().get();
222 }
223
dpbdb240722016-01-25 14:06:41 -0800224 /**
dpb90263a52016-07-13 07:52:41 -0700225 * A key whose {@link #qualifier()} and {@link #type()} are equivalent to this one's, but without
226 * a {@link #multibindingContributionIdentifier()}.
dpbdb240722016-01-25 14:06:41 -0800227 */
dpb90263a52016-07-13 07:52:41 -0700228 Key withoutMultibindingContributionIdentifier() {
dpbffd98f62016-12-20 10:05:16 -0800229 return toBuilder().multibindingContributionIdentifier(Optional.empty()).build();
sameb2ea676a2015-01-15 10:20:24 -0800230 }
231
gak3978af32014-08-19 14:38:40 -0700232 boolean isValidMembersInjectionKey() {
ronshapiro13eee292017-05-04 11:26:54 -0700233 return !qualifier().isPresent() && type().getKind().equals(TypeKind.DECLARED);
sameb2ea676a2015-01-15 10:20:24 -0800234 }
235
236 /**
dpbd8d950a2016-08-30 09:24:37 -0700237 * Returns {@code true} if this is valid as an implicit key (that is, if it's valid for a
238 * just-in-time binding by discovering an {@code @Inject} constructor).
sameb2ea676a2015-01-15 10:20:24 -0800239 */
dpbd8d950a2016-08-30 09:24:37 -0700240 boolean isValidImplicitProvisionKey(Types types) {
241 return isValidImplicitProvisionKey(qualifier(), type(), types);
242 }
243
244 /**
245 * Returns {@code true} if a key with {@code qualifier} and {@code type} is valid as an implicit
246 * key (that is, if it's valid for a just-in-time binding by discovering an {@code @Inject}
247 * constructor).
248 */
249 static boolean isValidImplicitProvisionKey(
250 Optional<? extends AnnotationMirror> qualifier, TypeMirror type, final Types types) {
sameb2ea676a2015-01-15 10:20:24 -0800251 // Qualifiers disqualify implicit provisioning.
dpbd8d950a2016-08-30 09:24:37 -0700252 if (qualifier.isPresent()) {
sameb2ea676a2015-01-15 10:20:24 -0800253 return false;
254 }
255
dpbd8d950a2016-08-30 09:24:37 -0700256 return type.accept(
257 new SimpleTypeVisitor6<Boolean, Void>(false) {
258 @Override
259 public Boolean visitDeclared(DeclaredType type, Void ignored) {
260 // Non-classes or abstract classes aren't allowed.
261 TypeElement element = MoreElements.asType(type.asElement());
262 if (!element.getKind().equals(ElementKind.CLASS)
263 || element.getModifiers().contains(Modifier.ABSTRACT)) {
264 return false;
265 }
sameb2ea676a2015-01-15 10:20:24 -0800266
dpbd8d950a2016-08-30 09:24:37 -0700267 // If the key has type arguments, validate that each type argument is declared.
268 // Otherwise the type argument may be a wildcard (or other type), and we can't
269 // resolve that to actual types.
270 for (TypeMirror arg : type.getTypeArguments()) {
271 if (arg.getKind() != TypeKind.DECLARED) {
272 return false;
273 }
274 }
sameb2ea676a2015-01-15 10:20:24 -0800275
dpbd8d950a2016-08-30 09:24:37 -0700276 // Also validate that the key is not the erasure of a generic type.
277 // If it is, that means the user referred to Foo<T> as just 'Foo',
278 // which we don't allow. (This is a judgement call -- we *could*
279 // allow it and instantiate the type bounds... but we don't.)
280 return MoreTypes.asDeclared(element.asType()).getTypeArguments().isEmpty()
281 || !types.isSameType(types.erasure(element.asType()), type);
gak3978af32014-08-19 14:38:40 -0700282 }
dpbd8d950a2016-08-30 09:24:37 -0700283 },
284 null);
gak3978af32014-08-19 14:38:40 -0700285 }
286
dpb90263a52016-07-13 07:52:41 -0700287 /**
288 * {@inheritDoc}
289 *
290 * <p>The returned string is equal to another key's if and only if this key is {@link
dpb54203462016-10-19 13:46:43 -0700291 * #equals(Object)} to it.
dpb90263a52016-07-13 07:52:41 -0700292 */
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700293 @Override
294 public String toString() {
dpb90263a52016-07-13 07:52:41 -0700295 return Joiner.on(' ')
296 .skipNulls()
dpbffd98f62016-12-20 10:05:16 -0800297 .join(qualifier().orElse(null), type(), multibindingContributionIdentifier().orElse(null));
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700298 }
299
dpbf8c5c7f2015-11-19 08:16:43 -0800300 /**
dpba2620422015-08-15 10:06:54 -0700301 * Indexes {@code haveKeys} by {@link HasKey#key()}.
302 */
303 static <T extends HasKey> ImmutableSetMultimap<Key, T> indexByKey(Iterable<T> haveKeys) {
gak66241102016-09-13 12:23:00 -0700304 return ImmutableSetMultimap.copyOf(Multimaps.index(haveKeys, HasKey::key));
dpba2620422015-08-15 10:06:54 -0700305 }
306
Christian Edward Gruber9daba782014-05-04 18:06:26 -0700307 static final class Factory {
308 private final Types types;
309 private final Elements elements;
ronshapirod804a302016-11-08 10:21:56 -0800310
dpb90263a52016-07-13 07:52:41 -0700311 Factory(Types types, Elements elements) {
Christian Edward Gruber9daba782014-05-04 18:06:26 -0700312 this.types = checkNotNull(types);
313 this.elements = checkNotNull(elements);
314 }
315
dpb800c7462016-09-08 09:11:47 -0700316 private TypeElement getClassElement(Class<?> cls) {
317 return elements.getTypeElement(cls.getCanonicalName());
318 }
319
dpbec434ad2016-09-08 13:24:00 -0700320 private TypeMirror boxPrimitives(TypeMirror type) {
321 return type.getKind().isPrimitive() ? types.boxedClass((PrimitiveType) type).asType() : type;
322 }
323
dpb7edcd4d2016-06-21 07:52:39 -0700324 private DeclaredType setOf(TypeMirror elementType) {
dpbec434ad2016-09-08 13:24:00 -0700325 return types.getDeclaredType(getClassElement(Set.class), boxPrimitives(elementType));
Christian Edward Gruber9daba782014-05-04 18:06:26 -0700326 }
327
dpb7edcd4d2016-06-21 07:52:39 -0700328 private DeclaredType mapOf(TypeMirror keyType, TypeMirror valueType) {
dpbec434ad2016-09-08 13:24:00 -0700329 return types.getDeclaredType(
330 getClassElement(Map.class), boxPrimitives(keyType), boxPrimitives(valueType));
331 }
332
333 /** Returns {@code Map<KeyType, FrameworkType<ValueType>>}. */
334 private TypeMirror mapOfFrameworkType(
335 TypeMirror keyType, TypeElement frameworkType, TypeMirror valueType) {
336 return mapOf(keyType, types.getDeclaredType(frameworkType, boxPrimitives(valueType)));
bederca9c82b2015-01-23 18:30:22 -0800337 }
338
ronshapirod804a302016-11-08 10:21:56 -0800339 private DeclaredType typedReleasableReferenceManagerOf(DeclaredType metadataType) {
340 return types.getDeclaredType(
341 getClassElement(TypedReleasableReferenceManager.class), metadataType);
342 }
343
Christian Edward Gruber14aafa62014-07-18 18:06:25 -0700344 Key forComponentMethod(ExecutableElement componentMethod) {
Christian Edward Gruber14aafa62014-07-18 18:06:25 -0700345 checkArgument(componentMethod.getKind().equals(METHOD));
dpbec434ad2016-09-08 13:24:00 -0700346 return forMethod(componentMethod, componentMethod.getReturnType());
Christian Edward Gruber14aafa62014-07-18 18:06:25 -0700347 }
348
bederca9c82b2015-01-23 18:30:22 -0800349 Key forProductionComponentMethod(ExecutableElement componentMethod) {
bederca9c82b2015-01-23 18:30:22 -0800350 checkArgument(componentMethod.getKind().equals(METHOD));
dpbec434ad2016-09-08 13:24:00 -0700351 TypeMirror returnType = componentMethod.getReturnType();
352 TypeMirror keyType =
353 isTypeOf(ListenableFuture.class, returnType)
354 ? getOnlyElement(MoreTypes.asDeclared(returnType).getTypeArguments())
355 : returnType;
dpb07489822015-07-06 10:34:40 -0700356 return forMethod(componentMethod, keyType);
bederca9c82b2015-01-23 18:30:22 -0800357 }
358
dpb99d64082015-11-12 11:27:12 -0800359 Key forSubcomponentBuilderMethod(
360 ExecutableElement subcomponentBuilderMethod, DeclaredType declaredContainer) {
dpb99d64082015-11-12 11:27:12 -0800361 checkArgument(subcomponentBuilderMethod.getKind().equals(METHOD));
362 ExecutableType resolvedMethod =
363 asExecutable(types.asMemberOf(declaredContainer, subcomponentBuilderMethod));
dpbec434ad2016-09-08 13:24:00 -0700364 return builder(resolvedMethod.getReturnType()).build();
dpb99d64082015-11-12 11:27:12 -0800365 }
366
ronshapirofbb68402016-08-31 06:44:45 -0700367 Key forSubcomponentBuilder(TypeMirror builderType) {
dpbec434ad2016-09-08 13:24:00 -0700368 return builder(builderType).build();
ronshapirofbb68402016-08-31 06:44:45 -0700369 }
370
dpb4955ef92016-04-29 12:31:14 -0700371 Key forProvidesMethod(ExecutableElement method, TypeElement contributingModule) {
dpb800c7462016-09-08 09:11:47 -0700372 return forBindingMethod(
373 method, contributingModule, Optional.of(getClassElement(Provider.class)));
Christian Edward Gruber9daba782014-05-04 18:06:26 -0700374 }
375
dpb4955ef92016-04-29 12:31:14 -0700376 Key forProducesMethod(ExecutableElement method, TypeElement contributingModule) {
dpb800c7462016-09-08 09:11:47 -0700377 return forBindingMethod(
378 method, contributingModule, Optional.of(getClassElement(Producer.class)));
ronshapiro665a4a52016-04-12 21:10:00 -0700379 }
380
dpbd8d950a2016-08-30 09:24:37 -0700381 /** Returns the key bound by a {@link Binds} method. */
382 Key forBindsMethod(ExecutableElement method, TypeElement contributingModule) {
383 checkArgument(isAnnotationPresent(method, Binds.class));
dpbffd98f62016-12-20 10:05:16 -0800384 return forBindingMethod(method, contributingModule, Optional.empty());
dpbd8d950a2016-08-30 09:24:37 -0700385 }
386
387 /** Returns the base key bound by a {@link BindsOptionalOf} method. */
388 Key forBindsOptionalOfMethod(ExecutableElement method, TypeElement contributingModule) {
389 checkArgument(isAnnotationPresent(method, BindsOptionalOf.class));
dpbffd98f62016-12-20 10:05:16 -0800390 return forBindingMethod(method, contributingModule, Optional.empty());
dpbd8d950a2016-08-30 09:24:37 -0700391 }
392
393 private Key forBindingMethod(
394 ExecutableElement method,
395 TypeElement contributingModule,
396 Optional<TypeElement> frameworkType) {
dpb4955ef92016-04-29 12:31:14 -0700397 checkArgument(method.getKind().equals(METHOD));
dpbdb240722016-01-25 14:06:41 -0800398 ExecutableType methodType =
dpb4955ef92016-04-29 12:31:14 -0700399 MoreTypes.asExecutable(
400 types.asMemberOf(MoreTypes.asDeclared(contributingModule.asType()), method));
ronshapiro665a4a52016-04-12 21:10:00 -0700401 ContributionType contributionType = ContributionType.fromBindingMethod(method);
dpbec434ad2016-09-08 13:24:00 -0700402 TypeMirror returnType = methodType.getReturnType();
dpbd8d950a2016-08-30 09:24:37 -0700403 if (frameworkType.isPresent()
dpb800c7462016-09-08 09:11:47 -0700404 && frameworkType.get().equals(getClassElement(Producer.class))
Ron Shapiro5f21a802016-09-21 10:23:55 -0400405 && isType(returnType)) {
406 if (isTypeOf(ListenableFuture.class, returnType)) {
407 returnType = getOnlyElement(MoreTypes.asDeclared(returnType).getTypeArguments());
408 } else if (contributionType.equals(ContributionType.SET_VALUES)
409 && SetType.isSet(returnType)) {
410 SetType setType = SetType.from(returnType);
411 if (setType.elementsAreTypeOf(ListenableFuture.class)) {
412 returnType =
413 types.getDeclaredType(
414 getClassElement(Set.class),
415 setType.unwrappedElementType(ListenableFuture.class));
416 }
417 }
beder8fdbb9e2014-12-08 10:14:17 -0800418 }
dpb07489822015-07-06 10:34:40 -0700419 TypeMirror keyType =
dpbd8d950a2016-08-30 09:24:37 -0700420 bindingMethodKeyType(returnType, method, contributionType, frameworkType);
dpbdb240722016-01-25 14:06:41 -0800421 Key key = forMethod(method, keyType);
ronshapiro665a4a52016-04-12 21:10:00 -0700422 return contributionType.equals(ContributionType.UNIQUE)
dpbdb240722016-01-25 14:06:41 -0800423 ? key
dpbec434ad2016-09-08 13:24:00 -0700424 : key.toBuilder()
425 .multibindingContributionIdentifier(
426 new MultibindingContributionIdentifier(method, contributingModule))
427 .build();
dpb07489822015-07-06 10:34:40 -0700428 }
beder893f7702016-02-17 05:22:50 -0800429
dpb51bf8b42015-12-18 09:59:56 -0800430 /**
ronshapiro6d853882017-03-16 16:37:02 -0700431 * Returns the key for a {@link Multibinds @Multibinds} method.
dpb51bf8b42015-12-18 09:59:56 -0800432 *
ronshapiro23c17b82016-06-10 09:57:13 -0700433 * <p>The key's type is either {@code Set<T>} or {@code Map<K, F<V>>}, where {@code F} is either
dpb51bf8b42015-12-18 09:59:56 -0800434 * {@link Provider} or {@link Producer}, depending on {@code bindingType}.
435 */
dpb228475f2016-05-24 14:46:53 -0700436 Key forMultibindsMethod(
dpb51bf8b42015-12-18 09:59:56 -0800437 BindingType bindingType, ExecutableType executableType, ExecutableElement method) {
438 checkArgument(method.getKind().equals(METHOD), "%s must be a method", method);
439 TypeElement factoryType =
440 elements.getTypeElement(bindingType.frameworkClass().getCanonicalName());
dpbec434ad2016-09-08 13:24:00 -0700441 TypeMirror returnType = executableType.getReturnType();
dpb51bf8b42015-12-18 09:59:56 -0800442 TypeMirror keyType =
443 MapType.isMap(returnType)
444 ? mapOfFrameworkType(
445 MapType.from(returnType).keyType(),
446 factoryType,
447 MapType.from(returnType).valueType())
448 : returnType;
449 return forMethod(method, keyType);
450 }
dpb07489822015-07-06 10:34:40 -0700451
ronshapiro846fd942016-06-01 11:50:01 -0700452 private TypeMirror bindingMethodKeyType(
dpb07489822015-07-06 10:34:40 -0700453 TypeMirror returnType,
454 ExecutableElement method,
ronshapiro665a4a52016-04-12 21:10:00 -0700455 ContributionType contributionType,
ronshapiro23c17b82016-06-10 09:57:13 -0700456 Optional<TypeElement> frameworkType) {
ronshapiro665a4a52016-04-12 21:10:00 -0700457 switch (contributionType) {
beder8fdbb9e2014-12-08 10:14:17 -0800458 case UNIQUE:
dpb07489822015-07-06 10:34:40 -0700459 return returnType;
beder8fdbb9e2014-12-08 10:14:17 -0800460 case SET:
dpb7edcd4d2016-06-21 07:52:39 -0700461 return setOf(returnType);
beder8fdbb9e2014-12-08 10:14:17 -0800462 case MAP:
ronshapiro23c17b82016-06-10 09:57:13 -0700463 if (frameworkType.isPresent()) {
464 return mapOfFrameworkType(mapKeyType(method), frameworkType.get(), returnType);
465 } else {
dpb7edcd4d2016-06-21 07:52:39 -0700466 return mapOf(mapKeyType(method), returnType);
ronshapiro23c17b82016-06-10 09:57:13 -0700467 }
beder8fdbb9e2014-12-08 10:14:17 -0800468 case SET_VALUES:
469 // TODO(gak): do we want to allow people to use "covariant return" here?
ronshapiro665a4a52016-04-12 21:10:00 -0700470 checkArgument(SetType.isSet(returnType));
dpb07489822015-07-06 10:34:40 -0700471 return returnType;
beder8fdbb9e2014-12-08 10:14:17 -0800472 default:
473 throw new AssertionError();
474 }
475 }
476
dpba2620422015-08-15 10:06:54 -0700477 /**
ronshapiro23c17b82016-06-10 09:57:13 -0700478 * Returns the key for a binding associated with a {@link DelegateDeclaration}.
479 *
480 * If {@code delegateDeclaration} is {@code @IntoMap}, transforms the {@code Map<K, V>} key
481 * from {@link DelegateDeclaration#key()} to {@code Map<K, FrameworkType<V>>}. If {@code
482 * delegateDeclaration} is not a map contribution, its key is returned.
483 */
484 Key forDelegateBinding(
485 DelegateDeclaration delegateDeclaration, Class<?> frameworkType) {
486 return delegateDeclaration.contributionType().equals(ContributionType.MAP)
487 ? wrapMapValue(delegateDeclaration.key(), frameworkType)
488 : delegateDeclaration.key();
489 }
490
dpb07489822015-07-06 10:34:40 -0700491 private TypeMirror mapKeyType(ExecutableElement method) {
dpba57e3872015-07-15 09:40:55 -0700492 AnnotationMirror mapKeyAnnotation = getMapKey(method).get();
dpb482cbd42015-08-07 08:17:31 -0700493 return MapKeys.unwrapValue(mapKeyAnnotation).isPresent()
dpb07489822015-07-06 10:34:40 -0700494 ? getUnwrappedMapKeyType(mapKeyAnnotation.getAnnotationType(), types)
495 : mapKeyAnnotation.getAnnotationType();
496 }
497
498 private Key forMethod(ExecutableElement method, TypeMirror keyType) {
dpbec434ad2016-09-08 13:24:00 -0700499 return forQualifiedType(getQualifier(method), keyType);
dpb07489822015-07-06 10:34:40 -0700500 }
501
sameb2ea676a2015-01-15 10:20:24 -0800502 Key forInjectConstructorWithResolvedType(TypeMirror type) {
dpbec434ad2016-09-08 13:24:00 -0700503 return builder(type).build();
Christian Edward Gruber9daba782014-05-04 18:06:26 -0700504 }
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -0700505
ronshapirodc07ed52017-08-23 08:52:10 -0700506 // TODO(ronshapiro): Remove these conveniences which are simple wrappers around Key.Builder
507 Key forType(TypeMirror type) {
dpbec434ad2016-09-08 13:24:00 -0700508 return builder(type).build();
gakad6b5e52014-09-03 09:38:09 -0700509 }
510
511 Key forMembersInjectedType(TypeMirror type) {
dpbec434ad2016-09-08 13:24:00 -0700512 return builder(type).build();
Christian Edward Gruber6a66a5b2014-06-12 21:10:17 -0700513 }
514
515 Key forQualifiedType(Optional<AnnotationMirror> qualifier, TypeMirror type) {
dpbec434ad2016-09-08 13:24:00 -0700516 return builder(boxPrimitives(type)).qualifier(qualifier).build();
Christian Edward Gruber122f2122014-06-16 16:06:00 -0700517 }
518
beder893f7702016-02-17 05:22:50 -0800519 Key forProductionExecutor() {
dpbec434ad2016-09-08 13:24:00 -0700520 return builder(getClassElement(Executor.class).asType())
521 .qualifier(getClassElement(Production.class))
522 .build();
beder893f7702016-02-17 05:22:50 -0800523 }
524
525 Key forProductionImplementationExecutor() {
dpbec434ad2016-09-08 13:24:00 -0700526 return builder(getClassElement(Executor.class).asType())
527 .qualifier(getClassElement(ProductionImplementation.class))
528 .build();
beder893f7702016-02-17 05:22:50 -0800529 }
530
gakb8dea082016-08-11 12:17:56 -0700531 Key forProductionComponentMonitor() {
dpbec434ad2016-09-08 13:24:00 -0700532 return builder(getClassElement(ProductionComponentMonitor.class).asType()).build();
gakb8dea082016-08-11 12:17:56 -0700533 }
534
cgruber815ccd12014-09-02 13:06:30 -0700535 /**
dpb1da29992016-06-24 07:54:52 -0700536 * If {@code requestKey} is for a {@code Map<K, V>} or {@code Map<K, Produced<V>>}, returns keys
537 * for {@code Map<K, Provider<V>>} and {@code Map<K, Producer<V>>} (if Dagger-Producers is on
538 * the classpath).
539 */
dpbffd98f62016-12-20 10:05:16 -0800540 ImmutableSet<Key> implicitFrameworkMapKeys(Key requestKey) {
541 return Stream.of(
542 implicitMapProviderKeyFrom(requestKey), implicitMapProducerKeyFrom(requestKey))
543 .filter(Optional::isPresent)
544 .map(Optional::get)
545 .collect(toImmutableSet());
dpb1da29992016-06-24 07:54:52 -0700546 }
547
548 /**
cgruber815ccd12014-09-02 13:06:30 -0700549 * Optionally extract a {@link Key} for the underlying provision binding(s) if such a
gakad6b5e52014-09-03 09:38:09 -0700550 * valid key can be inferred from the given key. Specifically, if the key represents a
cgruber815ccd12014-09-02 13:06:30 -0700551 * {@link Map}{@code <K, V>}, a key of {@code Map<K, Provider<V>>} will be returned.
552 */
553 Optional<Key> implicitMapProviderKeyFrom(Key possibleMapKey) {
dpb1da29992016-06-24 07:54:52 -0700554 return wrapMapKey(possibleMapKey, Provider.class);
bederca9c82b2015-01-23 18:30:22 -0800555 }
556
557 /**
558 * Optionally extract a {@link Key} for the underlying production binding(s) if such a
559 * valid key can be inferred from the given key. Specifically, if the key represents a
bederc2aea2b2016-01-19 12:13:37 -0800560 * {@link Map}{@code <K, V>} or {@code Map<K, Produced<V>>}, a key of
561 * {@code Map<K, Producer<V>>} will be returned.
bederca9c82b2015-01-23 18:30:22 -0800562 */
563 Optional<Key> implicitMapProducerKeyFrom(Key possibleMapKey) {
dpbffd98f62016-12-20 10:05:16 -0800564 return firstPresent(
565 rewrapMapKey(possibleMapKey, Produced.class, Producer.class),
566 wrapMapKey(possibleMapKey, Producer.class));
bederc2aea2b2016-01-19 12:13:37 -0800567 }
568
569 /**
ronshapiro23c17b82016-06-10 09:57:13 -0700570 * Keys for map contributions from {@link dagger.Provides} and {@link dagger.producers.Produces}
571 * are in the form {@code Map<K, Framework<V>>}, but keys for {@link Binds} methods are just
572 * {@code Map<K, V>} since the framework type is not known until graph resolution. This
573 * translates from the {@code @Provides}/{@code @Produces} format into the {@code @Binds}
574 * format. If {@link Key#type() possibleMapKey.type()} is not a {@code Map<K, Framework<V>>},
575 * returns {@code possibleMapKey}.
576 */
577 Key convertToDelegateKey(Key possibleMapKey) {
578 if (!MapType.isMap(possibleMapKey)) {
579 return possibleMapKey;
580 }
581 MapType mapType = MapType.from(possibleMapKey);
582 TypeMirror wrappedValueType;
583 if (mapType.valuesAreTypeOf(Provider.class)) {
584 wrappedValueType = mapType.unwrappedValueType(Provider.class);
585 } else if (mapType.valuesAreTypeOf(Producer.class)) {
586 wrappedValueType = mapType.unwrappedValueType(Producer.class);
587 } else {
588 return possibleMapKey;
589 }
dpbec434ad2016-09-08 13:24:00 -0700590 return possibleMapKey.toBuilder().type(mapOf(mapType.keyType(), wrappedValueType)).build();
ronshapiro23c17b82016-06-10 09:57:13 -0700591 }
592
593 /**
594 * Converts a {@link Key} of type {@code Map<K, V>} to {@code Map<K, Provider<V>>}.
595 */
596 private Key wrapMapValue(Key key, Class<?> newWrappingClass) {
597 checkArgument(
598 FrameworkTypes.isFrameworkType(
599 elements.getTypeElement(newWrappingClass.getName()).asType()));
dpb1da29992016-06-24 07:54:52 -0700600 return wrapMapKey(key, newWrappingClass).get();
ronshapiro23c17b82016-06-10 09:57:13 -0700601 }
602
603 /**
dpb1da29992016-06-24 07:54:52 -0700604 * If {@code key}'s type is {@code Map<K, CurrentWrappingClass<Bar>>}, returns a key with type
605 * {@code Map<K, NewWrappingClass<Bar>>} with the same qualifier. Otherwise returns {@link
dpbffd98f62016-12-20 10:05:16 -0800606 * Optional#empty()}.
dpb1da29992016-06-24 07:54:52 -0700607 *
dpbffd98f62016-12-20 10:05:16 -0800608 * <p>Returns {@link Optional#empty()} if {@code newWrappingClass} is not in the classpath.
dpb1da29992016-06-24 07:54:52 -0700609 *
610 * @throws IllegalArgumentException if {@code newWrappingClass} is the same as {@code
611 * currentWrappingClass}
bederc2aea2b2016-01-19 12:13:37 -0800612 */
dpb1da29992016-06-24 07:54:52 -0700613 Optional<Key> rewrapMapKey(
bederc2aea2b2016-01-19 12:13:37 -0800614 Key possibleMapKey, Class<?> currentWrappingClass, Class<?> newWrappingClass) {
615 checkArgument(!currentWrappingClass.equals(newWrappingClass));
ronshapiro698653f2016-06-03 09:14:13 -0700616 if (MapType.isMap(possibleMapKey)) {
617 MapType mapType = MapType.from(possibleMapKey);
bederc2aea2b2016-01-19 12:13:37 -0800618 if (mapType.valuesAreTypeOf(currentWrappingClass)) {
619 TypeElement wrappingElement = getClassElement(newWrappingClass);
620 if (wrappingElement == null) {
621 // This target might not be compiled with Producers, so wrappingClass might not have an
622 // associated element.
dpbffd98f62016-12-20 10:05:16 -0800623 return Optional.empty();
bederc2aea2b2016-01-19 12:13:37 -0800624 }
625 DeclaredType wrappedValueType =
626 types.getDeclaredType(
627 wrappingElement, mapType.unwrappedValueType(currentWrappingClass));
dpb7edcd4d2016-06-21 07:52:39 -0700628 return Optional.of(
dpbec434ad2016-09-08 13:24:00 -0700629 possibleMapKey.toBuilder().type(mapOf(mapType.keyType(), wrappedValueType)).build());
bederc2aea2b2016-01-19 12:13:37 -0800630 }
631 }
dpbffd98f62016-12-20 10:05:16 -0800632 return Optional.empty();
bederca9c82b2015-01-23 18:30:22 -0800633 }
634
635 /**
dpb1da29992016-06-24 07:54:52 -0700636 * If {@code key}'s type is {@code Map<K, Foo>} and {@code Foo} is not {@code WrappingClass
637 * <Bar>}, returns a key with type {@code Map<K, WrappingClass<Foo>>} with the same qualifier.
dpbffd98f62016-12-20 10:05:16 -0800638 * Otherwise returns {@link Optional#empty()}.
dpb1da29992016-06-24 07:54:52 -0700639 *
dpbffd98f62016-12-20 10:05:16 -0800640 * <p>Returns {@link Optional#empty()} if {@code WrappingClass} is not in the classpath.
bederca9c82b2015-01-23 18:30:22 -0800641 */
dpb1da29992016-06-24 07:54:52 -0700642 private Optional<Key> wrapMapKey(Key possibleMapKey, Class<?> wrappingClass) {
ronshapiro698653f2016-06-03 09:14:13 -0700643 if (MapType.isMap(possibleMapKey)) {
644 MapType mapType = MapType.from(possibleMapKey);
dpbf8c5c7f2015-11-19 08:16:43 -0800645 if (!mapType.valuesAreTypeOf(wrappingClass)) {
beder69667a22015-01-24 09:07:31 -0800646 TypeElement wrappingElement = getClassElement(wrappingClass);
647 if (wrappingElement == null) {
648 // This target might not be compiled with Producers, so wrappingClass might not have an
649 // associated element.
dpbffd98f62016-12-20 10:05:16 -0800650 return Optional.empty();
beder69667a22015-01-24 09:07:31 -0800651 }
dpbf8c5c7f2015-11-19 08:16:43 -0800652 DeclaredType wrappedValueType =
653 types.getDeclaredType(wrappingElement, mapType.valueType());
dpb7edcd4d2016-06-21 07:52:39 -0700654 return Optional.of(
dpbec434ad2016-09-08 13:24:00 -0700655 possibleMapKey.toBuilder().type(mapOf(mapType.keyType(), wrappedValueType)).build());
cgruber815ccd12014-09-02 13:06:30 -0700656 }
657 }
dpbffd98f62016-12-20 10:05:16 -0800658 return Optional.empty();
cgruber815ccd12014-09-02 13:06:30 -0700659 }
beder65834202015-09-30 08:49:44 -0700660
661 /**
dpb1da29992016-06-24 07:54:52 -0700662 * If {@code key}'s type is {@code Set<WrappingClass<Bar>>}, returns a key with type {@code Set
dpbffd98f62016-12-20 10:05:16 -0800663 * <Bar>} with the same qualifier. Otherwise returns {@link Optional#empty()}.
beder65834202015-09-30 08:49:44 -0700664 */
dpb1da29992016-06-24 07:54:52 -0700665 Optional<Key> unwrapSetKey(Key key, Class<?> wrappingClass) {
666 if (SetType.isSet(key)) {
667 SetType setType = SetType.from(key);
668 if (setType.elementsAreTypeOf(wrappingClass)) {
669 return Optional.of(
dpbec434ad2016-09-08 13:24:00 -0700670 key.toBuilder().type(setOf(setType.unwrappedElementType(wrappingClass))).build());
beder65834202015-09-30 08:49:44 -0700671 }
672 }
dpbffd98f62016-12-20 10:05:16 -0800673 return Optional.empty();
beder65834202015-09-30 08:49:44 -0700674 }
dpbd8d950a2016-08-30 09:24:37 -0700675
676 /**
677 * If {@code key}'s type is {@code Optional<T>} for some {@code T}, returns a key with the same
678 * qualifier whose type is {@linkplain DependencyRequest#extractKindAndType(TypeMirror)
679 * extracted} from {@code T}.
680 */
681 Optional<Key> unwrapOptional(Key key) {
682 if (!OptionalType.isOptional(key)) {
dpbffd98f62016-12-20 10:05:16 -0800683 return Optional.empty();
dpbd8d950a2016-08-30 09:24:37 -0700684 }
685 TypeMirror underlyingType =
686 DependencyRequest.extractKindAndType(OptionalType.from(key).valueType()).type();
dpbec434ad2016-09-08 13:24:00 -0700687 return Optional.of(key.toBuilder().type(underlyingType).build());
dpbd8d950a2016-08-30 09:24:37 -0700688 }
ronshapirod804a302016-11-08 10:21:56 -0800689
690 /** Returns a key for a {@code @ForReleasableReferences(scope) ReleasableReferenceManager}. */
691 Key forReleasableReferenceManager(Scope scope) {
692 return forQualifiedType(
693 Optional.of(forReleasableReferencesAnnotationMirror(scope)),
694 getClassElement(ReleasableReferenceManager.class).asType());
695 }
696
697 /**
698 * Returns a key for a {@code @ForReleasableReferences(scope)
699 * TypedReleasableReferenceManager<metadataType>}
700 */
701 Key forTypedReleasableReferenceManager(Scope scope, DeclaredType metadataType) {
702 return builder(typedReleasableReferenceManagerOf(metadataType))
703 .qualifier(forReleasableReferencesAnnotationMirror(scope))
704 .build();
705 }
706
707 /** Returns a key for a {@code Set<ReleasableReferenceManager>}. */
708 Key forSetOfReleasableReferenceManagers() {
709 return builder(setOf(getClassElement(ReleasableReferenceManager.class).asType())).build();
710 }
711
712 /** Returns a key for a {@code Set<TypedReleasableReferenceManager<metadataType>}. */
713 Key forSetOfTypedReleasableReferenceManagers(DeclaredType metadataType) {
714 return forQualifiedType(
dpbffd98f62016-12-20 10:05:16 -0800715 Optional.empty(), setOf(typedReleasableReferenceManagerOf(metadataType)));
ronshapirod804a302016-11-08 10:21:56 -0800716 }
717
718 private AnnotationMirror forReleasableReferencesAnnotationMirror(Scope scope) {
719 return SimpleAnnotationMirror.of(
720 getClassElement(ForReleasableReferences.class),
721 ImmutableMap.of(
722 "value", new SimpleTypeAnnotationValue(scope.scopeAnnotationElement().asType())));
723 }
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700724 }
Christian Edward Gruberc8e11072014-03-17 08:38:59 -0700725}