|  | // Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  | package com.android.tools.r8.shaking; | 
|  |  | 
|  | import com.android.tools.r8.experimental.graphinfo.GraphConsumer; | 
|  | import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo; | 
|  | import com.android.tools.r8.experimental.graphinfo.GraphNode; | 
|  | import java.util.HashMap; | 
|  | import java.util.HashSet; | 
|  | import java.util.Map; | 
|  | import java.util.Set; | 
|  |  | 
|  | /** Base implementation of a graph consumer that collects all of graph nodes and edges. */ | 
|  | public class CollectingGraphConsumer implements GraphConsumer { | 
|  |  | 
|  | // Possible sub-consumer that is also inspecting the kept-graph. | 
|  | private final GraphConsumer subConsumer; | 
|  |  | 
|  | // Directional map backwards from targets to direct sources. | 
|  | private final Map<GraphNode, Map<GraphNode, Set<GraphEdgeInfo>>> target2sources = new HashMap<>(); | 
|  |  | 
|  | public CollectingGraphConsumer(GraphConsumer subConsumer) { | 
|  | this.subConsumer = subConsumer; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public void acceptEdge(GraphNode source, GraphNode target, GraphEdgeInfo info) { | 
|  | target2sources | 
|  | .computeIfAbsent(target, k -> new HashMap<>()) | 
|  | .computeIfAbsent(source, k -> new HashSet<>()) | 
|  | .add(info); | 
|  | if (subConsumer != null) { | 
|  | subConsumer.acceptEdge(source, target, info); | 
|  | } | 
|  | } | 
|  |  | 
|  | public Set<GraphNode> getTargets() { | 
|  | return target2sources.keySet(); | 
|  | } | 
|  |  | 
|  | public Map<GraphNode, Set<GraphEdgeInfo>> getSourcesTargeting(GraphNode target) { | 
|  | return target2sources.get(target); | 
|  | } | 
|  | } |