private DependencyEdge chooseDependencyEdgeConnecting( Node source, Node target, BindingGraph bindingGraph) { return bindingGraph.network().edgesConnecting(source, target).stream() .flatMap(instancesOf(DependencyEdge.class)) .findFirst() .get(); }
/** Returns the dependencies on {@code binding}. */ // TODO(dpb): Move to BindingGraph. private Stream<DependencyEdge> incomingDependencies( dagger.model.Binding binding, BindingGraph bindingGraph) { return bindingGraph.network().inEdges(binding).stream() .flatMap(instancesOf(DependencyEdge.class)); }
private boolean allIncomingDependenciesCanUseProduction( MissingBinding missingBinding, BindingGraph graph) { return graph.network().inEdges(missingBinding).stream() .flatMap(instancesOf(DependencyEdge.class)) .allMatch(edge -> dependencyCanBeProduction(edge, graph)); }
/** * Returns one of the edges between two nodes that doesn't {@linkplain * #breaksCycle(DependencyEdge, BindingGraph) break} a cycle. */ private DependencyEdge nonCycleBreakingEdge(EndpointPair<Node> endpointPair, BindingGraph graph) { return graph.network().edgesConnecting(endpointPair.source(), endpointPair.target()).stream() .flatMap(instancesOf(DependencyEdge.class)) .filter(edge -> !breaksCycle(edge, graph)) .findFirst() .get(); }
ImmutableList<Node> shortestPathFromEntryPoint( DependencyEdge entryPoint, MaybeBinding binding) { return shortestPaths .row(binding) .computeIfAbsent( entryPoint, ep -> shortestPath( node -> filter( graph.network().successors(node), MaybeBinding.class::isInstance), graph.network().incidentNodes(ep).target(), binding)); }
private ImmutableSet<DependencyEdge> nonNullableDependencies( BindingGraph bindingGraph, dagger.model.Binding binding) { return bindingGraph.network().inEdges(binding).stream() .flatMap(instancesOf(DependencyEdge.class)) .filter(edge -> !edge.dependencyRequest().isNullable()) .collect(toImmutableSet()); }
private Node source(Edge edge) { return graph.network().incidentNodes(edge).source(); }
/** Returns all the nonsynthetic dependency requests for a binding. */ ImmutableSet<DependencyEdge> requests(MaybeBinding binding) { return graph.network().inEdges(binding).stream() .flatMap(instancesOf(DependencyEdge.class)) .filter(edge -> edge.dependencyRequest().requestElement().isPresent()) .sorted(requestEnclosingTypeName().thenComparing(requestElementDeclarationOrder())) .collect(toImmutableSet()); }
private void reportMissingModuleParameters( ChildFactoryMethodEdge edge, ImmutableSet<TypeElement> missingModules, BindingGraph graph, DiagnosticReporter diagnosticReporter) { diagnosticReporter.reportSubcomponentFactoryMethod( ERROR, edge, "%s requires modules which have no visible default constructors. " + "Add the following modules as parameters to this method: %s", graph .network() .incidentNodes(edge) .target() .componentPath() .currentComponent() .getQualifiedName(), Joiner.on(", ").join(missingModules)); } }
private ImmutableList<Node> shortestPathToCycleFromAnEntryPoint( Cycle<Node> cycle, BindingGraph bindingGraph) { Node someCycleNode = cycle.nodes().asList().get(0); ComponentNode componentContainingCycle = bindingGraph.componentNode(someCycleNode.componentPath()).get(); ImmutableList<Node> pathToCycle = shortestPath(bindingGraph.network(), componentContainingCycle, someCycleNode); return subpathToCycle(pathToCycle, cycle); }
/** * Returns the binding that requests a dependency. * * @throws IllegalArgumentException if {@code dependency} is an {@linkplain * DependencyEdge#isEntryPoint() entry point}. */ // TODO(dpb): Move to BindingGraph. private dagger.model.Binding bindingRequestingDependency( DependencyEdge dependency, BindingGraph bindingGraph) { checkArgument(!dependency.isEntryPoint()); Node source = bindingGraph.network().incidentNodes(dependency).source(); verify( source instanceof dagger.model.Binding, "expected source of %s to be a binding, but was: %s", dependency, source); return (dagger.model.Binding) source; }
private ImmutableSet<TypeElement> findMissingModules( ChildFactoryMethodEdge edge, BindingGraph graph) { ImmutableSet<TypeElement> factoryMethodParameters = subgraphFactoryMethodParameters(edge, graph); ComponentNode child = (ComponentNode) graph.network().incidentNodes(edge).target(); SetView<TypeElement> modulesOwnedByChild = ownedModules(child, graph); return graph.bindings().stream() // bindings owned by child .filter(binding -> binding.componentPath().equals(child.componentPath())) // that require a module instance .filter(binding -> binding.requiresModuleInstance()) .map(binding -> binding.contributingModule().get()) .distinct() // module owned by child .filter(module -> modulesOwnedByChild.contains(module)) // module not in the method parameters .filter(module -> !factoryMethodParameters.contains(module)) // module doesn't have an accessible no-arg constructor .filter(moduleType -> !componentCanMakeNewInstances(moduleType)) .collect(toImmutableSet()); }
Set<Edge> dependenciesBetween = graph .network() .edgesConnecting(shortestBindingPath.get(i), shortestBindingPath.get(i + 1));
/** Returns the subgraph containing only {@link DependencyEdge}s that would not break a cycle. */ // TODO(dpb): Return a network containing only Binding nodes. private ImmutableNetwork<Node, DependencyEdge> nonCycleBreakingDependencyGraph( BindingGraph bindingGraph) { MutableNetwork<Node, DependencyEdge> dependencyNetwork = NetworkBuilder.from(bindingGraph.network()) .expectedNodeCount(bindingGraph.network().nodes().size()) .expectedEdgeCount(bindingGraph.dependencyEdges().size()) .build(); bindingGraph.dependencyEdges().stream() .filter(edge -> !breaksCycle(edge, bindingGraph)) .forEach( edge -> { EndpointPair<Node> endpoints = bindingGraph.network().incidentNodes(edge); dependencyNetwork.addEdge(endpoints.source(), endpoints.target(), edge); }); return ImmutableNetwork.copyOf(dependencyNetwork); }
@Override public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) { if (bindingGraph.isModuleBindingGraph() || bindingGraph.isPartialBindingGraph()) { // We don't know all the modules that might be owned by the child until we know the root. return; } bindingGraph.network().edges().stream() .flatMap(instancesOf(ChildFactoryMethodEdge.class)) .forEach( edge -> { ImmutableSet<TypeElement> missingModules = findMissingModules(edge, bindingGraph); if (!missingModules.isEmpty()) { reportMissingModuleParameters( edge, missingModules, bindingGraph, diagnosticReporter); } }); }
@Override public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) { if (!compilerOptions.usesProducers()) { return; } Key productionImplementationExecutorKey = keyFactory.forProductionImplementationExecutor(); Key productionExecutorKey = keyFactory.forProductionExecutor(); bindingGraph.network().nodes().stream() .flatMap(instancesOf(MaybeBinding.class)) .filter(node -> node.key().equals(productionExecutorKey)) .flatMap(productionExecutor -> bindingGraph.requestingBindings(productionExecutor).stream()) .filter(binding -> !binding.key().equals(productionImplementationExecutorKey)) .forEach(binding -> reportError(diagnosticReporter, binding)); }
private boolean dependencyCanBeProduction(DependencyEdge edge, BindingGraph graph) { Node source = graph.network().incidentNodes(edge).source(); if (source instanceof ComponentNode) { return entryPointCanUseProduction(edge.dependencyRequest().kind()); } if (source instanceof dagger.model.Binding) { return ((dagger.model.Binding) source).isProduction(); } throw new IllegalArgumentException( "expected a dagger.model.Binding or ComponentNode: " + source); }
private ImmutableSet<TypeElement> subgraphFactoryMethodParameters( ChildFactoryMethodEdge edge, BindingGraph bindingGraph) { ComponentNode parent = (ComponentNode) bindingGraph.network().incidentNodes(edge).source(); DeclaredType parentType = asDeclared(parent.componentPath().currentComponent().asType()); ExecutableType factoryMethodType = asExecutable(types.asMemberOf(parentType, edge.factoryMethod())); return asTypeElements(factoryMethodType.getParameterTypes()); }
private boolean breaksCycle(DependencyEdge edge, BindingGraph graph) { if (edge.dependencyRequest().key().multibindingContributionIdentifier().isPresent()) { return false; } if (breaksCycle(edge.dependencyRequest().key().type(), edge.dependencyRequest().kind())) { return true; } Node target = graph.network().incidentNodes(edge).target(); if (target instanceof dagger.model.Binding && ((dagger.model.Binding) target).kind().equals(BindingKind.OPTIONAL)) { /* For @BindsOptionalOf bindings, unwrap the type inside the Optional. If the unwrapped type * breaks the cycle, so does the optional binding. */ TypeMirror optionalValueType = OptionalType.from(edge.dependencyRequest().key()).valueType(); RequestKind requestKind = getRequestKind(optionalValueType); return breaksCycle(extractKeyType(requestKind, optionalValueType), requestKind); } return false; }