Skip to content

Commit

Permalink
Internal changes
Browse files Browse the repository at this point in the history
RELNOTES=N/A
PiperOrigin-RevId: 588861836
  • Loading branch information
bcorso authored and Dagger Team committed Dec 7, 2023
1 parent eb9a034 commit f4b4519
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 38 deletions.
7 changes: 4 additions & 3 deletions java/dagger/internal/codegen/base/TarjanSCCs.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static java.lang.Math.min;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
Expand All @@ -39,7 +40,7 @@
public final class TarjanSCCs {

/** Returns the set of strongly connected components in reverse topological order. */
public static <NodeT> ImmutableSet<ImmutableSet<NodeT>> compute(
public static <NodeT> ImmutableList<ImmutableSet<NodeT>> compute(
ImmutableCollection<NodeT> nodes, SuccessorsFunction<NodeT> successorsFunction) {
return new TarjanSCC<>(nodes, successorsFunction).compute();
}
Expand All @@ -62,14 +63,14 @@ private static class TarjanSCC<NodeT> {
this.lowLinks = Maps.newHashMapWithExpectedSize(nodes.size());
}

private ImmutableSet<ImmutableSet<NodeT>> compute() {
private ImmutableList<ImmutableSet<NodeT>> compute() {
checkState(indexes.isEmpty(), "TarjanSCC#compute() can only be called once per instance!");
for (NodeT node : nodes) {
if (!indexes.containsKey(node)) {
stronglyConnect(node);
}
}
return ImmutableSet.copyOf(stronglyConnectedComponents);
return ImmutableList.copyOf(stronglyConnectedComponents);
}

private void stronglyConnect(NodeT node) {
Expand Down
2 changes: 1 addition & 1 deletion java/dagger/internal/codegen/binding/BindingGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Comparator<Node> nodeOrder() {

/** Returns the set of strongly connected nodes in this graph in reverse topological order. */
@Memoized
public ImmutableSet<ImmutableSet<Node>> stronglyConnectedNodes() {
public ImmutableList<ImmutableSet<Node>> stronglyConnectedNodes() {
return TarjanSCCs.<Node>compute(
ImmutableSet.copyOf(network().nodes()),
// NetworkBuilder does not have a stable successor order, so we have to roll our own
Expand Down
88 changes: 54 additions & 34 deletions java/dagger/internal/codegen/binding/BindingGraphFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -648,8 +648,7 @@ private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDe
* ResolvedBindings#owningComponent(ContributionBinding)}.
*/
private XTypeElement getOwningComponent(Key requestKey, ContributionBinding binding) {
if (isResolvedInParent(requestKey, binding)
&& !new RequiresResolutionChecker().requiresResolution(binding)) {
if (isResolvedInParent(requestKey, binding) && !requiresResolution(binding)) {
ResolvedBindings parentResolvedBindings =
parentResolver.get().resolvedContributionBindings.get(requestKey);
return parentResolvedBindings.owningComponent(binding);
Expand Down Expand Up @@ -876,7 +875,7 @@ void resolve(Key key) {
previouslyResolvedBindings.bindings().stream()
.anyMatch(binding -> binding.kind() == BindingKind.ASSISTED_INJECTION);
if (!isAssistedInjectionBinding
&& !new RequiresResolutionChecker().requiresResolution(key)
&& !requiresResolution(key)
&& getLocalExplicitBindings(key).isEmpty()) {
/* Cache the inherited parent component's bindings in case resolving at the parent found
* bindings in some component between this one and the previously-resolved one. */
Expand Down Expand Up @@ -921,7 +920,15 @@ private ResolvedBindings getResolvedMembersInjectionBindings(Key key) {
return resolvedMembersInjectionBindings.get(key);
}

private final class RequiresResolutionChecker {
private boolean requiresResolution(Key key) {
return new LegacyRequiresResolutionChecker().requiresResolution(key);
}

private boolean requiresResolution(Binding binding) {
return new LegacyRequiresResolutionChecker().requiresResolution(binding);
}

private final class LegacyRequiresResolutionChecker {
private final Set<Object> cycleChecker = new HashSet<>();

/**
Expand Down Expand Up @@ -969,9 +976,7 @@ private boolean requiresResolutionUncached(Key key) {
Resolver.this,
key);
ResolvedBindings previouslyResolvedBindings = getPreviouslyResolvedBindings(key).get();
if (hasLocalMultibindingContributions(key)
|| hasLocalOptionalBindingContribution(previouslyResolvedBindings)
) {
if (hasLocalBindings(previouslyResolvedBindings)) {
return true;
}

Expand All @@ -995,35 +1000,50 @@ private boolean requiresResolutionUncached(Binding binding) {
}
return false;
}
}

/**
* Returns {@code true} if there is at least one multibinding contribution declared within
* this component's modules that matches the key.
*/
private boolean hasLocalMultibindingContributions(Key requestKey) {
return keysMatchingRequest(requestKey)
.stream()
.anyMatch(key -> !getLocalExplicitMultibindings(key).isEmpty());
}
private boolean hasLocalBindings(Binding binding) {
return hasLocalMultibindingContributions(binding.key())
|| hasLocalOptionalBindingContribution(
binding.key(), ImmutableSet.of((ContributionBinding) binding));
}

/**
* Returns {@code true} if there is a contribution in this component for an {@code
* Optional<Foo>} key that has not been contributed in a parent.
*/
private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
if (resolvedBindings
.contributionBindings()
.stream()
.map(ContributionBinding::kind)
.anyMatch(isEqual(OPTIONAL))) {
return !getLocalExplicitBindings(keyFactory.unwrapOptional(resolvedBindings.key()).get())
.isEmpty();
} else {
// If a parent contributes a @Provides Optional<Foo> binding and a child has a
// @BindsOptionalOf Foo method, the two should conflict, even if there is no binding for
// Foo on its own
return !getOptionalBindingDeclarations(resolvedBindings.key()).isEmpty();
}
private boolean hasLocalBindings(ResolvedBindings resolvedBindings) {
return hasLocalMultibindingContributions(resolvedBindings.key())
|| hasLocalOptionalBindingContribution(resolvedBindings);
}

/**
* Returns {@code true} if there is at least one multibinding contribution declared within
* this component's modules that matches the key.
*/
private boolean hasLocalMultibindingContributions(Key requestKey) {
return keysMatchingRequest(requestKey)
.stream()
.anyMatch(key -> !getLocalExplicitMultibindings(key).isEmpty());
}

/**
* Returns {@code true} if there is a contribution in this component for an {@code
* Optional<Foo>} key that has not been contributed in a parent.
*/
private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
return hasLocalOptionalBindingContribution(
resolvedBindings.key(), resolvedBindings.contributionBindings());
}

private boolean hasLocalOptionalBindingContribution(
Key key, ImmutableSet<ContributionBinding> previousContributionBindings) {
if (previousContributionBindings.stream()
.map(ContributionBinding::kind)
.anyMatch(isEqual(OPTIONAL))) {
return !getLocalExplicitBindings(keyFactory.unwrapOptional(key).get())
.isEmpty();
} else {
// If a parent contributes a @Provides Optional<Foo> binding and a child has a
// @BindsOptionalOf Foo method, the two should conflict, even if there is no binding for
// Foo on its own
return !getOptionalBindingDeclarations(key).isEmpty();
}
}
}
Expand Down

0 comments on commit f4b4519

Please sign in to comment.