/* * Copyright (C) 2014 The Dagger Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package dagger.internal.codegen.binding; import static com.google.common.base.Preconditions.checkNotNull; import static dagger.internal.codegen.xprocessing.XElements.closestEnclosingTypeElement; import static dagger.internal.codegen.xprocessing.XElements.getSimpleName; import static dagger.internal.codegen.xprocessing.XElements.isPrivate; import static java.util.stream.Collectors.toList; import androidx.room.compiler.processing.XElement; import androidx.room.compiler.processing.XFieldElement; import androidx.room.compiler.processing.XMethodElement; import androidx.room.compiler.processing.XTypeElement; import com.google.auto.value.AutoValue; import com.google.auto.value.extension.memoized.Memoized; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import dagger.internal.codegen.model.BindingKind; import dagger.internal.codegen.model.DependencyRequest; import dagger.internal.codegen.model.Key; import java.util.Optional; /** Represents the full members injection of a particular type. */ @AutoValue public abstract class MembersInjectionBinding extends Binding { static MembersInjectionBinding create( Key key, ImmutableSet dependencies, Optional unresolved, ImmutableSortedSet injectionSites) { return new AutoValue_MembersInjectionBinding(key, dependencies, unresolved, injectionSites); } @Override public final Optional bindingElement() { return Optional.of(membersInjectedType()); } public final XTypeElement membersInjectedType() { return key().type().xprocessing().getTypeElement(); } @Override public abstract Optional unresolved(); @Override public Optional contributingModule() { return Optional.empty(); } /** The set of individual sites where {@link Inject} is applied. */ public abstract ImmutableSortedSet injectionSites(); @Override public BindingType bindingType() { return BindingType.MEMBERS_INJECTION; } @Override public BindingKind kind() { return BindingKind.MEMBERS_INJECTION; } @Override public boolean isNullable() { return false; } /** * Returns {@code true} if any of this binding's injection sites are directly on the bound type. */ public boolean hasLocalInjectionSites() { return injectionSites().stream() .map(InjectionSite::enclosingTypeElement) .anyMatch(membersInjectedType()::equals); } @Override public boolean requiresModuleInstance() { return false; } @Memoized @Override public abstract int hashCode(); // TODO(ronshapiro,dpb): simplify the equality semantics @Override public abstract boolean equals(Object obj); /** Metadata about a field or method injection site. */ @AutoValue public abstract static class InjectionSite { /** The type of injection site. */ public enum Kind { FIELD, METHOD, } public abstract Kind kind(); public abstract XElement element(); public abstract XTypeElement enclosingTypeElement(); public abstract ImmutableSet dependencies(); /** * Returns the index of {@link #element()} in its parents {@code @Inject} members that have the * same simple name. This method filters out private elements so that the results will be * consistent independent of whether the build system uses header jars or not. */ @Memoized public int indexAmongAtInjectMembersWithSameSimpleName() { return enclosingTypeElement().getEnclosedElements().stream() .filter(InjectionAnnotations::hasInjectAnnotation) .filter(element -> !isPrivate(element)) .filter(element -> getSimpleName(element).equals(getSimpleName(this.element()))) .collect(toList()) .indexOf(element()); } public static InjectionSite field(XFieldElement field, DependencyRequest dependency) { return create(Kind.FIELD, field, ImmutableSet.of(dependency)); } public static InjectionSite method( XMethodElement method, Iterable dependencies) { return create(Kind.METHOD, method, ImmutableSet.copyOf(dependencies)); } private static InjectionSite create( Kind kind, XElement element, ImmutableSet dependencies) { XTypeElement enclosingTypeElement = checkNotNull(closestEnclosingTypeElement(element)); return new AutoValue_MembersInjectionBinding_InjectionSite( kind, element, enclosingTypeElement, dependencies); } } }