Skip to content

Commit fb8bd41

Browse files
bcorsoDagger Team
authored andcommitted
Remove a binding's associated declarations from ResolvedBindings and use BindingNode directly instead.
This CL refactors the code to remove the associated declarations from `ResolvedBindings` and have the class use `BindingNode` (which includes the associated declarations itself) instead of `Binding`. This change is subtle, but it allows us to reuse the `BindingNode` instance from an ancestor component rather than trying to recreate it with the exact same declarations in a child component (see follow-up CL/644086367). Overall, I think this refactor is also an improvement to maintainability because it cuts out the `ResolvedBindings#associatedDeclarations()` being used as a middle-man for then creating a `BindingNode` and just holds the `BindingNode`s directly. RELNOTES=N/A PiperOrigin-RevId: 649129006
1 parent d456afc commit fb8bd41

File tree

4 files changed

+120
-229
lines changed

4 files changed

+120
-229
lines changed

java/dagger/internal/codegen/binding/BindingGraphConverter.java

Lines changed: 11 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import com.google.auto.value.AutoValue;
2727
import com.google.auto.value.extension.memoized.Memoized;
2828
import com.google.common.collect.ImmutableList;
29-
import com.google.common.collect.ImmutableSet;
3029
import com.google.common.graph.ImmutableNetwork;
3130
import com.google.common.graph.MutableNetwork;
3231
import com.google.common.graph.NetworkBuilder;
@@ -44,27 +43,22 @@
4443
import dagger.internal.codegen.model.Key;
4544
import java.util.ArrayDeque;
4645
import java.util.Deque;
47-
import java.util.HashMap;
4846
import java.util.HashSet;
49-
import java.util.Map;
5047
import java.util.Set;
5148
import javax.inject.Inject;
5249

