| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 1 | /* |
| ronshapiro | 5dde42d | 2016-06-17 09:03:35 -0700 | [diff] [blame] | 2 | * Copyright (C) 2014 The Dagger Authors. |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 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 | */ |
| dpb | 1b65b6a | 2016-07-11 12:11:24 -0700 | [diff] [blame] | 16 | |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 17 | package dagger.internal.codegen; |
| 18 | |
| gak | e55f074 | 2016-07-12 15:36:42 -0700 | [diff] [blame] | 19 | import static com.google.auto.common.MoreElements.isAnnotationPresent; |
| 20 | import static com.google.auto.common.MoreTypes.asDeclared; |
| 21 | import static com.google.common.base.Preconditions.checkArgument; |
| 22 | import static com.google.common.base.Preconditions.checkNotNull; |
| 23 | import static com.google.common.base.Preconditions.checkState; |
| 24 | import static dagger.internal.codegen.InjectionAnnotations.getQualifier; |
| 25 | import static dagger.internal.codegen.MapKeys.getMapKey; |
| 26 | import static dagger.internal.codegen.MoreAnnotationMirrors.wrapOptionalInEquivalence; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 27 | import static dagger.internal.codegen.Util.toImmutableSet; |
| gak | e55f074 | 2016-07-12 15:36:42 -0700 | [diff] [blame] | 28 | import static javax.lang.model.element.ElementKind.CONSTRUCTOR; |
| gak | e55f074 | 2016-07-12 15:36:42 -0700 | [diff] [blame] | 29 | import static javax.lang.model.element.ElementKind.METHOD; |
| 30 | |
| Christian Edward Gruber | 6a66a5b | 2014-06-12 21:10:17 -0700 | [diff] [blame] | 31 | import com.google.auto.common.MoreElements; |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 32 | import com.google.auto.common.MoreTypes; |
| Christian Edward Gruber | 6a66a5b | 2014-06-12 21:10:17 -0700 | [diff] [blame] | 33 | import com.google.auto.value.AutoValue; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 34 | import com.google.auto.value.extension.memoized.Memoized; |
| Christian Edward Gruber | 6a66a5b | 2014-06-12 21:10:17 -0700 | [diff] [blame] | 35 | import com.google.common.collect.ImmutableSet; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 36 | import com.google.common.collect.ImmutableSortedSet; |
| beder | b50b8ae | 2016-12-07 08:36:26 -0800 | [diff] [blame] | 37 | import com.google.common.collect.Iterables; |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 38 | import com.google.errorprone.annotations.CanIgnoreReturnValue; |
| beder | b50b8ae | 2016-12-07 08:36:26 -0800 | [diff] [blame] | 39 | import dagger.internal.codegen.ComponentDescriptor.BuilderRequirementMethod; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 40 | import dagger.internal.codegen.MembersInjectionBinding.InjectionSite; |
| dpb | ffd98f6 | 2016-12-20 10:05:16 -0800 | [diff] [blame] | 41 | import java.util.Optional; |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 42 | import javax.annotation.CheckReturnValue; |
| Christian Edward Gruber | 6a66a5b | 2014-06-12 21:10:17 -0700 | [diff] [blame] | 43 | import javax.inject.Inject; |
| ronshapiro | 23c17b8 | 2016-06-10 09:57:13 -0700 | [diff] [blame] | 44 | import javax.inject.Provider; |
| Christian Edward Gruber | 6a66a5b | 2014-06-12 21:10:17 -0700 | [diff] [blame] | 45 | import javax.lang.model.element.Element; |
| Christian Edward Gruber | 6a66a5b | 2014-06-12 21:10:17 -0700 | [diff] [blame] | 46 | import javax.lang.model.element.ExecutableElement; |
| 47 | import javax.lang.model.element.TypeElement; |
| beder | b50b8ae | 2016-12-07 08:36:26 -0800 | [diff] [blame] | 48 | import javax.lang.model.element.VariableElement; |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 49 | import javax.lang.model.type.DeclaredType; |
| 50 | import javax.lang.model.type.ExecutableType; |
| 51 | import javax.lang.model.type.TypeMirror; |
| Christian Edward Gruber | 6a66a5b | 2014-06-12 21:10:17 -0700 | [diff] [blame] | 52 | import javax.lang.model.util.Types; |
| 53 | |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 54 | /** |
| 55 | * A value object representing the mechanism by which a {@link Key} can be provided. New instances |
| 56 | * should be created using an instance of the {@link Factory}. |
| 57 | * |
| 58 | * @author Gregory Kick |
| 59 | * @since 2.0 |
| 60 | */ |
| 61 | @AutoValue |
| beder | ca9c82b | 2015-01-23 18:30:22 -0800 | [diff] [blame] | 62 | abstract class ProvisionBinding extends ContributionBinding { |
| dpb | 5719880 | 2015-12-17 12:18:15 -0800 | [diff] [blame] | 63 | |
| gak | 09075bc | 2014-07-31 11:02:39 -0700 | [diff] [blame] | 64 | @Override |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 65 | @Memoized |
| 66 | ImmutableSet<DependencyRequest> explicitDependencies() { |
| 67 | return ImmutableSet.<DependencyRequest>builder() |
| 68 | .addAll(provisionDependencies()) |
| 69 | .addAll(membersInjectionDependencies()) |
| 70 | .build(); |
| gak | 6fc2b5a | 2016-08-10 11:32:20 -0700 | [diff] [blame] | 71 | } |
| 72 | |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 73 | /** |
| 74 | * Dependencies necessary to invoke an {@code @Inject} constructor or {@code @Provides} method. |
| 75 | */ |
| 76 | abstract ImmutableSet<DependencyRequest> provisionDependencies(); |
| 77 | |
| 78 | @Memoized |
| 79 | ImmutableSet<DependencyRequest> membersInjectionDependencies() { |
| 80 | return injectionSites() |
| 81 | .stream() |
| 82 | .flatMap(i -> i.dependencies().stream()) |
| 83 | .collect(toImmutableSet()); |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * {@link InjectionSite}s for all {@code @Inject} members if {@link #bindingKind()} is {@link |
| 88 | * ContributionBinding.Kind#INJECTION}, otherwise empty. |
| 89 | */ |
| 90 | abstract ImmutableSortedSet<InjectionSite> injectionSites(); |
| gak | 6fc2b5a | 2016-08-10 11:32:20 -0700 | [diff] [blame] | 91 | |
| 92 | @Override |
| dpb | a262042 | 2015-08-15 10:06:54 -0700 | [diff] [blame] | 93 | public BindingType bindingType() { |
| 94 | return BindingType.PROVISION; |
| gak | 09075bc | 2014-07-31 11:02:39 -0700 | [diff] [blame] | 95 | } |
| dpb | 5719880 | 2015-12-17 12:18:15 -0800 | [diff] [blame] | 96 | |
| 97 | @Override |
| 98 | abstract Optional<ProvisionBinding> unresolved(); |
| 99 | |
| dpb | 6bd55de | 2015-09-28 07:58:09 -0700 | [diff] [blame] | 100 | @Override |
| beder | 3bdf32d | 2016-02-16 11:37:07 -0800 | [diff] [blame] | 101 | abstract Optional<Scope> scope(); |
| gak | e1b68a2 | 2016-04-07 11:54:06 -0700 | [diff] [blame] | 102 | |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 103 | private static Builder builder() { |
| 104 | return new AutoValue_ProvisionBinding.Builder() |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 105 | .provisionDependencies(ImmutableSet.of()) |
| 106 | .injectionSites(ImmutableSortedSet.of()); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 107 | } |
| ronshapiro | d804a30 | 2016-11-08 10:21:56 -0800 | [diff] [blame] | 108 | |
| dpb | d8d950a | 2016-08-30 09:24:37 -0700 | [diff] [blame] | 109 | abstract Builder toBuilder(); |
| 110 | |
| ronshapiro | 1c891fb | 2017-07-09 11:53:51 -0400 | [diff] [blame] | 111 | boolean shouldCheckForNull(CompilerOptions compilerOptions) { |
| 112 | return !providesPrimitiveType() |
| 113 | && !nullableType().isPresent() |
| 114 | && compilerOptions.doCheckForNulls(); |
| 115 | } |
| 116 | |
| 117 | private boolean providesPrimitiveType() { |
| 118 | return bindingElement().isPresent() |
| 119 | && MoreElements.asExecutable(bindingElement().get()) |
| 120 | .getReturnType() |
| 121 | .getKind() |
| 122 | .isPrimitive(); |
| 123 | } |
| 124 | |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 125 | @AutoValue.Builder |
| 126 | @CanIgnoreReturnValue |
| 127 | abstract static class Builder extends ContributionBinding.Builder<Builder> { |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 128 | abstract Builder provisionDependencies(DependencyRequest... provisionDependencies); |
| 129 | abstract Builder provisionDependencies(ImmutableSet<DependencyRequest> provisionDependencies); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 130 | |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 131 | abstract Builder injectionSites(ImmutableSortedSet<InjectionSite> injectionSites); |
| gak | 6fc2b5a | 2016-08-10 11:32:20 -0700 | [diff] [blame] | 132 | |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 133 | abstract Builder unresolved(ProvisionBinding unresolved); |
| 134 | |
| 135 | abstract Builder scope(Optional<Scope> scope); |
| 136 | |
| 137 | @CheckReturnValue |
| 138 | abstract ProvisionBinding build(); |
| 139 | } |
| 140 | |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 141 | static final class Factory { |
| Gregory Kick | 281cf48 | 2014-06-12 19:51:41 -0700 | [diff] [blame] | 142 | private final Types types; |
| Christian Edward Gruber | 9daba78 | 2014-05-04 18:06:26 -0700 | [diff] [blame] | 143 | private final Key.Factory keyFactory; |
| Christian Edward Gruber | 4aec5ba | 2014-05-20 19:37:11 -0700 | [diff] [blame] | 144 | private final DependencyRequest.Factory dependencyRequestFactory; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 145 | private final MembersInjectionBinding.Factory membersInjectionBindingFactory; |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 146 | |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 147 | Factory( |
| 148 | Types types, |
| 149 | Key.Factory keyFactory, |
| 150 | DependencyRequest.Factory dependencyRequestFactory, |
| 151 | MembersInjectionBinding.Factory membersInjectionBindingFactory) { |
| Gregory Kick | 281cf48 | 2014-06-12 19:51:41 -0700 | [diff] [blame] | 152 | this.types = types; |
| Christian Edward Gruber | 9daba78 | 2014-05-04 18:06:26 -0700 | [diff] [blame] | 153 | this.keyFactory = keyFactory; |
| Christian Edward Gruber | 4aec5ba | 2014-05-20 19:37:11 -0700 | [diff] [blame] | 154 | this.dependencyRequestFactory = dependencyRequestFactory; |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 155 | this.membersInjectionBindingFactory = membersInjectionBindingFactory; |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 156 | } |
| gak | cc08719 | 2015-01-25 20:29:15 -0800 | [diff] [blame] | 157 | |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 158 | /** |
| 159 | * Returns a ProvisionBinding for the given element. If {@code resolvedType} is present, this |
| dpb | 5420346 | 2016-10-19 13:46:43 -0700 | [diff] [blame] | 160 | * will return a resolved binding, with the key and type resolved to the given type (using |
| sameb | a5bf53f | 2015-01-28 15:51:27 -0800 | [diff] [blame] | 161 | * {@link Types#asMemberOf(DeclaredType, Element)}). |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 162 | */ |
| dpb | 5420346 | 2016-10-19 13:46:43 -0700 | [diff] [blame] | 163 | ProvisionBinding forInjectConstructor( |
| 164 | ExecutableElement constructorElement, Optional<TypeMirror> resolvedType) { |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 165 | checkNotNull(constructorElement); |
| 166 | checkArgument(constructorElement.getKind().equals(CONSTRUCTOR)); |
| Christian Edward Gruber | 8bcede4 | 2014-07-18 18:08:42 -0700 | [diff] [blame] | 167 | checkArgument(isAnnotationPresent(constructorElement, Inject.class)); |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 168 | checkArgument(!getQualifier(constructorElement).isPresent()); |
| 169 | |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 170 | ExecutableType cxtorType = MoreTypes.asExecutable(constructorElement.asType()); |
| 171 | DeclaredType enclosingCxtorType = |
| 172 | MoreTypes.asDeclared(constructorElement.getEnclosingElement().asType()); |
| 173 | // If the class this is constructing has some type arguments, resolve everything. |
| 174 | if (!enclosingCxtorType.getTypeArguments().isEmpty() && resolvedType.isPresent()) { |
| 175 | DeclaredType resolved = MoreTypes.asDeclared(resolvedType.get()); |
| 176 | // Validate that we're resolving from the correct type. |
| 177 | checkState(types.isSameType(types.erasure(resolved), types.erasure(enclosingCxtorType)), |
| 178 | "erased expected type: %s, erased actual type: %s", |
| 179 | types.erasure(resolved), types.erasure(enclosingCxtorType)); |
| 180 | cxtorType = MoreTypes.asExecutable(types.asMemberOf(resolved, constructorElement)); |
| 181 | enclosingCxtorType = resolved; |
| sameb | 2ea676a | 2015-01-15 10:20:24 -0800 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | Key key = keyFactory.forInjectConstructorWithResolvedType(enclosingCxtorType); |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 185 | checkArgument(!key.qualifier().isPresent()); |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 186 | ImmutableSet<DependencyRequest> provisionDependencies = |
| dpb | 31ce673 | 2016-04-29 09:19:30 -0700 | [diff] [blame] | 187 | dependencyRequestFactory.forRequiredResolvedVariables( |
| 188 | constructorElement.getParameters(), cxtorType.getParameterTypes()); |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 189 | // TODO(ronshapiro): instead of creating a MembersInjectionBinding just to retrieve the |
| 190 | // injection sites, create an InjectionSite.Factory and pass that in here. |
| 191 | ImmutableSortedSet<InjectionSite> injectionSites = |
| 192 | membersInjectionBindingFactory |
| 193 | .forInjectedType(enclosingCxtorType, Optional.empty()) |
| 194 | .injectionSites(); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 195 | |
| 196 | ProvisionBinding.Builder builder = |
| 197 | ProvisionBinding.builder() |
| 198 | .contributionType(ContributionType.UNIQUE) |
| 199 | .bindingElement(constructorElement) |
| 200 | .key(key) |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 201 | .provisionDependencies(provisionDependencies) |
| 202 | .injectionSites(injectionSites) |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 203 | .bindingKind(Kind.INJECTION) |
| 204 | .scope(Scope.uniqueScopeOf(constructorElement.getEnclosingElement())); |
| gak | b82b500 | 2015-02-19 00:08:30 -0800 | [diff] [blame] | 205 | |
| sameb | a5bf53f | 2015-01-28 15:51:27 -0800 | [diff] [blame] | 206 | TypeElement bindingTypeElement = |
| 207 | MoreElements.asType(constructorElement.getEnclosingElement()); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 208 | if (hasNonDefaultTypeParameters(bindingTypeElement, key.type(), types)) { |
| dpb | ffd98f6 | 2016-12-20 10:05:16 -0800 | [diff] [blame] | 209 | builder.unresolved(forInjectConstructor(constructorElement, Optional.empty())); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 210 | } |
| 211 | return builder.build(); |
| Christian Edward Gruber | fbb8e4b | 2014-04-15 14:02:34 -0700 | [diff] [blame] | 212 | } |
| 213 | |
| dpb | db24072 | 2016-01-25 14:06:41 -0800 | [diff] [blame] | 214 | ProvisionBinding forProvidesMethod( |
| 215 | ExecutableElement providesMethod, TypeElement contributedBy) { |
| Christian Edward Gruber | 9daba78 | 2014-05-04 18:06:26 -0700 | [diff] [blame] | 216 | checkArgument(providesMethod.getKind().equals(METHOD)); |
| sameb | 0d49be8 | 2015-01-22 17:29:48 -0800 | [diff] [blame] | 217 | ExecutableType resolvedMethod = |
| dpb | 4955ef9 | 2016-04-29 12:31:14 -0700 | [diff] [blame] | 218 | MoreTypes.asExecutable( |
| 219 | types.asMemberOf(MoreTypes.asDeclared(contributedBy.asType()), providesMethod)); |
| 220 | Key key = keyFactory.forProvidesMethod(providesMethod, contributedBy); |
| gak | 09075bc | 2014-07-31 11:02:39 -0700 | [diff] [blame] | 221 | ImmutableSet<DependencyRequest> dependencies = |
| sameb | 0d49be8 | 2015-01-22 17:29:48 -0800 | [diff] [blame] | 222 | dependencyRequestFactory.forRequiredResolvedVariables( |
| sameb | 0d49be8 | 2015-01-22 17:29:48 -0800 | [diff] [blame] | 223 | providesMethod.getParameters(), |
| 224 | resolvedMethod.getParameterTypes()); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 225 | return ProvisionBinding.builder() |
| 226 | .contributionType(ContributionType.fromBindingMethod(providesMethod)) |
| 227 | .bindingElement(providesMethod) |
| 228 | .contributingModule(contributedBy) |
| 229 | .key(key) |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 230 | .provisionDependencies(dependencies) |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 231 | .nullableType(ConfigurationAnnotations.getNullableType(providesMethod)) |
| 232 | .wrappedMapKey(wrapOptionalInEquivalence(getMapKey(providesMethod))) |
| 233 | .bindingKind(Kind.PROVISION) |
| 234 | .scope(Scope.uniqueScopeOf(providesMethod)) |
| 235 | .build(); |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 236 | } |
| gak | e1b68a2 | 2016-04-07 11:54:06 -0700 | [diff] [blame] | 237 | |
| gak | f53c3f9 | 2016-08-17 09:55:56 -0700 | [diff] [blame] | 238 | /** A synthetic binding of {@code Map<K, V>} that depends on {@code Map<K, Provider<V>>}. */ |
| 239 | ProvisionBinding syntheticMapOfValuesBinding(Key mapOfValuesKey) { |
| 240 | checkNotNull(mapOfValuesKey); |
| 241 | Optional<Key> mapOfProvidersKey = keyFactory.implicitMapProviderKeyFrom(mapOfValuesKey); |
| 242 | checkArgument(mapOfProvidersKey.isPresent(), "%s is not a key for Map<K, V>", mapOfValuesKey); |
| dpb | ad76361 | 2016-04-05 14:30:09 -0700 | [diff] [blame] | 243 | DependencyRequest requestForMapOfProviders = |
| gak | ed30daa | 2017-01-06 15:38:17 -0800 | [diff] [blame] | 244 | dependencyRequestFactory.providerForImplicitMapBinding(mapOfProvidersKey.get()); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 245 | return ProvisionBinding.builder() |
| 246 | .contributionType(ContributionType.UNIQUE) |
| gak | f53c3f9 | 2016-08-17 09:55:56 -0700 | [diff] [blame] | 247 | .key(mapOfValuesKey) |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 248 | .provisionDependencies(requestForMapOfProviders) |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 249 | .bindingKind(Kind.SYNTHETIC_MAP) |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 250 | .build(); |
| houcy | cb6c79f | 2014-08-08 12:42:22 -0700 | [diff] [blame] | 251 | } |
| Christian Edward Gruber | 98ad6e2 | 2014-06-04 12:42:49 -0700 | [diff] [blame] | 252 | |
| dpb | db24072 | 2016-01-25 14:06:41 -0800 | [diff] [blame] | 253 | /** |
| dpb | ad76361 | 2016-04-05 14:30:09 -0700 | [diff] [blame] | 254 | * A synthetic binding that depends explicitly on a set of individual provision multibinding |
| 255 | * contribution methods. |
| dpb | 7edcd4d | 2016-06-21 07:52:39 -0700 | [diff] [blame] | 256 | * |
| dpb | ad76361 | 2016-04-05 14:30:09 -0700 | [diff] [blame] | 257 | * <p>Note that these could be set multibindings or map multibindings. |
| dpb | db24072 | 2016-01-25 14:06:41 -0800 | [diff] [blame] | 258 | */ |
| 259 | ProvisionBinding syntheticMultibinding( |
| gak | f53c3f9 | 2016-08-17 09:55:56 -0700 | [diff] [blame] | 260 | Key key, Iterable<ContributionBinding> multibindingContributions) { |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 261 | return ProvisionBinding.builder() |
| 262 | .contributionType(ContributionType.UNIQUE) |
| gak | f53c3f9 | 2016-08-17 09:55:56 -0700 | [diff] [blame] | 263 | .key(key) |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 264 | .provisionDependencies( |
| dpb | 34e4ef7 | 2016-08-10 07:23:36 -0700 | [diff] [blame] | 265 | dependencyRequestFactory.forMultibindingContributions(multibindingContributions)) |
| gak | f53c3f9 | 2016-08-17 09:55:56 -0700 | [diff] [blame] | 266 | .bindingKind(Kind.forMultibindingKey(key)) |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 267 | .build(); |
| dpb | db24072 | 2016-01-25 14:06:41 -0800 | [diff] [blame] | 268 | } |
| 269 | |
| Christian Edward Gruber | 98ad6e2 | 2014-06-04 12:42:49 -0700 | [diff] [blame] | 270 | ProvisionBinding forComponent(TypeElement componentDefinitionType) { |
| 271 | checkNotNull(componentDefinitionType); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 272 | return ProvisionBinding.builder() |
| 273 | .contributionType(ContributionType.UNIQUE) |
| 274 | .bindingElement(componentDefinitionType) |
| 275 | .key(keyFactory.forComponent(componentDefinitionType.asType())) |
| 276 | .bindingKind(Kind.COMPONENT) |
| 277 | .build(); |
| Christian Edward Gruber | 98ad6e2 | 2014-06-04 12:42:49 -0700 | [diff] [blame] | 278 | } |
| Christian Edward Gruber | 14aafa6 | 2014-07-18 18:06:25 -0700 | [diff] [blame] | 279 | |
| 280 | ProvisionBinding forComponentMethod(ExecutableElement componentMethod) { |
| 281 | checkNotNull(componentMethod); |
| 282 | checkArgument(componentMethod.getKind().equals(METHOD)); |
| 283 | checkArgument(componentMethod.getParameters().isEmpty()); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 284 | return ProvisionBinding.builder() |
| 285 | .contributionType(ContributionType.UNIQUE) |
| 286 | .bindingElement(componentMethod) |
| 287 | .key(keyFactory.forComponentMethod(componentMethod)) |
| 288 | .nullableType(ConfigurationAnnotations.getNullableType(componentMethod)) |
| 289 | .bindingKind(Kind.COMPONENT_PROVISION) |
| 290 | .scope(Scope.uniqueScopeOf(componentMethod)) |
| 291 | .build(); |
| Christian Edward Gruber | 14aafa6 | 2014-07-18 18:06:25 -0700 | [diff] [blame] | 292 | } |
| dpb | 99d6408 | 2015-11-12 11:27:12 -0800 | [diff] [blame] | 293 | |
| beder | b50b8ae | 2016-12-07 08:36:26 -0800 | [diff] [blame] | 294 | ProvisionBinding forBuilderBinding(BuilderRequirementMethod method) { |
| 295 | ExecutableElement builderMethod = method.method(); |
| 296 | |
| 297 | checkNotNull(builderMethod); |
| 298 | checkArgument(builderMethod.getKind().equals(METHOD)); |
| 299 | checkArgument(builderMethod.getParameters().size() == 1); |
| 300 | VariableElement parameterElement = Iterables.getOnlyElement(builderMethod.getParameters()); |
| 301 | return ProvisionBinding.builder() |
| 302 | .contributionType(ContributionType.UNIQUE) |
| 303 | .bindingElement(builderMethod) |
| 304 | .key(method.requirement().key().get()) |
| 305 | .nullableType(ConfigurationAnnotations.getNullableType(parameterElement)) |
| 306 | .bindingKind(Kind.BUILDER_BINDING) |
| 307 | .build(); |
| 308 | } |
| 309 | |
| dpb | 99d6408 | 2015-11-12 11:27:12 -0800 | [diff] [blame] | 310 | ProvisionBinding forSubcomponentBuilderMethod( |
| 311 | ExecutableElement subcomponentBuilderMethod, TypeElement contributedBy) { |
| 312 | checkNotNull(subcomponentBuilderMethod); |
| 313 | checkArgument(subcomponentBuilderMethod.getKind().equals(METHOD)); |
| 314 | checkArgument(subcomponentBuilderMethod.getParameters().isEmpty()); |
| 315 | DeclaredType declaredContainer = asDeclared(contributedBy.asType()); |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 316 | return ProvisionBinding.builder() |
| 317 | .contributionType(ContributionType.UNIQUE) |
| 318 | .bindingElement(subcomponentBuilderMethod) |
| 319 | .key( |
| 320 | keyFactory.forSubcomponentBuilderMethod(subcomponentBuilderMethod, declaredContainer)) |
| 321 | .bindingKind(Kind.SUBCOMPONENT_BUILDER) |
| 322 | .build(); |
| dpb | 99d6408 | 2015-11-12 11:27:12 -0800 | [diff] [blame] | 323 | } |
| gak | e1b68a2 | 2016-04-07 11:54:06 -0700 | [diff] [blame] | 324 | |
| ronshapiro | fbb6840 | 2016-08-31 06:44:45 -0700 | [diff] [blame] | 325 | ProvisionBinding syntheticSubcomponentBuilder( |
| 326 | ImmutableSet<SubcomponentDeclaration> subcomponentDeclarations) { |
| 327 | SubcomponentDeclaration subcomponentDeclaration = subcomponentDeclarations.iterator().next(); |
| 328 | return ProvisionBinding.builder() |
| 329 | .contributionType(ContributionType.UNIQUE) |
| 330 | .key(subcomponentDeclaration.key()) |
| 331 | .bindingKind(Kind.SUBCOMPONENT_BUILDER) |
| 332 | .build(); |
| 333 | } |
| 334 | |
| gak | e1b68a2 | 2016-04-07 11:54:06 -0700 | [diff] [blame] | 335 | ProvisionBinding delegate( |
| 336 | DelegateDeclaration delegateDeclaration, ProvisionBinding delegate) { |
| ronshapiro | a0bd775 | 2016-08-10 09:48:51 -0700 | [diff] [blame] | 337 | return delegateBuilder(delegateDeclaration).nullableType(delegate.nullableType()).build(); |
| 338 | } |
| 339 | |
| 340 | /** |
| 341 | * A form of {@link #delegate(DelegateDeclaration, ProvisionBinding)} when the right-hand-side |
| 342 | * of a {@link dagger.Binds} method cannot be resolved. |
| 343 | */ |
| 344 | ProvisionBinding missingDelegate(DelegateDeclaration delegateDeclaration) { |
| 345 | return delegateBuilder(delegateDeclaration).build(); |
| 346 | } |
| 347 | |
| 348 | private ProvisionBinding.Builder delegateBuilder(DelegateDeclaration delegateDeclaration) { |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 349 | return ProvisionBinding.builder() |
| 350 | .contributionType(delegateDeclaration.contributionType()) |
| dpb | dd27603 | 2016-07-11 09:34:43 -0700 | [diff] [blame] | 351 | .bindingElement(delegateDeclaration.bindingElement().get()) |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 352 | .contributingModule(delegateDeclaration.contributingModule().get()) |
| 353 | .key(keyFactory.forDelegateBinding(delegateDeclaration, Provider.class)) |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 354 | .provisionDependencies(delegateDeclaration.delegateRequest()) |
| dpb | 6313ae3 | 2016-06-21 15:15:26 -0700 | [diff] [blame] | 355 | .wrappedMapKey(delegateDeclaration.wrappedMapKey()) |
| 356 | .bindingKind(Kind.SYNTHETIC_DELEGATE_BINDING) |
| ronshapiro | a0bd775 | 2016-08-10 09:48:51 -0700 | [diff] [blame] | 357 | .scope(Scope.uniqueScopeOf(delegateDeclaration.bindingElement().get())); |
| gak | e1b68a2 | 2016-04-07 11:54:06 -0700 | [diff] [blame] | 358 | } |
| dpb | d8d950a | 2016-08-30 09:24:37 -0700 | [diff] [blame] | 359 | |
| 360 | /** |
| ronshapiro | d804a30 | 2016-11-08 10:21:56 -0800 | [diff] [blame] | 361 | * Returns a synthetic binding for a {@code @ForReleasableReferences(scope) |
| 362 | * ReleasableReferenceManager} that provides the component-instantiated object. |
| 363 | */ |
| 364 | ProvisionBinding provideReleasableReferenceManager(Scope scope) { |
| 365 | return ProvisionBinding.builder() |
| 366 | .contributionType(ContributionType.UNIQUE) |
| 367 | .key(keyFactory.forReleasableReferenceManager(scope)) |
| 368 | .bindingKind(Kind.SYNTHETIC_RELEASABLE_REFERENCE_MANAGER) |
| 369 | .build(); |
| 370 | } |
| 371 | |
| 372 | /** |
| 373 | * Returns a synthetic binding for a {@code @ForReleasableReferences(scope) |
| 374 | * TypedReleasableReferenceManager<metadataType>} that provides the component-instantiated |
| 375 | * object. |
| 376 | */ |
| 377 | ContributionBinding provideTypedReleasableReferenceManager( |
| 378 | Scope scope, DeclaredType metadataType) { |
| 379 | return provideReleasableReferenceManager(scope) |
| 380 | .toBuilder() |
| 381 | .key(keyFactory.forTypedReleasableReferenceManager(scope, metadataType)) |
| 382 | .build(); |
| 383 | } |
| 384 | |
| 385 | /** Returns a synthetic binding for {@code Set<ReleasableReferenceManager>}. */ |
| 386 | ProvisionBinding provideSetOfReleasableReferenceManagers() { |
| 387 | return ProvisionBinding.builder() |
| 388 | .contributionType(ContributionType.UNIQUE) |
| 389 | .key(keyFactory.forSetOfReleasableReferenceManagers()) |
| 390 | .bindingKind(Kind.SYNTHETIC_RELEASABLE_REFERENCE_MANAGERS) |
| 391 | .build(); |
| 392 | } |
| 393 | |
| 394 | /** |
| 395 | * Returns a synthetic binding for {@code Set<TypedReleasableReferenceManager<metadataType>}. |
| 396 | */ |
| 397 | ContributionBinding provideSetOfTypedReleasableReferenceManagers(DeclaredType metadataType) { |
| 398 | return provideSetOfReleasableReferenceManagers() |
| 399 | .toBuilder() |
| 400 | .key(keyFactory.forSetOfTypedReleasableReferenceManagers(metadataType)) |
| 401 | .build(); |
| 402 | } |
| 403 | |
| 404 | /** |
| dpb | d8d950a | 2016-08-30 09:24:37 -0700 | [diff] [blame] | 405 | * Returns a synthetic binding for an {@linkplain dagger.BindsOptionalOf optional binding} in a |
| 406 | * component with no binding for the underlying key. |
| 407 | */ |
| 408 | ProvisionBinding syntheticAbsentBinding(Key key) { |
| 409 | return ProvisionBinding.builder() |
| 410 | .contributionType(ContributionType.UNIQUE) |
| 411 | .key(key) |
| 412 | .bindingKind(Kind.SYNTHETIC_OPTIONAL_BINDING) |
| 413 | .build(); |
| 414 | } |
| 415 | |
| 416 | /** |
| 417 | * Returns a synthetic binding for an {@linkplain dagger.BindsOptionalOf optional binding} in a |
| 418 | * component with a binding for the underlying key. |
| 419 | */ |
| ronshapiro | 3a891dd | 2017-07-04 20:04:14 -0700 | [diff] [blame] | 420 | ProvisionBinding syntheticPresentBinding(Key key, DependencyRequest.Kind kind) { |
| dpb | d8d950a | 2016-08-30 09:24:37 -0700 | [diff] [blame] | 421 | return syntheticAbsentBinding(key) |
| 422 | .toBuilder() |
| ronshapiro | e05f921 | 2017-08-08 11:22:11 -0700 | [diff] [blame] | 423 | .provisionDependencies( |
| ronshapiro | 3a891dd | 2017-07-04 20:04:14 -0700 | [diff] [blame] | 424 | dependencyRequestFactory.forSyntheticPresentOptionalBinding(key, kind)) |
| dpb | d8d950a | 2016-08-30 09:24:37 -0700 | [diff] [blame] | 425 | .build(); |
| 426 | } |
| Christian Edward Gruber | 4df3679 | 2014-04-15 14:01:28 -0700 | [diff] [blame] | 427 | } |
| 428 | } |