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