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.binding; 18 19 import static dagger.internal.codegen.extension.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.internal.codegen.base.ContributionType; 28 import dagger.internal.codegen.base.SetType; 29 import dagger.model.DependencyRequest; 30 import dagger.model.Key; 31 import java.util.Optional; 32 import java.util.stream.Stream; 33 import javax.lang.model.element.ExecutableElement; 34 import javax.lang.model.type.TypeMirror; 35 36 /** A value object representing the mechanism by which a {@link Key} can be produced. */ 37 @AutoValue 38 public abstract class ProductionBinding extends ContributionBinding { 39 40 @Override bindingType()41 public BindingType bindingType() { 42 return BindingType.PRODUCTION; 43 } 44 45 @Override unresolved()46 public abstract Optional<ProductionBinding> unresolved(); 47 48 @Override implicitDependencies()49 public 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 public 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 public 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 public abstract Optional<ProductionKind> productionKind(); 85 86 /** Returns the list of types in the throws clause of the method. */ thrownTypes()87 public 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 public boolean requiresModuleInstance() { 107 return super.requiresModuleInstance(); 108 } 109 builder()110 public static Builder builder() { 111 return new AutoValue_ProductionBinding.Builder() 112 .explicitDependencies(ImmutableList.<DependencyRequest>of()) 113 .thrownTypes(ImmutableList.<TypeMirror>of()); 114 } 115 116 @Override toBuilder()117 public abstract Builder toBuilder(); 118 119 @Memoized 120 @Override hashCode()121 public abstract int hashCode(); 122 123 // TODO(ronshapiro,dpb): simplify the equality semantics 124 @Override equals(Object obj)125 public abstract boolean equals(Object obj); 126 127 /** A {@link ProductionBinding} builder. */ 128 @AutoValue.Builder 129 @CanIgnoreReturnValue 130 public abstract static class Builder 131 extends ContributionBinding.Builder<ProductionBinding, Builder> { 132 133 @Override dependencies(Iterable<DependencyRequest> dependencies)134 public Builder dependencies(Iterable<DependencyRequest> dependencies) { 135 return explicitDependencies(dependencies); 136 } 137 explicitDependencies(Iterable<DependencyRequest> dependencies)138 abstract Builder explicitDependencies(Iterable<DependencyRequest> dependencies); 139 productionKind(ProductionKind productionKind)140 abstract Builder productionKind(ProductionKind productionKind); 141 142 @Override unresolved(ProductionBinding unresolved)143 public abstract Builder unresolved(ProductionBinding unresolved); 144 thrownTypes(Iterable<? extends TypeMirror> thrownTypes)145 abstract Builder thrownTypes(Iterable<? extends TypeMirror> thrownTypes); 146 executorRequest(DependencyRequest executorRequest)147 abstract Builder executorRequest(DependencyRequest executorRequest); 148 monitorRequest(DependencyRequest monitorRequest)149 abstract Builder monitorRequest(DependencyRequest monitorRequest); 150 } 151 } 152