5350
/** Converts {@link BindingGraph}s to {@link dagger.internal.codegen.model.BindingGraph}s. */
5451
final class BindingGraphConverter {
55-
private final BindingDeclarationFormatter bindingDeclarationFormatter;
5652

5753
@Inject
58-
BindingGraphConverter(BindingDeclarationFormatter bindingDeclarationFormatter) {
59-
this.bindingDeclarationFormatter = bindingDeclarationFormatter;
60-
}
54+
BindingGraphConverter() {}
6155

6256
/**
6357
* Creates the external {@link dagger.internal.codegen.model.BindingGraph} representing the given
6458
* internal {@link BindingGraph}.
6559
*/
6660
BindingGraph convert(LegacyBindingGraph legacyBindingGraph, boolean isFullBindingGraph) {
67-
MutableNetwork<Node, Edge> network = asNetwork(legacyBindingGraph);
61+
MutableNetwork<Node, Edge> network = Converter.convertToNetwork(legacyBindingGraph);
6862
ComponentNode rootNode = legacyBindingGraph.componentNode();
6963

7064
// When bindings are copied down into child graphs because they transitively depend on local
@@ -81,23 +75,20 @@ BindingGraph convert(LegacyBindingGraph legacyBindingGraph, boolean isFullBindin
8175
return BindingGraph.create(rootNode, topLevelBindingGraph);
8276
}
8377

84-
private MutableNetwork<Node, Edge> asNetwork(LegacyBindingGraph graph) {
85-
Converter converter = new Converter();
86-
converter.visitRootComponent(graph);
87-
return converter.network;
88-
}
78+
private static final class Converter {
79+
static MutableNetwork<Node, Edge> convertToNetwork(LegacyBindingGraph graph) {
80+
Converter converter = new Converter();
81+
converter.visitRootComponent(graph);
82+
return converter.network;
83+
}
8984

90-
private final class Converter {
9185
/** The path from the root graph to the currently visited graph. */
9286
private final Deque<LegacyBindingGraph> bindingGraphPath = new ArrayDeque<>();
9387

9488
private final MutableNetwork<Node, Edge> network =
9589
NetworkBuilder.directed().allowsParallelEdges(true).allowsSelfLoops(true).build();
9690
private final Set<BindingNode> bindings = new HashSet<>();
9791

98-
private final Map<ResolvedBindings, ImmutableSet<BindingNode>> resolvedBindingsMap =
99-
new HashMap<>();
100-
10192
private void visitRootComponent(LegacyBindingGraph graph) {
10293
visitComponent(graph);
10394
}
@@ -128,7 +119,7 @@ private void visitComponent(LegacyBindingGraph graph) {
128119
}
129120

130121
for (ResolvedBindings resolvedBindings : graph.resolvedBindings()) {
131-
for (BindingNode binding : bindingNodes(resolvedBindings)) {
122+
for (BindingNode binding : resolvedBindings.bindingNodes()) {
132123
if (bindings.add(binding)) {
133124
network.addNode(binding);
134125
for (DependencyRequest dependencyRequest : binding.dependencies()) {
@@ -140,8 +131,7 @@ private void visitComponent(LegacyBindingGraph graph) {
140131
network.addEdge(
141132
binding,
142133
subcomponentNode(binding.key().type().xprocessing(), graph),
143-
new SubcomponentCreatorBindingEdgeImpl(
144-
resolvedBindings.subcomponentDeclarations()));
134+
new SubcomponentCreatorBindingEdgeImpl(binding.subcomponentDeclarations()));
145135
}
146136
}
147137
}
@@ -170,21 +160,6 @@ private ComponentPath componentPath() {
170160
return bindingGraphPath.getLast().componentPath();
171161
}
172162

173-
/**
174-
* Returns the subpath from the root component to the matching {@code ancestor} of the current
175-
* component.
176-
*/
177-
private ComponentPath pathFromRootToAncestor(XTypeElement ancestor) {
178-
for (LegacyBindingGraph graph : bindingGraphPath) {
179-
if (graph.componentDescriptor().typeElement().equals(ancestor)) {
180-
return graph.componentPath();
181-
}
182-
}
183-
throw new IllegalArgumentException(
184-
String.format(
185-
"%s is not in the current path: %s", ancestor.getQualifiedName(), componentPath()));
186-
}
187-
188163
/**
189164
* Returns the LegacyBindingGraph for {@code ancestor}, where {@code ancestor} is in the
190165
* component path of the current traversal.
@@ -209,7 +184,7 @@ private void addDependencyEdges(Node source, DependencyRequest dependencyRequest
209184
if (dependencies.isEmpty()) {
210185
addDependencyEdge(source, dependencyRequest, missingBindingNode(dependencies));
211186
} else {
212-
for (BindingNode dependency : bindingNodes(dependencies)) {
187+
for (BindingNode dependency : dependencies.bindingNodes()) {
213188
addDependencyEdge(source, dependencyRequest, dependency);
214189
}
215190
}
@@ -249,35 +224,6 @@ private ResolvedBindings resolvedDependencies(
249224
.resolvedBindings(bindingRequest(dependencyRequest));
250225
}
251226

252-
private ImmutableSet<BindingNode> bindingNodes(ResolvedBindings resolvedBindings) {
253-
return resolvedBindingsMap.computeIfAbsent(resolvedBindings, this::uncachedBindingNodes);
254-
}
255-
256-
private ImmutableSet<BindingNode> uncachedBindingNodes(ResolvedBindings resolvedBindings) {
257-
ImmutableSet.Builder<BindingNode> bindingNodes = ImmutableSet.builder();
258-
resolvedBindings
259-
.allBindings()
260-
.asMap()
261-
.forEach(
262-
(component, bindings) -> {
263-
for (Binding binding : bindings) {
264-
bindingNodes.add(bindingNode(resolvedBindings, binding, component));
265-
}
266-
});
267-
return bindingNodes.build();
268-
}
269-
270-
private BindingNode bindingNode(
271-
ResolvedBindings resolvedBindings, Binding binding, XTypeElement owningComponent) {
272-
return BindingNode.create(
273-
pathFromRootToAncestor(owningComponent),
274-
binding,
275-
resolvedBindings.multibindingDeclarations(),
276-
resolvedBindings.optionalBindingDeclarations(),
277-
resolvedBindings.subcomponentDeclarations(),
278-
bindingDeclarationFormatter);
279-
}
280-
281227
private MissingBinding missingBindingNode(ResolvedBindings dependencies) {
282228
// Put all missing binding nodes in the root component. This simplifies the binding graph
283229
// and produces better error messages for users since all dependents point to the same node.

java/dagger/internal/codegen/binding/BindingGraphFactory.java

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static dagger.internal.codegen.base.RequestKinds.getRequestKind;
2222
import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
2323
import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.isAssistedFactoryType;
24+
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
2425
import static dagger.internal.codegen.model.BindingKind.ASSISTED_INJECTION;
2526
import static dagger.internal.codegen.model.BindingKind.DELEGATE;
2627
import static dagger.internal.codegen.model.BindingKind.INJECTION;
@@ -35,7 +36,6 @@
3536
import com.google.common.collect.ImmutableList;
3637
import com.google.common.collect.ImmutableSet;
3738
import com.google.common.collect.Iterables;
38-
import com.google.common.collect.Multimaps;
3939
import dagger.Reusable;
4040
import dagger.internal.codegen.base.ClearableCache;
4141
import dagger.internal.codegen.base.ContributionType;
@@ -73,6 +73,7 @@ public final class BindingGraphFactory implements ClearableCache {
7373
private final InjectBindingRegistry injectBindingRegistry;
7474
private final KeyFactory keyFactory;
7575
private final BindingFactory bindingFactory;
76+
private final BindingNode.Factory bindingNodeFactory;
7677
private final ComponentDeclarations.Factory componentDeclarationsFactory;
7778
private final BindingGraphConverter bindingGraphConverter;
7879
private final Map<Key, ImmutableSet<Key>> keysMatchingRequestCache = new HashMap<>();
@@ -83,12 +84,14 @@ public final class BindingGraphFactory implements ClearableCache {
8384
InjectBindingRegistry injectBindingRegistry,
8485
KeyFactory keyFactory,
8586
BindingFactory bindingFactory,
87+
BindingNode.Factory bindingNodeFactory,
8688
ComponentDeclarations.Factory componentDeclarationsFactory,
8789
BindingGraphConverter bindingGraphConverter,
8890
CompilerOptions compilerOptions) {
8991
this.injectBindingRegistry = injectBindingRegistry;
9092
this.keyFactory = keyFactory;
9193
this.bindingFactory = bindingFactory;
94+
this.bindingNodeFactory = bindingNodeFactory;
9295
this.componentDeclarationsFactory = componentDeclarationsFactory;
9396
this.bindingGraphConverter = bindingGraphConverter;
9497
this.compilerOptions = compilerOptions;
@@ -341,13 +344,18 @@ && isAssistedFactoryType(requestKey.type().xprocessing().getTypeElement())) {
341344
.ifPresent(bindings::add);
342345
}
343346

344-
return ResolvedBindings.forContributionBindings(
345-
componentPath,
347+
return ResolvedBindings.create(
346348
requestKey,
347-
Multimaps.index(bindings, binding -> getOwningComponent(requestKey, binding)),
348-
multibindingDeclarations,
349-
subcomponentDeclarations,
350-
optionalBindingDeclarations);
349+
bindings.stream()
350+
.map(
351+
binding ->
352+
bindingNodeFactory.forContributionBindings(
353+
getOwningComponentPath(requestKey, binding),
354+
binding,
355+
multibindingDeclarations,
356+
optionalBindingDeclarations,
357+
subcomponentDeclarations))
358+
.collect(toImmutableSet()));
351359
}
352360

353361
/**
@@ -380,9 +388,10 @@ ResolvedBindings lookUpMembersInjectionBinding(Key requestKey) {
380388
Optional<MembersInjectionBinding> binding =
381389
injectBindingRegistry.getOrFindMembersInjectionBinding(requestKey);
382390
return binding.isPresent()
383-
? ResolvedBindings.forMembersInjectionBinding(
384-
componentPath, requestKey, componentDescriptor, binding.get())
385-
: ResolvedBindings.noBindings(componentPath, requestKey);
391+
? ResolvedBindings.create(
392+
requestKey,
393+
bindingNodeFactory.forMembersInjectionBinding(componentPath, binding.get()))
394+
: ResolvedBindings.create(requestKey);
386395
}
387396

388397
/**
@@ -462,7 +471,7 @@ private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDe
462471
} finally {
463472
cycleStack.pop();
464473
}
465-
if (resolvedDelegate.contributionBindings().isEmpty()) {
474+
if (resolvedDelegate.bindings().isEmpty()) {
466475
// This is guaranteed to result in a missing binding error, so it doesn't matter if the
467476
// binding is a Provision or Production, except if it is a @IntoMap method, in which
468477
// case the key will be of type Map<K, Provider<V>>, which will be "upgraded" into a
@@ -477,7 +486,7 @@ private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDe
477486
// It doesn't matter which of these is selected, since they will later on produce a
478487
// duplicate binding error.
479488
ContributionBinding explicitDelegate =
480-
resolvedDelegate.contributionBindings().iterator().next();
489+
(ContributionBinding) resolvedDelegate.bindings().iterator().next();
481490
return bindingFactory.delegateBinding(delegateDeclaration, explicitDelegate);
482491
}
483492

@@ -491,13 +500,13 @@ private ContributionBinding createDelegateBinding(DelegateDeclaration delegateDe
491500
* multibinding contributions in the parent, and returns the parent-resolved {@link
492501
* ResolvedBindings#owningComponent(ContributionBinding)}.
493502
*/
494-
private XTypeElement getOwningComponent(Key requestKey, ContributionBinding binding) {
503+
private ComponentPath getOwningComponentPath(Key requestKey, ContributionBinding binding) {
495504
if (isResolvedInParent(requestKey, binding) && !requiresResolution(binding)) {
496505
ResolvedBindings parentResolvedBindings =
497506
parentResolver.get().resolvedContributionBindings.get(requestKey);
498-
return parentResolvedBindings.owningComponent(binding);
507+
return parentResolvedBindings.forBinding(binding).componentPath();
499508
} else {
500-
return componentDescriptor.typeElement();
509+
return componentPath;
501510
}
502511
}
503512

@@ -540,8 +549,7 @@ private Optional<Resolver> getOwningResolver(ContributionBinding binding) {
540549
// If a @Reusable binding was resolved in an ancestor, use that component.
541550
ResolvedBindings resolvedBindings =
542551
requestResolver.resolvedContributionBindings.get(binding.key());
543-
if (resolvedBindings != null
544-
&& resolvedBindings.contributionBindings().contains(binding)) {
552+
if (resolvedBindings != null && resolvedBindings.bindings().contains(binding)) {
545553
return Optional.of(requestResolver);
546554
}
547555
}
@@ -740,7 +748,7 @@ && getLocalExplicitBindings(key).isEmpty()) {
740748
* component.
741749
*/
742750
private void resolveDependencies(ResolvedBindings resolvedBindings) {
743-
for (Binding binding : resolvedBindings.bindingsOwnedBy(componentDescriptor)) {
751+
for (BindingNode binding : resolvedBindings.bindingNodesOwnedBy(componentPath)) {
744752
for (DependencyRequest dependency : binding.dependencies()) {
745753
resolve(dependency.key());
746754
}
@@ -870,13 +878,13 @@ private boolean hasLocalMultibindingContributions(Key requestKey) {
870878
*/
871879
private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
872880
return hasLocalOptionalBindingContribution(
873-
resolvedBindings.key(), resolvedBindings.contributionBindings());
881+
resolvedBindings.key(), resolvedBindings.bindings());
874882
}
875883

876884
private boolean hasLocalOptionalBindingContribution(
877-
Key key, ImmutableSet<ContributionBinding> previousContributionBindings) {
878-
if (previousContributionBindings.stream()
879-
.map(ContributionBinding::kind)
885+
Key key, ImmutableSet<? extends Binding> previouslyResolvedBindings) {
886+
if (previouslyResolvedBindings.stream()
887+
.map(Binding::kind)
880888
.anyMatch(isEqual(OPTIONAL))) {
881889
return !getLocalExplicitBindings(keyFactory.unwrapOptional(key).get())
882890
.isEmpty();

0 commit comments

Comments
 (0)