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 dagger.internal.codegen.DaggerStreams.toImmutableSet; 20 import static dagger.internal.codegen.langmodel.DaggerTypes.isFutureType; 21 22 import com.google.auto.value.AutoValue; 23 import com.google.auto.value.extension.memoized.Memoized; 24 import com.google.common.collect.ImmutableList; 25 import com.google.common.collect.ImmutableSet; 26 import com.google.errorprone.annotations.CanIgnoreReturnValue; 27 import dagger.model.DependencyRequest; 28 import dagger.model.Key; 29 import java.util.Optional; 30 import java.util.stream.Stream; 31 import javax.lang.model.element.ExecutableElement; 32 import javax.lang.model.type.TypeMirror; 33 34 /** 35 * A value object representing the mechanism by which a {@link Key} can be produced. 36 */ 37 @AutoValue 38 abstract class ProductionBinding extends ContributionBinding { 39 40 @Override bindingType()41 public BindingType bindingType() { 42 return BindingType.PRODUCTION; 43 } 44 45 @Override unresolved()46 abstract Optional<ProductionBinding> unresolved(); 47 48 @Override implicitDependencies()49 ImmutableSet<DependencyRequest> implicitDependencies() { 50 return Stream.of(executorRequest(), monitorRequest()) 51 .filter(Optional::isPresent) 52 .map(Optional::get) 53 .collect(toImmutableSet()); 54 } 55 56 /** What kind of object a {@code @Produces}-annotated method returns. */ 57 enum ProductionKind { 58 /** A value. */ 59 IMMEDIATE, 60 /** A {@code ListenableFuture<T>}. */ 61 FUTURE, 62 /** A {@code Set<ListenableFuture<T>>}. */ 63 SET_OF_FUTURE; 64 65 /** Returns the kind of object a {@code @Produces}-annotated method returns. */ fromProducesMethod(ExecutableElement producesMethod)66 static ProductionKind fromProducesMethod(ExecutableElement producesMethod) { 67 if (isFutureType(producesMethod.getReturnType())) { 68 return FUTURE; 69 } else if (ContributionType.fromBindingElement(producesMethod) 70 .equals(ContributionType.SET_VALUES) 71 && isFutureType(SetType.from(producesMethod.getReturnType()).elementType())) { 72 return SET_OF_FUTURE; 73 } else { 74 return IMMEDIATE; 75 } 76 } 77 } 78 79 /** 80 * Returns the kind of object the produces method returns. All production bindings from 81 * {@code @Produces} methods will have a production kind, but synthetic production bindings may 82 * not. 83 */ productionKind()84 abstract Optional<ProductionKind> productionKind(); 85 86 /** Returns the list of types in the throws clause of the method. */ thrownTypes()87 abstract ImmutableList<? extends TypeMirror> thrownTypes(); 88 89 /** 90 * If this production requires an executor, this will be the corresponding request. All 91 * production bindings from {@code @Produces} methods will have an executor request, but 92 * synthetic production bindings may not. 93 */ executorRequest()94 abstract Optional<DependencyRequest> executorRequest(); 95 96 /** If this production requires a monitor, this will be the corresponding request. All 97 * production bindings from {@code @Produces} methods will have a monitor request, but synthetic 98 * production bindings may not. 99 */ monitorRequest()100 abstract Optional<DependencyRequest> monitorRequest(); 101 102 // Profiling determined that this method is called enough times that memoizing it had a measurable 103 // performance improvement for large components. 104 @Memoized 105 @Override requiresModuleInstance()106 boolean requiresModuleInstance() { 107 return super.requiresModuleInstance(); 108 } 109 builder()110 static Builder builder() { 111 return new AutoValue_ProductionBinding.Builder() 112 .explicitDependencies(ImmutableList.<DependencyRequest>of()) 113 .thrownTypes(ImmutableList.<TypeMirror>of()); 114 } 115 116 @Memoized 117 @Override hashCode()118 public abstract int hashCode(); 119 120 // TODO(ronshapiro,dpb): simplify the equality semantics 121 @Override equals(Object obj)122 public abstract boolean equals(Object obj); 123 124 @AutoValue.Builder 125 @CanIgnoreReturnValue 126 abstract static class Builder extends ContributionBinding.Builder<ProductionBinding, Builder> { 127 128 @Override dependencies(Iterable<DependencyRequest> dependencies)129 Builder dependencies(Iterable<DependencyRequest> dependencies) { 130 return explicitDependencies(dependencies); 131 } 132 explicitDependencies(Iterable<DependencyRequest> dependencies)133 abstract Builder explicitDependencies(Iterable<DependencyRequest> dependencies); 134 productionKind(ProductionKind productionKind)135 abstract Builder productionKind(ProductionKind productionKind); 136 137 @Override unresolved(ProductionBinding unresolved)138 abstract Builder unresolved(ProductionBinding unresolved); 139 thrownTypes(Iterable<? extends TypeMirror> thrownTypes)140 abstract Builder thrownTypes(Iterable<? extends TypeMirror> thrownTypes); 141 executorRequest(DependencyRequest executorRequest)142 abstract Builder executorRequest(DependencyRequest executorRequest); 143 monitorRequest(DependencyRequest monitorRequest)144 abstract Builder monitorRequest(DependencyRequest monitorRequest); 145 } 146 } 147