• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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