• 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;
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