• 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 com.google.common.base.Preconditions.checkNotNull;
20 import static dagger.internal.codegen.xprocessing.XElements.closestEnclosingTypeElement;
21 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
22 import static dagger.internal.codegen.xprocessing.XElements.isPrivate;
23 import static java.util.stream.Collectors.toList;
24 
25 import androidx.room.compiler.processing.XElement;
26 import androidx.room.compiler.processing.XFieldElement;
27 import androidx.room.compiler.processing.XMethodElement;
28 import androidx.room.compiler.processing.XTypeElement;
29 import com.google.auto.value.AutoValue;
30 import com.google.auto.value.extension.memoized.Memoized;
31 import com.google.common.collect.ImmutableSet;
32 import com.google.common.collect.ImmutableSortedSet;
33 import dagger.internal.codegen.model.BindingKind;
34 import dagger.internal.codegen.model.DependencyRequest;
35 import dagger.internal.codegen.model.Key;
36 import java.util.Optional;
37 
38 /** Represents the full members injection of a particular type. */
39 @AutoValue
40 public abstract class MembersInjectionBinding extends Binding {
create( Key key, ImmutableSet<DependencyRequest> dependencies, Optional<MembersInjectionBinding> unresolved, ImmutableSortedSet<InjectionSite> injectionSites)41   static MembersInjectionBinding create(
42       Key key,
43       ImmutableSet<DependencyRequest> dependencies,
44       Optional<MembersInjectionBinding> unresolved,
45       ImmutableSortedSet<InjectionSite> injectionSites) {
46     return new AutoValue_MembersInjectionBinding(key, dependencies, unresolved, injectionSites);
47   }
48 
49   @Override
bindingElement()50   public final Optional<XElement> bindingElement() {
51     return Optional.of(membersInjectedType());
52   }
53 
membersInjectedType()54   public final XTypeElement membersInjectedType() {
55     return key().type().xprocessing().getTypeElement();
56   }
57 
58   @Override
unresolved()59   public abstract Optional<MembersInjectionBinding> unresolved();
60 
61   @Override
contributingModule()62   public Optional<XTypeElement> contributingModule() {
63     return Optional.empty();
64   }
65 
66   /** The set of individual sites where {@link Inject} is applied. */
injectionSites()67   public abstract ImmutableSortedSet<InjectionSite> injectionSites();
68 
69   @Override
bindingType()70   public BindingType bindingType() {
71     return BindingType.MEMBERS_INJECTION;
72   }
73 
74   @Override
kind()75   public BindingKind kind() {
76     return BindingKind.MEMBERS_INJECTION;
77   }
78 
79   @Override
isNullable()80   public boolean isNullable() {
81     return false;
82   }
83 
84   /**
85    * Returns {@code true} if any of this binding's injection sites are directly on the bound type.
86    */
hasLocalInjectionSites()87   public boolean hasLocalInjectionSites() {
88     return injectionSites().stream()
89         .map(InjectionSite::enclosingTypeElement)
90         .anyMatch(membersInjectedType()::equals);
91   }
92 
93   @Override
requiresModuleInstance()94   public boolean requiresModuleInstance() {
95     return false;
96   }
97 
98   @Memoized
99   @Override
hashCode()100   public abstract int hashCode();
101 
102   // TODO(ronshapiro,dpb): simplify the equality semantics
103   @Override
equals(Object obj)104   public abstract boolean equals(Object obj);
105 
106   /** Metadata about a field or method injection site. */
107   @AutoValue
108   public abstract static class InjectionSite {
109     /** The type of injection site. */
110     public enum Kind {
111       FIELD,
112       METHOD,
113     }
114 
kind()115     public abstract Kind kind();
116 
element()117     public abstract XElement element();
118 
enclosingTypeElement()119     public abstract XTypeElement enclosingTypeElement();
120 
dependencies()121     public abstract ImmutableSet<DependencyRequest> dependencies();
122 
123     /**
124      * Returns the index of {@link #element()} in its parents {@code @Inject} members that have the
125      * same simple name. This method filters out private elements so that the results will be
126      * consistent independent of whether the build system uses header jars or not.
127      */
128     @Memoized
indexAmongAtInjectMembersWithSameSimpleName()129     public int indexAmongAtInjectMembersWithSameSimpleName() {
130       return enclosingTypeElement().getEnclosedElements().stream()
131           .filter(InjectionAnnotations::hasInjectAnnotation)
132           .filter(element -> !isPrivate(element))
133           .filter(element -> getSimpleName(element).equals(getSimpleName(this.element())))
134           .collect(toList())
135           .indexOf(element());
136     }
137 
field(XFieldElement field, DependencyRequest dependency)138     public static InjectionSite field(XFieldElement field, DependencyRequest dependency) {
139       return create(Kind.FIELD, field, ImmutableSet.of(dependency));
140     }
141 
method( XMethodElement method, Iterable<DependencyRequest> dependencies)142     public static InjectionSite method(
143         XMethodElement method, Iterable<DependencyRequest> dependencies) {
144       return create(Kind.METHOD, method, ImmutableSet.copyOf(dependencies));
145     }
146 
create( Kind kind, XElement element, ImmutableSet<DependencyRequest> dependencies)147     private static InjectionSite create(
148         Kind kind, XElement element, ImmutableSet<DependencyRequest> dependencies) {
149       XTypeElement enclosingTypeElement = checkNotNull(closestEnclosingTypeElement(element));
150       return new AutoValue_MembersInjectionBinding_InjectionSite(
151           kind, element, enclosingTypeElement, dependencies);
152     }
153   }
154 }
155