1 /* 2 * Copyright (C) 2014 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 static com.google.common.base.Suppliers.memoize; 20 import static com.google.common.collect.Iterables.getOnlyElement; 21 import static dagger.internal.codegen.DaggerStreams.toImmutableList; 22 import static java.util.stream.Collectors.toSet; 23 import static javax.lang.model.element.Modifier.ABSTRACT; 24 import static javax.lang.model.element.Modifier.STATIC; 25 26 import com.google.auto.value.AutoValue; 27 import com.google.common.base.Supplier; 28 import com.google.common.collect.ImmutableList; 29 import com.google.common.collect.ImmutableMap; 30 import com.google.common.collect.ImmutableSet; 31 import com.google.common.collect.ImmutableSetMultimap; 32 import com.google.common.collect.Lists; 33 import com.google.common.collect.Multimaps; 34 import com.google.common.collect.Sets; 35 import dagger.internal.codegen.langmodel.DaggerTypes; 36 import dagger.model.BindingKind; 37 import dagger.model.DependencyRequest; 38 import dagger.model.Key; 39 import dagger.model.Scope; 40 import java.util.Iterator; 41 import java.util.List; 42 import java.util.Map; 43 import java.util.Optional; 44 import java.util.Set; 45 import javax.lang.model.element.Element; 46 import javax.lang.model.element.Modifier; 47 import javax.lang.model.element.TypeElement; 48 import javax.lang.model.element.TypeParameterElement; 49 import javax.lang.model.type.DeclaredType; 50 import javax.lang.model.type.TypeMirror; 51 import javax.lang.model.util.SimpleTypeVisitor6; 52 53 /** 54 * An abstract type for classes representing a Dagger binding. Particularly, contains the {@link 55 * Element} that generated the binding and the {@link DependencyRequest} instances that are required 56 * to satisfy the binding, but leaves the specifics of the <i>mechanism</i> of the binding to the 57 * subtypes. 58 */ 59 abstract class Binding extends BindingDeclaration { 60 61 /** 62 * Returns {@code true} if using this binding requires an instance of the {@link 63 * #contributingModule()}. 64 */ requiresModuleInstance()65 boolean requiresModuleInstance() { 66 if (!bindingElement().isPresent() || !contributingModule().isPresent()) { 67 return false; 68 } 69 Set<Modifier> modifiers = bindingElement().get().getModifiers(); 70 return !modifiers.contains(ABSTRACT) && !modifiers.contains(STATIC); 71 } 72 73 /** 74 * Returns {@code true} if this binding may provide {@code null} instead of an instance of {@link 75 * #key()}. Nullable bindings cannot be requested from {@linkplain DependencyRequest#isNullable() 76 * non-nullable dependency requests}. 77 */ isNullable()78 abstract boolean isNullable(); 79 80 /** The kind of binding this instance represents. */ kind()81 abstract BindingKind kind(); 82 83 /** The {@link BindingType} of this binding. */ bindingType()84 abstract BindingType bindingType(); 85 86 /** The {@link FrameworkType} of this binding. */ frameworkType()87 final FrameworkType frameworkType() { 88 return FrameworkType.forBindingType(bindingType()); 89 } 90 91 /** 92 * The explicit set of {@link DependencyRequest dependencies} required to satisfy this binding as 93 * defined by the user-defined injection sites. 94 */ explicitDependencies()95 abstract ImmutableSet<DependencyRequest> explicitDependencies(); 96 97 /** 98 * The set of {@link DependencyRequest dependencies} that are added by the framework rather than a 99 * user-defined injection site. This returns an unmodifiable set. 100 */ 101 // TODO(gak): this will eventually get changed to return a set of FrameworkDependency implicitDependencies()102 ImmutableSet<DependencyRequest> implicitDependencies() { 103 return ImmutableSet.of(); 104 } 105 106 private final Supplier<ImmutableSet<DependencyRequest>> dependencies = 107 memoize( 108 () -> { 109 ImmutableSet<DependencyRequest> implicitDependencies = implicitDependencies(); 110 return ImmutableSet.copyOf( 111 implicitDependencies.isEmpty() 112 ? explicitDependencies() 113 : Sets.union(implicitDependencies, explicitDependencies())); 114 }); 115 116 /** 117 * The set of {@link DependencyRequest dependencies} required to satisfy this binding. This is the 118 * union of {@link #explicitDependencies()} and {@link #implicitDependencies()}. This returns an 119 * unmodifiable set. 120 */ dependencies()121 final ImmutableSet<DependencyRequest> dependencies() { 122 return dependencies.get(); 123 } 124 125 private final Supplier<ImmutableList<FrameworkDependency>> frameworkDependencies = 126 memoize( 127 () -> 128 dependencyAssociations() 129 .stream() 130 .map(DependencyAssociation::frameworkDependency) 131 .collect(toImmutableList())); 132 133 /** 134 * The framework dependencies of {@code binding}. There will be one element for each different 135 * binding key in the <em>{@linkplain Binding#unresolved() unresolved}</em> version of {@code 136 * binding}. 137 * 138 * <p>For example, given the following modules: 139 * 140 * <pre><code> 141 * {@literal @Module} abstract class {@literal BaseModule<T>} { 142 * {@literal @Provides} Foo provideFoo(T t, String string) { 143 * return …; 144 * } 145 * } 146 * 147 * {@literal @Module} class StringModule extends {@literal BaseModule<String>} {} 148 * </code></pre> 149 * 150 * Both dependencies of {@code StringModule.provideFoo} have the same binding key: {@code String}. 151 * But there are still two dependencies, because in the unresolved binding they have different 152 * binding keys: 153 * 154 * <dl> 155 * <dt>{@code T} 156 * <dd>{@code String t} 157 * <dt>{@code String} 158 * <dd>{@code String string} 159 * </dl> 160 * 161 * <p>Note that the sets returned by this method when called on the same binding will be equal, 162 * and their elements will be in the same order. 163 */ 164 /* TODO(dpb): The stable-order postcondition is actually hard to verify in code for two equal 165 * instances of Binding, because it really depends on the order of the binding's dependencies, 166 * and two equal instances of Binding may have the same dependencies in a different order. */ frameworkDependencies()167 final ImmutableList<FrameworkDependency> frameworkDependencies() { 168 return frameworkDependencies.get(); 169 } 170 171 /** 172 * Associates a {@link FrameworkDependency} with the set of {@link DependencyRequest} instances 173 * that correlate for a binding. 174 */ 175 @AutoValue 176 abstract static class DependencyAssociation { frameworkDependency()177 abstract FrameworkDependency frameworkDependency(); 178 dependencyRequests()179 abstract ImmutableSet<DependencyRequest> dependencyRequests(); 180 create( FrameworkDependency frameworkDependency, Iterable<DependencyRequest> dependencyRequests)181 static DependencyAssociation create( 182 FrameworkDependency frameworkDependency, Iterable<DependencyRequest> dependencyRequests) { 183 return new AutoValue_Binding_DependencyAssociation( 184 frameworkDependency, ImmutableSet.copyOf(dependencyRequests)); 185 } 186 } 187 188 private final Supplier<ImmutableList<DependencyAssociation>> dependencyAssociations = 189 memoize( 190 () -> { 191 FrameworkTypeMapper frameworkTypeMapper = 192 FrameworkTypeMapper.forBindingType(bindingType()); 193 ImmutableList.Builder<DependencyAssociation> list = ImmutableList.builder(); 194 for (Set<DependencyRequest> requests : groupByUnresolvedKey()) { 195 list.add( 196 DependencyAssociation.create( 197 FrameworkDependency.create( 198 getOnlyElement( 199 requests.stream().map(DependencyRequest::key).collect(toSet())), 200 frameworkTypeMapper.getFrameworkType(requests)), 201 requests)); 202 } 203 return list.build(); 204 }); 205 206 /** 207 * Returns the same {@link FrameworkDependency} instances from {@link #frameworkDependencies}, but 208 * with the set of {@link DependencyRequest} instances with which each is associated. 209 * 210 * <p>Ths method returns a list of {@link Map.Entry entries} rather than a {@link Map} or {@link 211 * com.google.common.collect.Multimap} because any given {@link FrameworkDependency} may appear 212 * multiple times if the {@linkplain Binding#unresolved() unresolved} binding requires it. If that 213 * distinction is not important, the entries can be merged into a single mapping. 214 */ dependencyAssociations()215 final ImmutableList<DependencyAssociation> dependencyAssociations() { 216 return dependencyAssociations.get(); 217 } 218 219 private final Supplier<ImmutableMap<DependencyRequest, FrameworkDependency>> 220 frameworkDependenciesMap = 221 memoize( 222 () -> { 223 ImmutableMap.Builder<DependencyRequest, FrameworkDependency> frameworkDependencies = 224 ImmutableMap.builder(); 225 for (DependencyAssociation dependencyAssociation : dependencyAssociations()) { 226 for (DependencyRequest dependencyRequest : 227 dependencyAssociation.dependencyRequests()) { 228 frameworkDependencies.put( 229 dependencyRequest, dependencyAssociation.frameworkDependency()); 230 } 231 } 232 return frameworkDependencies.build(); 233 }); 234 235 /** 236 * Returns the mapping from each {@linkplain #dependencies dependency} to its associated {@link 237 * FrameworkDependency}. 238 */ 239 final ImmutableMap<DependencyRequest, FrameworkDependency> dependenciesToFrameworkDependenciesMap()240 dependenciesToFrameworkDependenciesMap() { 241 return frameworkDependenciesMap.get(); 242 } 243 244 /** 245 * Groups {@code binding}'s implicit dependencies by their binding key, using the dependency keys 246 * from the {@link Binding#unresolved()} binding if it exists. 247 */ groupByUnresolvedKey()248 private ImmutableList<Set<DependencyRequest>> groupByUnresolvedKey() { 249 ImmutableSetMultimap.Builder<Key, DependencyRequest> dependenciesByKeyBuilder = 250 ImmutableSetMultimap.builder(); 251 Iterator<DependencyRequest> dependencies = dependencies().iterator(); 252 Binding unresolved = unresolved().isPresent() ? unresolved().get() : this; 253 Iterator<DependencyRequest> unresolvedDependencies = unresolved.dependencies().iterator(); 254 while (dependencies.hasNext()) { 255 dependenciesByKeyBuilder.put(unresolvedDependencies.next().key(), dependencies.next()); 256 } 257 return ImmutableList.copyOf( 258 Multimaps.asMap( 259 dependenciesByKeyBuilder.orderValuesBy(SourceFiles.DEPENDENCY_ORDERING).build()) 260 .values()); 261 } 262 263 /** 264 * If this binding's key's type parameters are different from those of the 265 * {@link #bindingTypeElement()}, this is the binding for the {@link #bindingTypeElement()}'s 266 * unresolved type. 267 */ unresolved()268 abstract Optional<? extends Binding> unresolved(); 269 scope()270 Optional<Scope> scope() { 271 return Optional.empty(); 272 } 273 274 // TODO(sameb): Remove the TypeElement parameter and pull it from the TypeMirror. hasNonDefaultTypeParameters( TypeElement element, TypeMirror type, DaggerTypes types)275 static boolean hasNonDefaultTypeParameters( 276 TypeElement element, TypeMirror type, DaggerTypes types) { 277 // If the element has no type parameters, nothing can be wrong. 278 if (element.getTypeParameters().isEmpty()) { 279 return false; 280 } 281 282 List<TypeMirror> defaultTypes = Lists.newArrayList(); 283 for (TypeParameterElement parameter : element.getTypeParameters()) { 284 defaultTypes.add(parameter.asType()); 285 } 286 287 List<TypeMirror> actualTypes = 288 type.accept( 289 new SimpleTypeVisitor6<List<TypeMirror>, Void>() { 290 @Override 291 protected List<TypeMirror> defaultAction(TypeMirror e, Void p) { 292 return ImmutableList.of(); 293 } 294 295 @Override 296 public List<TypeMirror> visitDeclared(DeclaredType t, Void p) { 297 return ImmutableList.<TypeMirror>copyOf(t.getTypeArguments()); 298 } 299 }, 300 null); 301 302 // The actual type parameter size can be different if the user is using a raw type. 303 if (defaultTypes.size() != actualTypes.size()) { 304 return true; 305 } 306 307 for (int i = 0; i < defaultTypes.size(); i++) { 308 if (!types.isSameType(defaultTypes.get(i), actualTypes.get(i))) { 309 return true; 310 } 311 } 312 return false; 313 } 314 } 315