1 /* 2 * Copyright (C) 2014 Google, Inc. 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 package dagger.internal.codegen; 17 18 import com.google.auto.common.MoreElements; 19 import com.google.auto.common.MoreTypes; 20 import com.google.auto.value.AutoValue; 21 import com.google.common.base.Function; 22 import com.google.common.base.Optional; 23 import com.google.common.collect.FluentIterable; 24 import com.google.common.collect.ImmutableSet; 25 import com.google.common.collect.Iterables; 26 import com.google.common.util.concurrent.ListenableFuture; 27 import dagger.Lazy; 28 import dagger.MembersInjector; 29 import dagger.Provides; 30 import dagger.producers.Produced; 31 import dagger.producers.Producer; 32 import dagger.producers.internal.AbstractProducer; 33 import java.util.List; 34 import javax.inject.Inject; 35 import javax.inject.Provider; 36 import javax.lang.model.element.AnnotationMirror; 37 import javax.lang.model.element.Element; 38 import javax.lang.model.element.ExecutableElement; 39 import javax.lang.model.element.TypeElement; 40 import javax.lang.model.element.VariableElement; 41 import javax.lang.model.type.DeclaredType; 42 import javax.lang.model.type.ExecutableType; 43 import javax.lang.model.type.TypeKind; 44 import javax.lang.model.type.TypeMirror; 45 import javax.lang.model.util.Elements; 46 47 import static com.google.auto.common.MoreTypes.isTypeOf; 48 import static com.google.common.base.Preconditions.checkArgument; 49 import static com.google.common.base.Preconditions.checkNotNull; 50 import static com.google.common.base.Preconditions.checkState; 51 import static javax.lang.model.type.TypeKind.DECLARED; 52 import static javax.lang.model.util.ElementFilter.constructorsIn; 53 54 /** 55 * Represents a request for a key at an injection point. Parameters to {@link Inject} constructors 56 * or {@link Provides} methods are examples of key requests. 57 * 58 * @author Gregory Kick 59 * @since 2.0 60 */ 61 // TODO(gak): Set bindings and the permutations thereof need to be addressed 62 @AutoValue 63 abstract class DependencyRequest { 64 static final Function<DependencyRequest, BindingKey> BINDING_KEY_FUNCTION = 65 new Function<DependencyRequest, BindingKey>() { 66 @Override public BindingKey apply(DependencyRequest request) { 67 return request.bindingKey(); 68 } 69 }; 70 71 enum Kind { 72 /** A default request for an instance. E.g.: {@code Blah} */ 73 INSTANCE, 74 /** A request for a {@link Provider}. E.g.: {@code Provider<Blah>} */ 75 PROVIDER, 76 /** A request for a {@link Lazy}. E.g.: {@code Lazy<Blah>} */ 77 LAZY, 78 /** A request for a {@link MembersInjector}. E.g.: {@code MembersInjector<Blah>} */ 79 MEMBERS_INJECTOR, 80 /** A request for a {@link Producer}. E.g.: {@code Producer<Blah>} */ 81 PRODUCER, 82 /** A request for a {@link Produced}. E.g.: {@code Produced<Blah>} */ 83 PRODUCED, 84 /** 85 * A request for a {@link ListenableFuture}. E.g.: {@code ListenableFuture<Blah>}. 86 * These can only be requested by component interfaces. 87 */ 88 FUTURE, 89 } 90 kind()91 abstract Kind kind(); key()92 abstract Key key(); 93 bindingKey()94 BindingKey bindingKey() { 95 switch (kind()) { 96 case INSTANCE: 97 case LAZY: 98 case PROVIDER: 99 case PRODUCER: 100 case PRODUCED: 101 case FUTURE: 102 return BindingKey.create(BindingKey.Kind.CONTRIBUTION, key()); 103 case MEMBERS_INJECTOR: 104 return BindingKey.create(BindingKey.Kind.MEMBERS_INJECTION, key()); 105 default: 106 throw new AssertionError(); 107 } 108 } 109 requestElement()110 abstract Element requestElement(); 111 112 /** 113 * Returns the possibly resolved type that contained the requesting element. For members injection 114 * requests, this is the type itself. 115 */ enclosingType()116 abstract DeclaredType enclosingType(); 117 118 /** Returns true if this request allows null objects. */ isNullable()119 abstract boolean isNullable(); 120 121 /** 122 * An optional name for this request when it's referred to in generated code. If absent, it will 123 * use a name derived from {@link #requestElement}. 124 */ overriddenVariableName()125 abstract Optional<String> overriddenVariableName(); 126 127 /** 128 * Factory for {@link DependencyRequest}s. 129 * 130 * <p>Any factory method may throw {@link TypeNotPresentException} if a type is not available, 131 * which may mean that the type will be generated in a later round of processing. 132 */ 133 static final class Factory { 134 private final Elements elements; 135 private final Key.Factory keyFactory; 136 Factory(Elements elements, Key.Factory keyFactory)137 Factory(Elements elements, Key.Factory keyFactory) { 138 this.elements = elements; 139 this.keyFactory = keyFactory; 140 } 141 forRequiredResolvedVariables(DeclaredType container, List<? extends VariableElement> variables, List<? extends TypeMirror> resolvedTypes)142 ImmutableSet<DependencyRequest> forRequiredResolvedVariables(DeclaredType container, 143 List<? extends VariableElement> variables, List<? extends TypeMirror> resolvedTypes) { 144 checkState(resolvedTypes.size() == variables.size()); 145 ImmutableSet.Builder<DependencyRequest> builder = ImmutableSet.builder(); 146 for (int i = 0; i < variables.size(); i++) { 147 builder.add(forRequiredResolvedVariable(container, variables.get(i), resolvedTypes.get(i))); 148 } 149 return builder.build(); 150 } 151 forRequiredVariables( List<? extends VariableElement> variables)152 ImmutableSet<DependencyRequest> forRequiredVariables( 153 List<? extends VariableElement> variables) { 154 return FluentIterable.from(variables) 155 .transform( 156 new Function<VariableElement, DependencyRequest>() { 157 @Override 158 public DependencyRequest apply(VariableElement input) { 159 return forRequiredVariable(input); 160 } 161 }) 162 .toSet(); 163 } 164 165 /** 166 * Creates a implicit {@link DependencyRequest} for {@code mapOfFactoryKey}, which will be used 167 * to satisfy the {@code mapOfValueRequest}. 168 * 169 * @param mapOfValueRequest a request for {@code Map<K, V>} 170 * @param mapOfFactoryKey a key equivalent to {@code mapOfValueRequest}'s key, whose type is 171 * {@code Map<K, Provider<V>>} or {@code Map<K, Producer<V>>} 172 */ forImplicitMapBinding( DependencyRequest mapOfValueRequest, Key mapOfFactoryKey)173 DependencyRequest forImplicitMapBinding( 174 DependencyRequest mapOfValueRequest, Key mapOfFactoryKey) { 175 checkNotNull(mapOfValueRequest); 176 return new AutoValue_DependencyRequest( 177 Kind.PROVIDER, 178 mapOfFactoryKey, 179 mapOfValueRequest.requestElement(), 180 mapOfValueRequest.enclosingType(), 181 false /* doesn't allow null */, 182 Optional.<String>absent()); 183 } 184 forRequiredVariable(VariableElement variableElement)185 DependencyRequest forRequiredVariable(VariableElement variableElement) { 186 return forRequiredVariable(variableElement, Optional.<String>absent()); 187 } 188 forRequiredVariable(VariableElement variableElement, Optional<String> name)189 DependencyRequest forRequiredVariable(VariableElement variableElement, Optional<String> name) { 190 checkNotNull(variableElement); 191 TypeMirror type = variableElement.asType(); 192 Optional<AnnotationMirror> qualifier = InjectionAnnotations.getQualifier(variableElement); 193 return newDependencyRequest( 194 variableElement, type, qualifier, getEnclosingType(variableElement), name); 195 } 196 forRequiredResolvedVariable(DeclaredType container, VariableElement variableElement, TypeMirror resolvedType)197 DependencyRequest forRequiredResolvedVariable(DeclaredType container, 198 VariableElement variableElement, 199 TypeMirror resolvedType) { 200 checkNotNull(variableElement); 201 checkNotNull(resolvedType); 202 Optional<AnnotationMirror> qualifier = InjectionAnnotations.getQualifier(variableElement); 203 return newDependencyRequest( 204 variableElement, resolvedType, qualifier, container, Optional.<String>absent()); 205 } 206 forComponentProvisionMethod(ExecutableElement provisionMethod, ExecutableType provisionMethodType)207 DependencyRequest forComponentProvisionMethod(ExecutableElement provisionMethod, 208 ExecutableType provisionMethodType) { 209 checkNotNull(provisionMethod); 210 checkNotNull(provisionMethodType); 211 checkArgument( 212 provisionMethod.getParameters().isEmpty(), 213 "Component provision methods must be empty: %s", 214 provisionMethod); 215 Optional<AnnotationMirror> qualifier = InjectionAnnotations.getQualifier(provisionMethod); 216 return newDependencyRequest( 217 provisionMethod, 218 provisionMethodType.getReturnType(), 219 qualifier, 220 getEnclosingType(provisionMethod), 221 Optional.<String>absent()); 222 } 223 forComponentProductionMethod(ExecutableElement productionMethod, ExecutableType productionMethodType)224 DependencyRequest forComponentProductionMethod(ExecutableElement productionMethod, 225 ExecutableType productionMethodType) { 226 checkNotNull(productionMethod); 227 checkNotNull(productionMethodType); 228 checkArgument(productionMethod.getParameters().isEmpty(), 229 "Component production methods must be empty: %s", productionMethod); 230 TypeMirror type = productionMethodType.getReturnType(); 231 Optional<AnnotationMirror> qualifier = InjectionAnnotations.getQualifier(productionMethod); 232 DeclaredType container = getEnclosingType(productionMethod); 233 // Only a component production method can be a request for a ListenableFuture, so we 234 // special-case it here. 235 if (isTypeOf(ListenableFuture.class, type)) { 236 return new AutoValue_DependencyRequest( 237 Kind.FUTURE, 238 keyFactory.forQualifiedType( 239 qualifier, Iterables.getOnlyElement(((DeclaredType) type).getTypeArguments())), 240 productionMethod, 241 container, 242 false /* doesn't allow null */, 243 Optional.<String>absent()); 244 } else { 245 return newDependencyRequest( 246 productionMethod, type, qualifier, container, Optional.<String>absent()); 247 } 248 } 249 forComponentMembersInjectionMethod(ExecutableElement membersInjectionMethod, ExecutableType membersInjectionMethodType)250 DependencyRequest forComponentMembersInjectionMethod(ExecutableElement membersInjectionMethod, 251 ExecutableType membersInjectionMethodType) { 252 checkNotNull(membersInjectionMethod); 253 checkNotNull(membersInjectionMethodType); 254 Optional<AnnotationMirror> qualifier = 255 InjectionAnnotations.getQualifier(membersInjectionMethod); 256 checkArgument(!qualifier.isPresent()); 257 TypeMirror returnType = membersInjectionMethodType.getReturnType(); 258 if (returnType.getKind().equals(DECLARED) 259 && MoreTypes.isTypeOf(MembersInjector.class, returnType)) { 260 return new AutoValue_DependencyRequest( 261 Kind.MEMBERS_INJECTOR, 262 keyFactory.forMembersInjectedType( 263 Iterables.getOnlyElement(((DeclaredType) returnType).getTypeArguments())), 264 membersInjectionMethod, 265 getEnclosingType(membersInjectionMethod), 266 false /* doesn't allow null */, 267 Optional.<String>absent()); 268 } else { 269 return new AutoValue_DependencyRequest( 270 Kind.MEMBERS_INJECTOR, 271 keyFactory.forMembersInjectedType( 272 Iterables.getOnlyElement(membersInjectionMethodType.getParameterTypes())), 273 membersInjectionMethod, 274 getEnclosingType(membersInjectionMethod), 275 false /* doesn't allow null */, 276 Optional.<String>absent()); 277 } 278 } 279 forMembersInjectedType(DeclaredType type)280 DependencyRequest forMembersInjectedType(DeclaredType type) { 281 return new AutoValue_DependencyRequest( 282 Kind.MEMBERS_INJECTOR, 283 keyFactory.forMembersInjectedType(type), 284 type.asElement(), 285 type, 286 false /* doesn't allow null */, 287 Optional.<String>absent()); 288 } 289 forProductionComponentMonitorProvider()290 DependencyRequest forProductionComponentMonitorProvider() { 291 TypeElement element = elements.getTypeElement(AbstractProducer.class.getCanonicalName()); 292 for (ExecutableElement constructor : constructorsIn(element.getEnclosedElements())) { 293 if (constructor.getParameters().size() == 2) { 294 // the 2-arg constructor has the appropriate dependency as its first arg 295 return forRequiredVariable(constructor.getParameters().get(0), Optional.of("monitor")); 296 } 297 } 298 throw new AssertionError("expected 2-arg constructor in AbstractProducer"); 299 } 300 newDependencyRequest( Element requestElement, TypeMirror type, Optional<AnnotationMirror> qualifier, DeclaredType container, Optional<String> name)301 private DependencyRequest newDependencyRequest( 302 Element requestElement, 303 TypeMirror type, 304 Optional<AnnotationMirror> qualifier, 305 DeclaredType container, 306 Optional<String> name) { 307 KindAndType kindAndType = extractKindAndType(type); 308 if (kindAndType.kind().equals(Kind.MEMBERS_INJECTOR)) { 309 checkArgument(!qualifier.isPresent()); 310 } 311 // Only instance types can be non-null -- all other requests are wrapped 312 // inside something (e.g, Provider, Lazy, etc..). 313 // TODO(sameb): should Produced/Producer always require non-nullable? 314 boolean allowsNull = !kindAndType.kind().equals(Kind.INSTANCE) 315 || ConfigurationAnnotations.getNullableType(requestElement).isPresent(); 316 return new AutoValue_DependencyRequest( 317 kindAndType.kind(), 318 keyFactory.forQualifiedType(qualifier, kindAndType.type()), 319 requestElement, 320 container, 321 allowsNull, 322 name); 323 } 324 325 @AutoValue 326 static abstract class KindAndType { kind()327 abstract Kind kind(); type()328 abstract TypeMirror type(); 329 } 330 331 /** 332 * Extracts the correct requesting type & kind out a request type. For example, if a user 333 * requests {@code Provider<Foo>}, this will return ({@link Kind#PROVIDER}, {@code Foo}). 334 * 335 * @throws TypeNotPresentException if {@code type}'s kind is {@link TypeKind#ERROR}, which may 336 * mean that the type will be generated in a later round of processing 337 */ extractKindAndType(TypeMirror type)338 static KindAndType extractKindAndType(TypeMirror type) { 339 if (type.getKind().equals(TypeKind.ERROR)) { 340 throw new TypeNotPresentException(type.toString(), null); 341 } 342 343 // We must check TYPEVAR explicitly before the below checks because calling 344 // isTypeOf(..) on a TYPEVAR throws an exception (because it can't be 345 // represented as a Class). 346 if (type.getKind().equals(TypeKind.TYPEVAR)) { 347 return new AutoValue_DependencyRequest_Factory_KindAndType(Kind.INSTANCE, type); 348 } else if (isTypeOf(Provider.class, type)) { 349 return new AutoValue_DependencyRequest_Factory_KindAndType(Kind.PROVIDER, 350 Iterables.getOnlyElement(((DeclaredType) type).getTypeArguments())); 351 } else if (isTypeOf(Lazy.class, type)) { 352 return new AutoValue_DependencyRequest_Factory_KindAndType(Kind.LAZY, 353 Iterables.getOnlyElement(((DeclaredType) type).getTypeArguments())); 354 } else if (isTypeOf(MembersInjector.class, type)) { 355 return new AutoValue_DependencyRequest_Factory_KindAndType(Kind.MEMBERS_INJECTOR, 356 Iterables.getOnlyElement(((DeclaredType) type).getTypeArguments())); 357 } else if (isTypeOf(Producer.class, type)) { 358 return new AutoValue_DependencyRequest_Factory_KindAndType(Kind.PRODUCER, 359 Iterables.getOnlyElement(((DeclaredType) type).getTypeArguments())); 360 } else if (isTypeOf(Produced.class, type)) { 361 return new AutoValue_DependencyRequest_Factory_KindAndType(Kind.PRODUCED, 362 Iterables.getOnlyElement(((DeclaredType) type).getTypeArguments())); 363 } else { 364 return new AutoValue_DependencyRequest_Factory_KindAndType(Kind.INSTANCE, type); 365 } 366 } 367 getEnclosingType(Element element)368 static DeclaredType getEnclosingType(Element element) { 369 while (!MoreElements.isType(element)) { 370 element = element.getEnclosingElement(); 371 } 372 return MoreTypes.asDeclared(element.asType()); 373 } 374 } 375 } 376